117
IPGEN: UN FRAMEWORK PER LA GENERAZIONE AUTOMATICA DI IP-CORE PER FPGA 12 ottobre 2006

IPGEN: UN FRAMEWORK PER LA GENERAZIONE … · 2007-10-01 · Love is the dance of Eternity. (Dream Theater) Matteo I know someday you’ll have a beautiful life, I know you’ll be

  • Upload
    doquynh

  • View
    219

  • Download
    0

Embed Size (px)

Citation preview

IPGEN: UN FRAMEWORK PER LA

GENERAZIONE AUTOMATICA DI

IP-CORE PER FPGA

12 ottobre 2006

POLITECNICO DI MILANO

FACOLTÀ DI INGEGNERIA

CORSO DI LAUREA IN INGEGNERIA INFORMATICA

IPGEN: UN FRAMEWORK PER LA GENERAZIONEAUTOMATICA DI IP-CORE PER FPGA

Relatore: Prof. Donatella SCIUTO

Correlatore: Ing. Marco Domenico SANTAMBROGIO

Tesi di Laurea di:

Matteo MurgidaMatricola n. 662247

Alessandro PanellaMatricola n. 661986

ANNO ACCADEMICO 2005-2006

Love is the dance of Eternity. (Dream Theater)

Matteo

I know someday you’ll have a beautiful life,

I know you’ll be a star... (Pearl Jam)

Alessandro

Indice

Riassunto 3

1 Premesse 7

1.1 Scenario operativo . . . . . . . . . . . . . . . . . . . . . . . . . 7

1.1.1 Progettazione modulare dello hardware . . . . . . . . . . 8

1.1.2 IP-Core . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

1.1.2.1 Definizione . . . . . . . . . . . . . . . . . . . 9

1.1.2.2 Dal core all’IP-Core . . . . . . . . . . . . . . . 10

1.1.3 Sistemi riconfigurabili . . . . . . . . . . . . . . . . . . . 12

1.1.4 Riconfigurabilità dinamica parziale: il flusso di Caronte . 13

1.1.4.1 Architettura hardware di Caronte . . . . . . . . 16

1.1.4.2 Da Caronte a YaRA . . . . . . . . . . . . . . . 17

1.2 Strumenti utilizzati . . . . . . . . . . . . . . . . . . . . . . . . . 20

1.2.1 Xilinx EDK . . . . . . . . . . . . . . . . . . . . . . . . 20

1.2.2 Xilinx ISE . . . . . . . . . . . . . . . . . . . . . . . . . 21

1.2.3 MentorGraphics ModelSim . . . . . . . . . . . . . . . . 23

2 Approcci precedenti 27

2.1 OCP Socket e CoreCreator . . . . . . . . . . . . . . . . . . . . . 27

2.2 Interface Adaptor Logic . . . . . . . . . . . . . . . . . . . . . . . 29

2.3 EDK Create/Import Peripheral Wizard . . . . . . . . . . . . . . . 30

2.4 ImpulseC CoDeveloper . . . . . . . . . . . . . . . . . . . . . . . 31

2.5 Conclusioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

v

3 Infrastrutture di comunicazione 333.1 IBM CoreConnect OPB . . . . . . . . . . . . . . . . . . . . . . . 34

3.1.1 OPB PSelect . . . . . . . . . . . . . . . . . . . . . . . . 37

3.1.2 OPB IPIF . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3.1.2.1 I Servizi . . . . . . . . . . . . . . . . . . . . . 40

3.1.2.2 Decodifica degli indirizzi . . . . . . . . . . . . 41

3.1.2.3 IPIC . . . . . . . . . . . . . . . . . . . . . . . 42

3.1.2.4 Modalità di utilizzo . . . . . . . . . . . . . . . 44

3.2 Wishbone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

3.2.1 Le interfacce . . . . . . . . . . . . . . . . . . . . . . . . 45

3.2.2 Protocollo di comunicazione . . . . . . . . . . . . . . . . 47

3.2.3 Tipi di connessione . . . . . . . . . . . . . . . . . . . . . 48

4 Metodologia 514.1 Motivazioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

4.1.1 IPGen nel flusso di Caronte . . . . . . . . . . . . . . . . 52

4.2 Struttura dell’IP-Core generato . . . . . . . . . . . . . . . . . . . 53

4.2.1 Core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

4.2.2 Stub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

4.2.3 IP-Core . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

4.3 Workflow di IPGen . . . . . . . . . . . . . . . . . . . . . . . . . 57

4.3.1 Lettura . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

4.3.2 Scrittura . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

4.4 Confronti con gli altri approcci . . . . . . . . . . . . . . . . . . . 59

5 Implementazione 655.1 Struttura del programma . . . . . . . . . . . . . . . . . . . . . . 65

5.2 Utilizzo e funzionamento del framework . . . . . . . . . . . . . . 69

5.2.1 Inizializzazione . . . . . . . . . . . . . . . . . . . . . . . 70

5.2.2 Fase di lettura . . . . . . . . . . . . . . . . . . . . . . . . 70

5.2.3 Scelta dell’interfaccia e fase di scrittura . . . . . . . . . . 71

5.2.4 Terminazione . . . . . . . . . . . . . . . . . . . . . . . . 75

5.3 Caratteristiche delle descrizioni VHDL generate . . . . . . . . . . 75

5.3.1 Visione d’insieme . . . . . . . . . . . . . . . . . . . . . . 75

5.3.2 Istanziazione dei componenti e mappaggio delle porte . . 78

5.3.3 Processi di lettura e scrittura . . . . . . . . . . . . . . . . 79

5.3.4 Gestione dei generic . . . . . . . . . . . . . . . . . . . . 81

5.3.5 Gestione di porte con dimensione maggiore di 32 bit . . . 83

5.4 Come scrivere un core interfacciabile automaticamente . . . . . . 85

5.4.1 Requisiti concettuali . . . . . . . . . . . . . . . . . . . . 86

5.4.2 Requisiti pratici . . . . . . . . . . . . . . . . . . . . . . . 87

6 Risultati sperimentali 896.1 Test di prestazione . . . . . . . . . . . . . . . . . . . . . . . . . 89

6.2 Test di funzionamento . . . . . . . . . . . . . . . . . . . . . . . . 95

7 Conclusione e sviluppi futuri 99

Bibliografia 101

Ringraziamenti 103

Elenco delle figure

1.1 Struttura di un IP-Core . . . . . . . . . . . . . . . . . . . . . . . 11

1.2 Il flusso di lavoro di Caronte . . . . . . . . . . . . . . . . . . . . 15

1.3 L’architettura hardware di Caronte . . . . . . . . . . . . . . . . . 17

1.4 Collegamento tra un modulo fisso e uno riconfigurabile nell’ar-

chitettura di Caronte . . . . . . . . . . . . . . . . . . . . . . . . 18

1.5 L’architettura di YaRA . . . . . . . . . . . . . . . . . . . . . . . 19

1.6 Workspace di Project Navigator . . . . . . . . . . . . . . . . . . 22

1.7 Workspace di ModelSim. . . . . . . . . . . . . . . . . . . . . . . 24

2.1 Schema dell’IP-Core secondo l’approccio OCP . . . . . . . . . . 29

3.1 Set di segnali visti all’interfaccia con un componente slave . . . . 35

3.2 Schema dei servizi e dei segnali IPIF . . . . . . . . . . . . . . . . 39

3.3 Le interfacce Wishbone lato master e lato slave . . . . . . . . . . 45

3.4 Schema della connessione “Data Flow” . . . . . . . . . . . . . . 48

3.5 Schema della connessione “Shared Bus Interconnection” . . . . . 49

3.6 Schema della connessione “Crossbar Interconnection” . . . . . . 50

4.1 Flusso di creazione delle HW-SSP . . . . . . . . . . . . . . . . . 54

4.2 Struttura di un core interfacciato con OPB . . . . . . . . . . . . . 55

4.3 Struttura di un core interfacciato con Wishbone . . . . . . . . . . 55

4.4 Flusso operativo del reader . . . . . . . . . . . . . . . . . . . . . 58

4.5 Flusso operativo del writer . . . . . . . . . . . . . . . . . . . . . 59

4.6 Confronto degli IP-Core risultanti utilizzando differenti approcci . 61

ix

5.1 Class diagram di IPGen . . . . . . . . . . . . . . . . . . . . . . . 66

5.2 Esempio dell’output video di IPGen . . . . . . . . . . . . . . . . 72

5.3 Flusso di creazione dei file in uscita . . . . . . . . . . . . . . . . 74

5.4 Sequence diagram dell’esecuzione di IPGen . . . . . . . . . . . . 76

5.5 Diverse strutture di file generati . . . . . . . . . . . . . . . . . . . 78

5.6 Dichiarazione e istanziazione del core di un addizionatore binario

a 32 bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

5.7 Esempio di processo di lettura dei registri . . . . . . . . . . . . . 81

5.8 Esempio di processo di scrittura dei registri . . . . . . . . . . . . 82

5.9 Processo di lettura per un core avente una uscita da 128 bit . . . . 83

5.10 Processo di scrittura per un core avente un ingresso da 96 bit . . . 85

6.1 Occupazione percentuale di overhead introdotto da IPGen . . . . . 92

6.2 Occupazione dello stub generato per i “dummy core” . . . . . . . 94

6.3 Simulazione di un IP-Core con interfaccia PSelect . . . . . . . . . 95

6.4 Simulazione di un IP-Core con interfaccia OPB IPIF . . . . . . . 96

6.5 Simulazione di un IP-Core con interfaccia Wishbone . . . . . . . 96

Riassunto

L’obiettivo di questo lavoro di tesi è stato lo sviluppo di un framework, denomi-

nato IPGen, in grado di creare automaticamente l’interfaccia di comunicazione

per core scritti in linguaggio VHDL. L’interfacciamento viene realizzato inca-

psulando il core ricevuto in input in una struttura, chiamata IP-Core, che con-

tenga la logica necessaria affinchè esso possa dialogare correttamente con gli altri

componenti del sistema nel quale viene inserito.

Il beneficio primario che l’utilizzo di IPGen apporta in fase di progettazione

di un componente hardware consiste nel fatto che lo sviluppatore è libero di

concentrare interamente i propri sforzi nell’implementazione della logica fun-

zionale, anzichè occupare parte del tempo nella realizzazione della logica di co-

municazione, in quanto quest’ultima viene generata automaticamente in modo

estremamente rapido.

Questa caratteristica permette di incrementare il livello di automatismo nella

progettazione di sistemi modulari, ovvero architetture composte da una molte-

plicità di componenti, ciascuno dei quali svolge una funzionalità specifica ed è

in grado di interagire con gli altri moduli attraverso un’opportuna infrastruttu-

ra di comunicazione. Tale metodologia di progettazione permette la creazione

di sistemi dinamicamente riconfigurabili, tipicamente implementati su dispositivi

riprogrammabili come le FPGA. La funzionalità di un sistema di questo tipo può

essere modificata mentre esso è operativo, senza alcuna interruzione apparente,

intercambiando alcuni dei moduli che lo compongono.

Il progetto di ricerca D.R.E.S.D. (Dynamic Reconfigurability in Embedded

System Design), condotto all’interno del Laboratorio di Microarchitetture del Po-

3

Riassunto

litecnico di Milano, si occupa dello studio e dello sviluppo di tali architetture, e

costituisce il contesto all’interno del quale il software è stato concepito.

Caronte è un flusso di progettazione realizzato in seno a D.R.E.S.D. per la

creazione di sistemi dinamicamente riconfigurabili. Dal momento che il flusso di

Caronte riceve una specifica di alto livello, la quale viene analizzata e partizionata

generando i moduli che andranno a comporre l’architettura, è necessario creare

in breve tempo le interfacce per tali componenti. È questa la motivazione che ha

portato alla realizzazione di IPGen.

Nonostante il framework sia stato concepito come parte integrante del flusso

di Caronte, esso mantiene inalterata la propria identità di software stand-alone, in

quanto il suo utilizzo permette un notevole risparmio di tempo e risorse ogniqual-

volta si debba creare un componente hardware.

Nel Capitolo 1 sono fornite alcune nozioni di base utili a tracciare un quadro

dell’ambito in cui IPGen si colloca. Innanzitutto viene mostrata una panoramica

sulla progettazione modulare dello hardware e ne viene descritto il componen-

te fondamentale: l’IP-Core. Dopo aver analizzato i vari tipi di sistemi riconfi-

gurabili, vengono introdotti il flusso di Caronte per la riconfigurabilità dinamica

parziale e la sua evoluzione YaRA. Successivamente vengono presentati gli stru-

menti utilizzati durante lo sviluppo del framework: Xilinx EDK, Xilinx ISE e

MentorGraphics ModelSim.

Nel Capitolo 2 vengono discussi gli approcci relativi al problema dell’in-

terfacciamento di moduli hardware, fornendo in tal modo importanti termini di

paragone con i quali confrontare la metodologia proposta.

Nel Capitolo 3 vengono descritte dettagliatamente le interfacce attualmente

supportate da IPGen. In primo luogo viene esposto il funzionamento del bus OPB

e delle due interfacce che permettono di connettersi ad esso: PSelect ed IPIF.

Viene poi presentato il bus Wishbone, componente che sta alla base dell’inno-

vazione apportata da YaRA.

Nel Capitolo 4 viene introdotto IPGen spiegando la metodologia che è alla

base del suo funzionamento. Dapprima sono esposte le motivazioni che hanno

portato allo sviluppo del framework; successivamente viene delineata la struttura

4

Riassunto

dell’IP-Core costituente l’output del tool e il flusso di esecuzione che porta alla

sua generazione. Il capitolo termina fornendo alcuni confronti con gli approcci

esposti nel capitolo 2.

Nel Capitolo 5 il framework viene presentato dal punto di vista implemen-

tativo, iniziando dalla descrizione delle classi che lo compongono. Nel seguito

vengono illustrati l’utilizzo e il funzionamento di IPGen e vengono descritte le

caratteristiche dei file da esso generati. Infine sono enunciate alcune convenzioni

alle quali il progettista si deve attenere durante la creazione di un core affinché

esso sia interfacciabile tramite il programma.

Nel Capitolo 6 sono mostrati i risultati sperimentali che validano il lavoro

svolto, ottenuti tramite test di prestazione e di funzionamento.

Il Capitolo 7 conclude l’elaborato ponendo le basi per sviluppi futuri.

5

Capitolo 1

Premesse

IPGen è un software pensato per rendere la creazione di componenti hardware

più veloce ed efficiente. Esso è stato concepito per essere integrato in un flusso

di sviluppo di sistemi hardware, denominato Caronte [1, 2]. Quest’ultimo per-

mette la progettazione di architetture che siano “dinamicamente riconfigurabili”,

la cui funzionalità possa essere cioè modificata a run-time, senza interruzioni nel

flusso di lavoro del dispositivo. Al fine di agevolare la comprensione degli ar-

gomenti trattati in questo testo si procede in questo capitolo con la descrizione

dello scenario nel quale il framework si colloca, fornendo un insieme di nozioni

e definizioni utili al lettore. Nella prima parte vine descritto l’ambiente nel quale

il software presentato si trova ad operare, cioè quello della riconfigurabilità dina-

mica, mentre nella seconda parte si descrivono brevemente gli strumenti software

utilizzati durante lo svolgimento del lavoro di tesi.

1.1 Scenario operativo

Il settore nel quale IPGen è stato concepito è quello dei sistemi hardware em-

bedded, ovvero sistemi elettronici progettati appositamente per una determinata

applicazione. Una tipologia particolare di questi è costituita dai sistemi riconfi-

gurabili, generalmente implementati su supporti fisici riprogrammabili, come le

FPGA (Field Programmable Gate Array). La funzionalità di ogni singolo dispo-

7

CAPITOLO 1. PREMESSE

sitivo di questo tipo può essere modificata un numero indeterminato di volte, in

modo tale da conferire a queste architetture un’elevatissima flessibilità. Uno dei

segmenti di ricerca attivi in questo ambito riguarda la potenzialità di questi dispo-

sitivi di essere riconfigurati mentre operano, senza alcuna interruzione apparente.

Questo tipo di riconfigurazione viene eseguita suddividendo il sistema in blocchi,

ognuno dei quali può essere modificato senza interrompere la normale esecuzione

degli altri. All’interno di questi blocchi vengono collocati dei moduli, denomi-

nati IP-Core, che svolgono il compito per il quale sono stati progettati, secondo i

principi della progettazione modulare.

Questa sezione descrive in modo dettagliato lo scenario qui accennato, pre-

sentando dapprima il metodo di progettazione modulare dello hardware e suc-

cessivamente il componente fondamentale di questa metodologia, l’IP-Core. Si

prosegue con una panoramica sui sistemi riconfigurabili e con la descrizione di

Caronte, il flusso di lavoro per la riconfigurabilità dinamica sviluppato all’inter-

no del Laboratorio di Microarchitetture del quale il tool costituisce un passaggio

fondamentale.

1.1.1 Progettazione modulare dello hardware

La progettazione modulare (Modular-Based Design) [3] è una metodologia di

sviluppo che identifica un sistema hardware come un insieme di moduli, ognuno

dei quali espleta una determinata funzionalità. Queste componenti, sviluppate

separatamente, vengono poi interconnesse mediante un’opportuna infrastruttura

di comunicazione, tipicamente un bus o degli allacciamenti “punto a punto”. I

vantaggi che questa metodologia comporta sono molteplici:

• un sistema può essere sviluppato da un team di individui che lavorano in-

dipendentemente su moduli differenti, i quali vengono assemblati in un

secondo momento. Questo lavoro parallelo permette di risparmiare molto

tempo e risorse;

• permette di modificare solo una parte di un sistema, lasciando il resto inal-

terato;

8

CAPITOLO 1. PREMESSE

• getta le fondamenta per il riutilizzo dello hardware: i moduli creati costi-

tuiscono un’entità a sé stante, e possono perciò essere inseriti in sistemi

diversi.

Esiste una prassi di massima da seguire per ottenere una buona architettura mo-

dulare, eccone i punti più significativi:

1. creazione di una architettura di alto livello (top-level design) che contenga

le informazioni sui moduli e le modalità di comunicazione;

2. implementazione dei moduli nel linguaggio scelto (di solito VHDL o Veri-

log), che può essere svolta da persone diverse;

3. assemblaggio dei moduli all’interno del top-level design.

Ognuno dei moduli che compongono un sistema di questo tipo viene denomina-

to IP-Core, il quale costituisce l’output di IPGen ed è argomento della sezione

seguente.

1.1.2 IP-Core

L’obiettivo di IPGen è costruire IP-Core. È dunque estremamente importante

conoscere ciò a cui questo termine si riferisce. Viene dapprima fornita una definizione

formale del termine, per proseguire con la descrizione della struttura interna di

questo “oggetto”.

1.1.2.1 Definizione

Il termine “IP-Core” (Intellectual Property-Core) indica [4, 5] un’entità logica

riutilizzabile, impiegata sia nella creazione di logiche “statiche” (ASIC) che nelle

schede riprogrammabili (come le FPGA, vedere sezione 1.1.3). In altre parole, un

IP-Core è un’unità che, all’interno di un sistema hardware più ampio, svolge un

determinato compito. Come esprime il termine stesso, un IP-Core è una proprietà

intellettuale: vale a dire che esso è una risorsa che può essere posseduta da un

9

CAPITOLO 1. PREMESSE

singolo o da una società, oppure può essere messa a disposizione di chiunque la

voglia utilizzare (spesso si parla di open cores).

Una usuale classificazione degli IP-Core è la seguente:

• Hard cores, implementazioni fisiche della progettazione della proprietà in-

tellettuale;

• Firm (semi-hard) cores, che contengono informazioni sul proprio posizio-

namento ma possono essere esportate su varie architetture;

• Soft cores, definibili come una rete di porte logiche e registri, implementata

spesso in un linguaggio di descrizione dell’hardware come VHDL.

Un IP-Core può costituire sia un componente master, per esempio la stessa CPU,

oppure un componente slave, che deve essere “utilizzato” da un master1. Es-

so può inoltre rappresentare entità come un bus o porta seriale, e quindi costi-

tuire una infrastruttura di comunicazione tra altri IP-Core. Nel seguito si farà

riferimento soltanto a IP-Core di tipo slave; inoltre, con il termine IP-Core ci si

riferirà esclusivamente ai soft cores, cioè quelli che possono essere istanziati su

una FPGA.

L’analogia tra le componenti della progettazione modulare (sezione 1.1.1) e

IP-Core è immediata: gli IP-Core costituiscono infatti i moduli che compongono

un sistema hardware progettato modularmente.

Nel prossimo paragrafo viene descritta la struttura generale di un IP-Core.

1.1.2.2 Dal core all’IP-Core

Con il termine core si intende il “cuore elaborativo” di un componente, cioè la

parte di logica interna che ne costituisce la funzionalità vera e propria. Il core

è dunque la porzione distintiva e caratteristica che rappresenta la vera e propria

1I dispositivi che possono essere connessi ad un bus si dividono in master e slave. I primi sonocomponenti attivi, ovvero possono decidere quando iniziare un trasferimento di dati; i secondisono passivi, in quanto rimangono in attesa di una richiesta di trasferimento [6].

10

CAPITOLO 1. PREMESSE

“proprietà intellettuale” del componente. In realtà, per essere inserito efficace-

mente all’interno di un sistema più grande, un core deve essere dotato di un’inter-

faccia verso l’esterno. Questa interfaccia permette ad esso di accedere al canale

di comunicazione (per esempio un bus) e dialogare con gli altri componenti del-

l’architettura. Per questo motivo, con il termine IP-Core d’ora in poi si farà rife-

rimento ad un blocco logico dotato di un’opportuna interfaccia, adatto ad essere

inserito in un sistema che adotti l’infrastruttura di comunicazione per il quale esso

è stato progettato.

In pratica, un IP-Core è costituito da un “guscio” esterno che racchiude il

core ed un’opportuna interfaccia di comunicazione, come mostrato in figura 1.1.

Spesso un core, quando contenuto in questo tipo di struttura, viene indicato con

l’espressione user logic, proprio per rimarcare il fatto che è questa la parte che

viene effettivamente implementata dall’utente e ne costituisce una proprietà intel-

lettuale.

Figura 1.1: Struttura di un IP-Core

Nella prossima sezione vengono introdotti i sistemi riconfigurabili, all’interno

dei quali gli IP-Core rivestono un ruolo fondamentale in quanto costituiscono,

nella architettura presa in esame, i blocchi che possono essere intercambiati per

fornire la capacità al sistema di evolversi.

11

CAPITOLO 1. PREMESSE

1.1.3 Sistemi riconfigurabili

Una branca relativamente nuova della progettazione hardware si occupa di siste-

mi riconfigurabili, ovvero sistemi che, al contrario delle tradizionali architetture

ASIC (Application-specific Integrated Circuit), permettono di essere modificati

dopo essere stati prodotti. Essi prendono dunque il nome di sistemi riconfigurabi-

li. In questo ambito i dispositivi più diffusi sono le FPGA (Field Programmable

Gate Array) che, grazie ad un complesso sistema di porte logiche, possono es-

sere riprogrammate ogni qual volta è necessario far svolgere loro un particolare

compito.

Non esiste un’unica direzione secondo cui intendere la riconfigurabilità di un

sistema; si possono infatti identificare i seguenti parametri:

• Riconfigurabilità interna: il flusso di riconfigurazione è gestito da un com-

ponente interno alla FPGA da riconfigurare;

• Riconfigurabilità esterna: la riconfigurazione è gestita da un componente

esterno alla FPGA da riconfigurare.

Si può inoltre fare una distinzione tra:

• Riconfigurabilità totale: è il caso in cui la FPGA viene interamente ricon-

figurata;

• Riconfigurabilità parziale: secondo questa modalità, soltanto una parte del-

la FPGA viene modificata, mentre l’altra non è interessata dal processo di

riconfigurazione.

Quest’ultima classificazione necessita di un’ulteriore esplicazione: se si opera su

una rete di più FPGA, invece che su di un singolo chip, la riconfigurabilità è totale

se si analizza una singola FPGA ma può risultare parziale se il punto di vista è

quello della rete nel suo insieme.

Su tali basi si aggiunge un ulteriore grado di libertà: tali architetture pos-

sono essere riconfigurate anche a run-time, cioè mentre sono operative, senza

12

CAPITOLO 1. PREMESSE

interrompere il flusso di lavoro. Tale processo prende il nome di riconfigura-bilità dinamica, che si contrappone alla tradizionale riconfigurabilità statica, ef-

fettuata soltanto quando la FPGA non è operativa. Risulta evidente che la ri-

configurabilità dinamica effettuata su un solo chip deve essere parziale, in modo

da non interromperne l’esecuzione. Il tipo di riconfigurazione che viene presa

in esame nel seguito è la Riconfigurabilità Dinamica Parziale (Partial Dynamic

Reconfiguration).

Xilinx introduce [7] due differenti flussi per implementare la riconfigurabilità

dinamica parziale: l’approccio module-based e quello difference-based .

• Module-based partial reconfiguration. Questo approccio si basa sulla

progettazione modulare dello hardware (sezione 1.1.1), e prevede la definizione

di moduli riconfigurabili, cioè porzioni delimitate di FPGA la cui dimen-

sione è invariante durante l’esecuzione, che possono essere riconfigurate a

run-time senza interferire con il funzionamento degli altri moduli e quindi

del sistema complessivo. Per rendere tale procedimento possibile, è neces-

sario definire una architettura di livello “top” (top-level architecture) in cui

ogni modulo è visto come una “scatola nera” (black-box). La logica al livel-

lo top deve limitarsi alla descrizione delle black box (senza conoscenza del

loro contenuto) e di una infrastruttura fissa di comunicazione, i bus macro.

• Difference-based partial reconfiguration. Nelle architetture in cui si rende

necessario riconfigurare blocchi logici di dimensioni significative, è richi-

esta la riconfigurazione module-based. Se invece si devono attuare cambia-

menti piccoli, per esempio una porta di Input/Output, è consigliabile utiliz-

zare l’approccio difference based. In questi casi, si modifica il file di confi-

gurazione (NGC) dove è necessario e si produce un bitstream che contiene

solamente le differenze tra la configurazione attuale e quella precedente.

1.1.4 Riconfigurabilità dinamica parziale: il flusso di Caronte

In questa sezione viene presentato Caronte, un workflow di sviluppo per architet-

ture riconfigurabili [1, 2] sviluppato all’interno del Laboratorio di Microarchitet-

13

CAPITOLO 1. PREMESSE

ture. Tale metodologia è in parte basata su EDK, presentato nella sezione 1.2.1,

e adotta dunque uno strumento già largamente utilizzato nello sviluppo di ar-

chitetture per FPGA, sfruttandone le caratteristiche che lo rendono adatto alla

realizzazione di sistemi riconfigurabili. Caronte intende la riconfigurabilità come

ridefinizione di uno o più componenti all’interno dell’architettura, è dunque pro-

fondamente legato alla riconfigurazione per moduli (sezione 1.1.3): ogni modu-

lo che viene intercambiato viene denominato blocco riconfigurabile. Il flusso di

lavoro di Caronte è mostrato in figura 1.2, e include le seguenti fasi:

• HW-SSP Phase. Durante la fase Hardware Static System Photo viene iden-

tificato un insieme di sistemi completi ognuno dei quali rappresenta un pas-

so nel processo di riconfigurazione. L’idea è quella di considerare il sistema

nel tempo come una sequenza di foto statiche. Queste sono tutte identiche

per quanto riguarda la parte statica del sistema, mentre differiscono per il

contenuto di almeno una Black Box (vedere sezione 1.1.4.1);

• Design Phase. Obiettivo di questa fase è quello di raccogliere tutte le in-

formazioni richieste per il calcolo dei bitstream necessari per implementare

la riconfigurabilità su di una FPGA. A tal proposito viene utilizzato EDK,

adottando una approccio modular based (sezione 1.1.1), fino a produrre la

descrizione dei sistemi in VHDL. Un problema da tenere in considerazio-

ne è la natura dinamica dell’architettura realizzata, in particolare per quan-

to riguarda la comunicazione sia tra i moduli riconfigurabili, sia tra essi

e la parte fissa del sistema. Per questo vengono utilizzate delle partico-

lari linee di comunicazione chiamate bus macro, che rimangono inalterate

durante la riconfigurazione, e sono dunque comuni a tutte le SSP che com-

pongono l’evoluzione del sistema. Bisogna inoltre determinare a priori la

dimensioni di ogni porzione fisica di FPGA destinata ad accogliere i moduli

riconfigurabili;

• Bitstream Creation Phase. Vengono creati tutti i bitstream necessari per

la mappatura fisica dell’architettura su FPGA. Questi vengono chiamati bit-

stream parziali in quanto non contengono l’informazione sull’intero siste-

14

CAPITOLO 1. PREMESSE

ma, ma solo sulle porzioni che vengono modificate tra due passi successivi,

e vengono pertanto calcolati come differenza tra due bitstream completi di

configurazione.

Figura 1.2: Il flusso di lavoro di Caronte

Un problema cruciale è la decisione di quali parti di un sistema hardware coin-

volgere nella riconfigurazione e quali invece lasciare fissi sulla FPGA. Bisogna

inoltre determinare quali blocchi riconfigurabili andranno in una determinata porzione

di FPGA (la partizione del chip deve essere fissata a priori e non può essere modi-

ficata) e quali in altre. Si tratta di questioni molto delicate che vanno trattate con

particolare attenzione, avendo l’obiettivo di raggiungere il miglior compromesso

tra occupazione e prestazioni dell’architettura.

15

CAPITOLO 1. PREMESSE

1.1.4.1 Architettura hardware di Caronte

La struttura hardware alla base del funzionamento del flusso di Caronte è sud-

divisa in due parti: quella fissa e quella riconfigurabile (figura 1.3). La pri-

ma è schematicamente rappresentabile come una tradizionale macchina di Von-

Neumann controllata da un processore anch’esso interno al chip (soft-processor).

In questa parte si trovano i seguenti componenti: l’Interrupt Controller, l’ICAP

(necessario per leggere da memoria e scrivere nella specifica Black Box i mo-

duli riconfigurabili) e l’IP-Core Manager (IPCM), una sorta di ponte tra il lato

software e il lato hardware. Sempre collocato sulla parte fissa si trova il bus di

comunicazione, tipicamente della famiglia CoreConnect (vedere il capitolo 3).

La parte riconfigurabile, o dinamica, è invece costituita da un insieme di Black

Box. EDK definisce un componente come una qualsiasi parte di un sistema, per

esempio un bus, una periferica o un processore. Da questo punto di vista anche

una Black Box può essere considerata un componente, anche se questo è riduttivo:

in realtà una Black Box è una porzione di FPGA di dimensione fissa che può es-

sere completamente riconfigurata senza interferire con il normale funzionamento

della restante parte del chip, come se fosse un guscio entro il quale collocare i mo-

duli. Dal punto di vista dell’implementazione essa è costituita da due parti: una

interna, e cioè l’IP-Core che costituisce il modulo riconfigurabile, e una esterna,

che fornisce l’interconnessione tra la logica interna e i bus macro.

La modalità di comunicazione all’interno di uno scenario come quello appena

descritto include tre casi: innanzitutto si ha il collegamento tradizionale tra due

moduli fissi tramite un bus, tipicamente CoreConnect OPB; inoltre è necessario

supportare la connessione tra un blocco fisso e uno riconfigurabile, come pure

tra due blocchi entrambi riconfigurabili. Tutto questo considerando il fatto che

nella parte dinamica i collegamenti sono realizzati tramite bus macro, necessa-

ri per creare un canale stabile che supporti la riconfigurazione delle Black Box.

Per avere una corretta visione del quadro è utile immaginare di “percorrere” il

collegamento tra un modulo fisso e uno riconfigurabile (figura 1.4): il modulo fis-

so è dotato di un’interfaccia verso il bus adottato dall’architettura (si considera,

senza perdere generalità, OPB). Una volta raggiunto il “confine” tra parte fissa e

16

CAPITOLO 1. PREMESSE

Figura 1.3: L’architettura hardware di Caronte

riconfigurabile è necessario passare attraverso i bus macro, che fortunatamente,

essendo semplicemente delle linee fisiche presenti sulla FPGA non possiedono un

protocollo di comunicazione, e possono quindi essere semplicemente allacciati ai

segnali OPB. Si deve ora “penetrare” nella Black Box per giungere all’IP-Core:

anche qui sarà sufficiente un semplice mappaggio tra bus macro e segnali entranti

nell’IP-Core: esso è dotato di un interfaccia OPB, in modo da non richiedere la

presenza di un bridge che traduca tra due protocolli di comunicazione differenti.

Per quanto riguarda il collegamento di due moduli riconfigurabili il procedimento

è analogo a prima, con la differenza che in questo caso il punto di partenza è un

IP-Core all’interno di una Black Box, quindi si passa al bus macro e infine ad

un’altra Black Box.

1.1.4.2 Da Caronte a YaRA

L’architettura proposta, pur essendo valida, soffre di alcune limitazioni, soprattut-

to se utilizzata in un contesto di riconfigurabilità dinamica. La prima di queste

è il fatto che la comunicazione tra moduli fisicamente non contigui sulla FPGA

può avvenire solamente se i moduli che si frappongo tra la sorgente e la desti-

17

CAPITOLO 1. PREMESSE

Figura 1.4: Collegamento tra un modulo fisso e uno riconfigurabile nell’architettura diCaronte

nazione ritrasmettono i dati inalterati. Questo problema implica pesanti effetti

sulla riconfigurazione, dato che se uno dei moduli attraverso il quale il canale

di comunicazione deve passare viene riconfigurato, la comunicazione dovrà es-

sere interrotta; ciò rappresenta un collo di bottiglia nelle prestazioni del sistema

e limita il campo di applicazione dove Caronte può essere effettivamente utiliz-

zato. Un altro forte limite sta nel fatto che lo standard CoreConnect imposto da

IBM prevede che per ogni IP-Core istanziato all’interno di un sistema vengano

replicate tutte le linee di bus. In questo modo ogni IP-Core aggiunto occupa ben

più dello spazio necessario al suo effettivo funzionamento e ciò impone un vin-

colo estremamente restrittivo alla scalabilità del sistema, il quale non potrà essere

composto da un numero elevato di IP-Core.

Per questi motivi è stata creata YaRA (Yet another Reconfigurable Architec-

ture); anche in questo caso il sistema è composto da una parte fissa ed una ricon-

figurabile ma, a differenza di Caronte, presenta un’infrastruttura di comunicazione

diversa. La nuova architettura si presenta come in figura 1.5.

La parte fissa è suddivisa a sua volta in due sottosistemi. Il primo di questi

adotta un bus di comunicazione di tipo PLB, il quale connette componenti quali un

processore PowerPC, un BRAM Controller per controllare l’accesso alle memorie

BRAM presenti sulla FPGA e l’ICAP. Il secondo sottosistema utilizza invece un

bus OPB, dove sono presenti IP-Core che variano da un particolare sistema all’al-

tro, ma per i quali non è prevista alcuna riconfigurazione (per esempio una porta

seriale). Per collegare queste due parti è presente un bridge tra PLB e OPB. La

18

CAPITOLO 1. PREMESSE

Figura 1.5: L’architettura di YaRA

parte riconfigurabile è dotata di connessioni di tipo Wishbone (sezione 3.2), che è

esente dagli svantaggi che emergono utilizzando il bus OPB.

Il cuore dell’innovazione nel passaggio da Caronte e YaRA è stata la creazione,

all’interno del Laboratorio di Microarchitetture, del componente OPB to Wish-

bone Bridge che permette il collegamento tra la parte fissa e quella riconfigurabile.

I moduli riconfigurabili devono rispettare alcuni requisiti: devono essere compati-

bili con il protocollo Wishbone e devono occupare lo stesso numero di CLB2, che

deve essere necessariamente un multiplo di 8 ed essere scelto in modo da con-

tenere il più grande dei moduli utilizzati dal sistema nelle sue riconfigurazioni.

Queste limitazioni hanno lo scopo di garantire l’intercambiabilità dei moduli per

poterli sostituire senza problemi nel processo di riconfigurazione.

2CLB: Configurable Logic Block. Nell’architettura di una FPGA sono i blocchi logici atomiciattraverso i quali viene realizzata la logica combinatoria che si vuole implementare nel dispositivo.Ogni cella è dotata di ingressi dati e di controllo attraverso i quali può essere riprogrammatacon la funzione logica desiderata. Il numero di CLB è una delle unità di misura per la stimadell’occupazione di un dato modulo nel chip.

19

CAPITOLO 1. PREMESSE

1.2 Strumenti utilizzati

In questa sezione vengono presentati i software che sono stati utilizzati nello svol-

gimento del lavoro di tesi. Il primo di questi è Xilinx EDK, che permette la

creazione di sistemi per FPGA; esso è ampiamente utilizzato all’interno del flus-

so di Caronte e costituisce uno degli ambienti principali di utilizzo degli IP-Core

generati dal IPGen. Successivamente è descritto Xilinx ISE, il quale costituisce

uno strumento di sviluppo e sintesi di architetture hardware, utilizzato in questo

lavoro per la sintesi degli IP-Core generati. L’ultimo software presentato è Men-

torGraphics Modelsim, che consente di effettuare simulazioni sui componenti im-

plementati; esso è stato indispensabile per effettuare i test di funzionamento dei

componenti creati.

1.2.1 Xilinx EDK

Embedded Development Kit (EDK) [8], prodotto da Xilinx, è un framework com-

posto da numerosi tool che permette di creare un sistema embedded completo

implementabile su una FPGA. EDK permette infatti di realizzare sia l’architettura

hardware del sistema sia la componente software. Dal punto di vista hardware

è necessaria la creazione di una piattaforma embedded che consista di uno o più

processori e moduli (spesso denominati anche periferiche) collegati ad un bus,

adottando perciò un approccio alla progettazione di tipo modulare (sezione 1.1.1);

EDK descrive questa piattaforma hardware in un file MHS (Microprocessor Hard-

ware Specification). Dall’altro lato vi è la realizzazione di una piattaforma soft-

ware, cioè l’insieme di driver per i moduli ed eventualmente di un sistema ope-

rativo per l’architettura creata; questo è descritto in un file MSS (Microprocessor

Software Specification).

L’interfaccia grafica di EDK è XPS (Xilinx Platform Studio), che integra stru-

menti aventi vario scopo e utilizzo, dalla creazione del sistema hardware alle fun-

zionalità di test e debugging. Con XPS è possibile generare e modificare i file

MPS e MHS, creare una visualizzazione schematica dell’architettura realizzata e

accedere a numerosi tool che compongono la suite EDK I principali sono:

20

CAPITOLO 1. PREMESSE

• Base System Builder (BSB): wizard che permette la facile e veloce creazione

di un sistema funzionante, o la realizzazione di un sistema base personaliz-

zabile per progetti più complessi;

• Platform Generator (Platgen): permette di tradurre la descrizione della piat-

taforma software in una netlist HDL che può essere implementata su una

FPGA. In particolare invoca XST (mostrato nella sezione seguente) per la

sintesi degli IP-Core utilizzati;

• Create and Import Peripheral Wizard: vedere sezione 2.3;

• Library Generator (Libgen): configura la piattaforma software, comprese le

applicazioni che si vogliono utilizzare, gestendo il file MSS.

Una caratteristica importante di EDK è che, nel costruire un’architettura collegan-

do insieme vari IP-Core, esso non analizza il contenuto di ciascun componente,

ma si interessa solamente dei segnali di Input/Output di ciascuno di essi; in questo

modo è possibile creare dei moduli costituiti solamente dal “guscio” esterno, con-

tenenti un parte della logica di comunicazione, che verranno poi “riempiti” suc-

cessivamente con IP-Core appropriati. È proprio questa considerazione che sta

alla base della metodologia di riconfigurabilità dinamica presentata nella sezione

1.1.4.

1.2.2 Xilinx ISE

Integrated Software Environment (ISE), anch’esso prodotto da Xilinx, è un in-

sieme di tool che permette di effettuare il design e la sintesi di un’architettura

descritta tramite linguaggi come VHDL (Very high speed integrated circuit Hard-

ware Description Language) o Verilog. Nel seguito ci si riferirà sempre a VHDL

poiché è il linguaggio riconosciuto dal tool presentato in questa tesi, nonostante

gli strumenti Xilinx permettano di utilizzare anche Verilog.

L’interfaccia grafica di questo pacchetto di software si chiama Project Navi-

gator, tramite il quale è possibile accedere a tutte le funzionalità implementative

offerte da ISE. Come si può vedere in figura 1.6, l’area di lavoro è divisa in quattro

21

CAPITOLO 1. PREMESSE

Figura 1.6: Workspace di Project Navigator

settori:

• un editor di testo (riquadro A), in cui è possibile modificare i file sorgenti

del progetto da sintetizzare. Sempre nella stessa finestra possono essere

visualizzati i risultati di sintesi (Design Summary);

• una finestra (riquadro B) in cui è rappresentata la struttura del progetto, in

termini di moduli e librerie utilizzate;

• una finestra (riquadro C) da cui si possono lanciare le funzioni;

• una shell (riquadro D) dove viene visualizzato il log delle operazioni effet-

tuate dal programma.

Le funzioni incluse in ISE sono divise in gruppi, e sono qui di seguito presentate.

Il primo gruppo (Design Utilities) comprende alcune utilità come la chiamata al

simulatore (in questo caso ModelSim, sezione 1.2.3). Si trovano poi le funzionalità

User Constraints, che permettono di impostare dei vincoli prestazionali di spazio

22

CAPITOLO 1. PREMESSE

e di tempo al sistema creato. Il gruppo successivo è Synthesize - XST, necessa-

rio per compilare e sintetizzare il codice VHDL. Queste funzionalità utilizzano il

tool XST [9], che, partendo dal VHDL, crea una netlist descritta in un file NGC,

effettuando una mappatura del codice sorgente su una rete logica composta da

blocchi combinatori, sequenziali e interconnessioni tra di essi. Il processo di sin-

tesi è estremamente complesso, e ciò è dovuto in buona parte alla ottimizzazioni

spaziali (area occupata) e temporali (maximum delay time) effettuate. Come si

può vedere nel capitolo 6, queste influenzano in modo determinante le prestazioni

del tool oggetto di questa tesi. Sempre nell’ambito di sintesi XST si trova View

RTL Schematic, che fornisce una visualizzazione schematica dei blocchi logici

che costituiscono il sistema. Un altro gruppo di funzionalità è Implement Design,

che mappa la rete risultante dal processo di sintesi su di una FPGA, il cui modello

e versione vengono decisi a priori.

1.2.3 MentorGraphics ModelSim

ModelSim è uno strumento di editing, simulazione e debug di sistemi hardware

descritti in un linguaggio HDL. Esso permette di simulare il comportamento di

un’architettura hardware visualizzandone numericamente e graficamente il com-

portamento. L’interfaccia grafica del software [10] consiste di varie finestre che

danno accesso alle varie parti del sistema da simulare e ai numerosi tool disponi-

bili. Si possono effettuare due tipi di simulazione: la simulazione step-by-step,

che permette di procedere un’istruzione alla volta direttamente sul codice sor-

gente, e la simulazione wave, di più alto livello, che procede in base ad un’unità

temporale definita dall’utente. Quest’ultima modalità è quella che è stata utilizza-

ta nella fase di test di questo progetto, e nel seguito del documento salvo esplicita

specificazione si farà implicitamente riferimento ad essa.

In fase di simulazione, l’interfaccia si presenta come in figura 1.7. Le parti

principali che la compongono sono:

• Workspace (riquadro A): consente un rapido accesso al progetto, permetten-

23

CAPITOLO 1. PREMESSE

Figura 1.7: Workspace di ModelSim.

do di visualizzare rapidamente la struttura del sistema, le librerie utilizzabili

ed i file VHDL che compongono il progetto;

• Objects (riquadro B): mostra il nome e il valore dei segnali del modu-

lo corrente, ossia quello selezionato nella visualizzazione “struttura” del

Workspace. Da questo pannello si può forzare il valore dei segnali (solita-

mente quelli di input) e impostare il segnale di clock, per procedere poi alla

simulazione vera e propria;

• Wave (riquadro C): permette di visualizzare i risultati della simulazione.

Questo pannello è suddiviso a sua volta in tre parti

– Pathway Pane: visualizza i segnali e il relativo percorso, partendo dal

livello top dell’architettura;

– Value Pane: visualizza il valore dei segnali all’istante indicato dal

cursore nel Wave pane;

– Wave pane: visualizza graficamente l’andamento temporale dei segna-

li.

24

CAPITOLO 1. PREMESSE

• Transcript (riquadro D): tiene traccia della history del flusso del programma

e fornisce un’interfaccia da linea di comando.

Si può avviare la simulazione direttamente dal Project Navigator di ISE. A questo

punto è necessario impostare solitamente alcuni segnali, forzandoli al valore de-

siderato. Inoltre è necessario configurare, se presente, il segnale di clock. Dopo

aver determinato il parametro run length corrispondente alla lunghezza del peri-

odo di simulazione, è possibile procedere, un periodo alla volta, alla simulazione

vera e propria.

25

Capitolo 2

Approcci precedenti

Prima di iniziare a descrivere il software realizzato, si vogliono presentare breve-

mente alcuni approcci esistenti al problema dell’interfacciamento dei core. Tale

analisi risulta molto utile sotto due punti di vista: innanzitutto essa permette di

pervenire ad una migliore comprensione dei benefici apportati da questo lavoro

nell’ambito della progettazione modulare; in secondo luogo si ottiene una visione

più nitida dello scenario di applicazione, con l’effetto di delineare in modo più

chiaro la collocazione del framework, sia in una dimensione “verticale” (nel flus-

so di design) che “orizzontale” (all’interno dell’architettura). Si inizia con una

descrizione di OCP Socket e di Interface Adaptor Logic, standard proposti per le

interfacce dei core, per poi passare alla presentazione del tool Import Peripheral

Wizard che fa parte di Xilinx EDK (presentato nella sezione 1.2.1). Si prosegue

con un accenno al framework CoDeveloper sviluppato da ImpulseC. Conside-

razioni circa la bontà degli approcci presentati e confronti con IPGen verranno

discusse nella sezione 4.4.

2.1 OCP Socket e CoreCreator

L’Open Core Protocol (OCP) [11, 12] è un progetto sviluppato inizialmente dal-

l’organizzazione Virtual Socket Interface Alliance (VSIA), e passato successiva-

mente sotto il controllo di OCP International Partnership (OCP-IP). L’obiettivo

27

CAPITOLO 2. APPROCCI PRECEDENTI

primario di tale progetto è quello di fornire un supporto condiviso per il riuso

degli IP-Cores in sistemi differenti. Il riutilizzo di componenti porta con sé nu-

merosi benefici, primo tra tutti la diminuzione del tempo richiesto nello sviluppo

di un sistema hardware, con un ovvio incremento della produttività.

L’approccio è basato sulla proposta di uno standard per l’interfacciamento dei

core all’interno del sistema ospite. Il Socket OCP è alla base di tale metodologia:

si tratta di un componente di interfacciamento molto flessibile, progettato per es-

sere utilizzato sia da moduli di tipo master che di tipo slave. Esso offre un’ampia

gamma di servizi allo sviluppatore, che può scegliere di utilizzarli o meno tramite

un opportuno file di specifica. Sempre in un’ottica di diffusione su larga scala del-

lo standard proposto, OCP-IP ha sviluppato un bus che si sposa perfettamente con

le caratteristiche del Socket OCP. Ovviamente, se si vuole rendere tale componen-

te effettivamente portabile anche su sistemi che utilizzano una infrastruttura di co-

municazione differente, è necessario utilizzare un “bus wrapper”, che implementa

la connessione tra il particolare mezzo trasmissivo e il Socket OCP. Si avranno

dunque numerosi wrapper, uno per ogni infrastruttura di comunicazione. Non è

dunque escluso che ci si possa trovare nella condizione di dovere implementare

personalmente tale componente, in quanto esso potrebbe non esistere. Seguendo

questa metodologia si ottiene dunque un IP-Core stratificato su tre livelli, come

mostrato in figura 2.1. Si noti che è proprio il concetto di stratificazione (layer-

ing) che sta alla base di questo approccio: essa permette infatti di disaccoppiare

in modo preciso la funzionalità logica del core dalla connessione con il sistema.

Come detto precedentemente, lo sviluppatore ha la possibilità di scegliere

quali servizi offerti dal Socket OCP utilizzare, sulla base delle caratteristiche del

proprio componente. Tale scelta viene implementata tramite un file di specifica

RTL, che può risultare di difficile implementazione da parte di sviluppatori non

esperti di linguaggio RTL.

Per ovviare a questo problema OCP fornisce un tool denominato CoreCre-

ator, che permette di creare in modo automatico, dopo aver selezionato le opzioni

desiderate, un pacchetto costituente il nuovo IP-Core con Socket OCP integrato.

Questo tool permette anche di validare in modo automatico la compatibilità del

28

CAPITOLO 2. APPROCCI PRECEDENTI

Figura 2.1: Schema dell’IP-Core secondo l’approccio OCP

core con lo standard OCP.

2.2 Interface Adaptor Logic

In [13] e [14] viene descritta una metodologia sostanzialmente molto simile a

quella mostrata nella precedente sezione. Anche in questo caso l’attenzione è fo-

calizzata sul riutilizzo degli IP-Core, obiettivo raggiungibile mediante una rigida

separazione tra interfaccia di comunicazione e logica funzionale. A connettere le

due parti si trova un blocco denominato Interface Adaptor Logic (IAL), che ha il

pregio, a detta degli autori, di essere molto più leggero del Socket OCP. Anche

in questo caso dunque si ha un’architettura strutturata su tre livelli: la connes-

sione con il mezzo di comunicazione (corrispondente al “bus wrapper” di OCP),

il blocco IAL e il core che implementa la funzionalità.

Il modulo IAL ha la caratteristica di presentare un set molto esiguo di porte

per quanto riguarda la connessione “lato core”; meno porte implicano necessaria-

mente meno vincoli da rispettare, e questo è sicuramente un aspetto positivo di

questa interfaccia. Ciò nonostante l’interesse per questo approccio sembra essere

scemato, in quanto attualmente non si trovano corrispondenze reali per quelli che

nei due articoli presi in esame sono presentati come sviluppi futuri, in primis la

29

CAPITOLO 2. APPROCCI PRECEDENTI

creazione di “IAL Generator”, uno strumento software che sarebbe stato in grado

di generare automaticamente un IP-Core completo di interfaccia IAL.

2.3 EDK Create/Import Peripheral Wizard

Uno dei tool che compone la suite EDK (sezione 1.2.1) è Create/Import Peripheral

Wizard [8]. L’obiettivo di tale strumento è quello di aiutare lo sviluppatore nel re-

alizzare IP-Core che siano compatibili con EDK. Si compone, come dice il nome,

di due parti: la creazione di un nuovo componente (create) e l’importazione di un

componente già esistente (import).

Per quanto riguarda la creazione di un nuovo componente, il tool offre un

generatore automatico del template nel quale porre il codice che descrive la fun-

zionalità dell’IP-Core che si vuole creare. Per template si intende la descrizione

dell’IP-Core priva della parte di logica che esprime il comportamento del mo-

dulo. Sostanzialmente, riprendendo la figura 1.1, il tool crea automaticamente il

file VHDL che contiene l’istanza dell’interfaccia e della “user logic”. Per quan-

to concerne quest’ultima, viene generato un secondo file VHDL contenente la

dichiarazione di entity, mentre la parte implementativa (architecture) è vuota ed

è appunto la porzione che va inserita da parte dello sviluppatore. Essendo stato

sviluppato nell’ambito di EDK, che adotta come canali di comunicazione i bus

della famiglia IBM CoreConnect (sezione 3), il tool permette di utilizzare soltan-

to due interfacce: OPB IPIF e PLB IPIF. Siccome un’interfaccia di tipo IPIF offre

molti servizi, l’utente può scegliere, in fase di creazione del template, quali di

questi servizi utilizzare per il proprio modulo. In questo modo vengono auto-

maticamente impostati i parametri relativi a tali servizi all’interno del file VHDL

che contiene l’istanza dell’interfaccia. Per quanto riguarda il file predisposto a

contenere la logica propria del modulo, esso presenta porte di input/output fisse

(IPIC), e i segnali provenienti da queste devono essere opportunamente trattati

all’interno della logica dell’utente.

La funzione di importazione degli IP-Core, invece, prende in input il codice

VHDL già completo che rappresenta un IP-Core e lo correda di alcuni file che lo

30

CAPITOLO 2. APPROCCI PRECEDENTI

rendono un componente realmente inseribile in un sistema EDK. Sostanzialmente

vengono creati due file:

• Peripheral Analyze Order (PAO), che definisce l’ordine dei file HDL neces-

sari alla sintesi del componente;

• Microprocessor Peripheral Definition (MPD), nel quale si trovano tutte le

porte e i parametri dell’IP-Core importato, in modo che esso sia trattato in

modo corretto da EDK.

Il Create/Import Peripheral Wizard è dunque un utile strumento nell’ambito di la-

voro di EDK, in quanto permette di facilitare e velocizzare il flusso di inserimento

di un nuovo modulo all’interno di un sistema. La sua utilità è però molto ridotta

al di fuori di tale ambiente, proprio perché si tratta di uno strumento sviluppato

ad-hoc.

2.4 ImpulseC CoDeveloper

Il framework CoDeveloper [15], prodotto da Impulse Accelerated Technologies,

è una complessa piattaforma di sviluppo che permette di gestire la creazione di si-

stemi misti hardware e software (hardware-software codesign), sintetizzando una

specifica di alto livello. Questa specifica è implementata in linguaggio C, utiliz-

zando le librerie ImpulseC fornite con il programma. Durante il processo di sintesi

di un componente si può selezionare, tra molte alternative, quale sarà l’architet-

tura ospite, in modo da implementare nel codice VHDL prodotto un’interfaccia

opportuna; per esempio si può scegliere un’interfaccia di tipo OPB IPIF (vedere

capitolo 3). Il punto di forza di questa metodologia sta nel fatto che, generando

essa stessa il codice VHDL da utilizzare come “core”, nel processo di creazione

dell’interfaccia dispone di un set di segnali conosciuti che si collegano in mo-

do meccanico all’insieme dei segnali dell’interfaccia. Complessivamente, questo

framework è uno strumento molto valido che, se utilizzato in modo opportuno,

può produrre un risparmio di tempo notevole nello sviluppo di sistemi integrati

hardware e software.

31

CAPITOLO 2. APPROCCI PRECEDENTI

2.5 Conclusioni

Dopo avere analizzato le caratteristiche di questi approcci, è opportuno sottoli-

nearne pregi e difetti, in modo da fornire un valido sistema di confronto con la

metodologia proposta in questo documento.

OCP Socket è uno standard progettato molto dettagliatamente che ha sicura-

mente buone possibilità di affermarsi, soprattutto perchè è sostenuto da una reale

organizzazione che si occupa della sua diffusione. Ciò nonostante, affinchè un

core sia effettivamente portabile su sistemi esistenti che non adottano il bus OCP,

è necessario introdurre un ulteriore livello di logica (il bus wrapper) che appe-

santisce il modulo hardware. Oltre a quanto detto lo strumento di generazio-

ne automatica che viene proposto, ovvero CoreCreator, è in grado di generare

l’interfaccia di comunicazione solamente per la connessione al bus OCP.

Interface Adaptor Logic, pur essendo più leggera, soffre degli stessi difetti di

OCP Socket, in quanto anche in questo caso è necessario implementare opportuni

bus wrapper per l’effettiva portabilità dei componenti. Inoltre tale progetto sembra

essere stato abbandonato, siccome non si trovano riferimenti a sviluppi ulteriori.

EDK Create/Import Peripheral Wizard è un tool molto utile per importare core

in un sistema EDK, ma non offre una reale soluzione per l’interfacciamento di

core già esistenti, in quanto si limita a fornire un template per le interfacce OPB

IPIF e PLB IPIF.

Infine, Impulse CoDeveloper rappresenta un framework molto valido per quan-

to riguarda la sintesi di sistemi a partire da specifiche di alto livello, ed ha il pregio

di supportare numerose infrastrutture di comunicazione. Ciò nonostante, la fun-

zionalità che offre l’interfacciamento automatico è applicabile solamente ai core

generati dal software a partire dalla specifica, i quali presentano un insieme di

porte sempre identico. Poiché si il set di sagnali da gestire è conosciuto a priori,

la creazione dell’interfaccia risulta essere un compito meccanico.

32

Capitolo 3

Infrastrutture di comunicazione

Il software presentato in questo lavoro di tesi ha la finalità di interfacciare i core

dati in input con il resto del sistema nel quale si troveranno ad operare. Per questo

motivo prima di descrivere il framework vengono illustrate le infrastrutture di

comunicazione che IPGen supporta ad oggi.

La prima architettura che viene presentata utilizza il bus OPB (On-chip Peri-

pheral Bus) assieme alle interfacce implementate da Xilinx per rendere più sem-

plice l’interfacciamento dei core con il bus; queste sono due e si chiamano PSelect

e IP-Core Interface (IPIF) nella versione OPB. Successivamente viene data una

breve descrizione del bus Wishbone, il quale fornisce la stessa funzionalità del

precedente, ma a differenza di questo non presenta delle interfacce già sviluppate

da terzi per facilitarne l’uso. Esso fornisce infatti un protocollo di facile utilizzo, e

una logica per gestire la comunicazione molto meno complessa da implementare.

Sono state scelte queste particolari architetture in quanto, come visto nella

sezione 1.1.4, OPB viene utilizzato nel flusso di Caronte, mentre Wishbone in

quello di YaRA. Questo permette al software di essere adottato fin da subito come

parte integrante di questi due flussi, mostrandone le potenzialità in un contesto che

mira al maggiore automatismo ottenibile in fase di progettazione hardware. Nel

capitolo 5 viene spiegato come IPGen possa essere ampliato al fine di contemplare

sempre più infrastrutture.

33

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

3.1 IBM CoreConnect OPB

La progettazione modulare dello hardware, sezione 1.1.1, permette di ottenere si-

stemi composti da tanti moduli ognuno con funzionalità proprie e ben distinte. Un

sistema nel quale tutti questi componenti vengono integrati all’interno dello stes-

so chip viene chiamato System-on-Chip (SoC) [16]. In uno scenario come questo

sorge l’esigenza di una infrastruttura di comunicazione che sia efficiente e per-

metta in modo relativamente semplice di connettere tra di loro componenti le cui

funzionalità sono state sviluppate separatamente le une dalle altre. CoreConnect

[17] è un’architettura realizzata da IBM composta da tre bus e dai loro protocolli

di comunicazione, che ha lo scopo di fornire un’infrastruttura di comunicazione

tra i vari moduli di un SoC. I tre bus che compongono l’architettura sono:

• Processor Local Bus (PLB): bus a 64 bit pensato per dispositivi che neces-

sitano di prestazioni elevate e bassa latenza, utilizzato prevalentemente per

connessioni dirette al processore, che può essere PowerPC o Microblaze;

• On-Chip Peripheral Bus (OPB): bus a 32 bit utilizzato per sgravare il PLB

da una parte del traffico dati e per evitare colli di bottiglia nel sistema. Viene

utilizzato comunemente per applicazioni con minori necessita prestazionali.

• Device Control Register (DCR): bus sussidiario utile a ridurre il carico dei

due bus precedenti.

Il bus supportato da IPGen ed utilizzato in Caronte è OPB. Le caratteristiche

fondamentali di questo bus sono [18, 19]:

• Un protocollo completamente sincrono con 32 bit dedicati al bus dati e

altrettanti per il bus indirizzi;

• Dimensione del bus dinamica per permettere trasmissioni di dati inferiori a

32 bit (byte steering);

• Un protocollo che consente l’invio di segmenti sequenziali di dati (burst);

• Supporto per più di un OPB Master contemporaneamente.

34

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

Figura 3.1: Set di segnali visti all’interfaccia con un componente slave

In figura 3.1 è mostrato il set di segnali visti all’interfaccia di un componente di

tipo slave, per i quali il framework garantisce l’interfacciamento. Si precisa che

tali segnali sono da considerarsi attivi alti e, secondo la specifica del bus, devono

essere campionati sul fronte di salita del clock.

Vengono ora spiegate le funzionalità di questi segnali (tra parentesi quadre

verrà indicata la larghezza in bit dei segnali).

• Segnali in ingresso nel componente.

– OPB_Clk [1]: segnale di clock;

– OPB_Rst [1]: segnale di reset;

– OPB_Abus [32]: bus indirizzi, contiene l’indirizzo del registro sul

quale si vuole effettuare un’operazione di lettura/scrittura; l’indirizzo

presente sul bus è da considerarsi valido solo se il segnale OPB_select

è attivo;

35

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

– OPB_BE [4]: segnale Byte Enable che permette la trasmissione di

particolari byte di dati presi da un registro, quando non è necessaria la

trasmissione dell’intero registro;

– OPB_DBus [32]: bus dati in scrittura comandato dal master, il con-

tenuto del bus rimande valido finché il master non riceve il segnale di

acknowledgement di scrittura avvenuta con successo;

– OPB_RNW [1]: segnale Read Not Write, ha lo scopo di indicare la

direzione del trasferimento dati in corso; se il segnale è posto a 1 il

Master sta compiendo un’operazione di lettura sullo slave, al contrario

se è posto a 0 è in corso un’operazione di scrittura;

– OPB_Select [1]: segnale di select, indica che vi è un trasferimento

in corso lungo la linea dati; inoltre valida il contenuto dei segnali

OPB_ABus, OPB_BE, OPB_RNW e OPB_seqAddr. Rimane atti-

vo finchè il master non riceve un segnale di acknowledgement o di

transfer retry;

– OPB_seqAddr [1]: segnale di trasferimento sequenziale, indica allo

slave che il trasferimento successivo avverrà nella stessa direzione e

sull’indirizzo successivo all’attuale. Questo segnale non implica l’u-

tilizzo del protocollo “burst”. Questa modalità di comunicazione, che

non verrà approfondita in questo testo, è utile per l’invio in cicli di

clock successivi di uno stesso dato più grosso della capacità del bus e

quindi spezzato in pacchetti più piccoli.

• Segnali uscenti dal componente (il prefisso “<Sln>_” indica l’appartenenza

del segnale ad un generico slave):

– <Sln>_DBus [32]: bus dati in lettura comandato dallo Slave, il con-

tenuto rimane valido finchè il segnale <Sln>_xferAck non viene sol-

levato e riportato a 0;

– <Sln>_xferAck [1]: segnale OPB Transfer Acknowledge, sollevato

dallo slave per indicare il completamento di un’operazione di comu-

nicazione tra il master e lo slave. Esso rimane attivo per un ciclo di

36

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

clock per ogni operazione da notificare. Nel caso di un’operazione di

scrittura significa che lo slave ha correttamente accettato il dato, nel

caso di lettura significa che lo slave ha posto sul bus dati in uscita il

dato richiesto dal master. Inoltre questo segnale deve essere attivato

non oltre 16 cicli di clock dal momento in cui OPB_select viene posto

a 1, altrimenti questo ritardo verrà interpretato come timeout;

– <Sln>_retry [1]: segnale di retry, viene utilizzato per indicare una

situazione in cui lo slave temporaneamente non può portare a termine

un’operazione I/O richiesta dal master. È un segnale molto utile nella

prevenzione di possibili deadlock nell’arbitraggio del bus;

– <Sln>_toutSup [1]: segnale con il quale viene indicata l’impossibilità

di effettuare un’operazione richiesta dal master prima dello scadere

dei 16 cicli di clock dall’attivazione di OPB_select. Il segnale deve

rimanere a 1 finchè l’operazione prorogata non viene completata;

– <Sln>_errAck [1]: segnale utilizzato per notificare al master un errore

di lettura o scrittura.

Oltre ai segnali elencati, possono essere utilizzati dei segnali opzionali che dipen-

dono dalla funzionalità specifica del modulo, un esempio di tali segnali sono quelli

di interrupt.

3.1.1 OPB PSelect

La prima interfaccia implementata da Xilinx che viene descritta è OPB PSelect.

Essa consiste in un unico file (pselect.vhd) che svolge la sola funzione di Address

Decoding Logic, ovvero gestisce semplicemente la codifica degli indirizzi cor-

rispondenti ai registri del componente dove il Master del bus andrà a leggere o

scrivere. Per questo motivo viene utilizzata assieme a core che non hanno esigen-

ze particolari quali gestione di interrupt e di registri con dimensione differente da

32 bit.

Si spiega il comportamento del’interfaccia PSelect analizzando i suoi generic,

ovvero le costanti che possono essere impostate dal progettista secondo le esi-

37

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

genze della funzionalità del core, e i suoi segnali di I/O. I generic di pselect.vhd

sono:

• C_AB: generic di tipo intero che identifica il numero dei bit più significativi

del bus indirizzi; questi bit sono identificativi del modulo slave mentre i

rimanenti corrispondono ai registri presenti all’interno di uno slave. Da ciò

si deduce che aumentando il numero dei bit significativi si diminuisce lo

spazio da dedicare ai registri interni.

• C_AW: generic di tipo intero corrispondente alla larghezza dal bus indirizzi

in numero di bit. Questo valore per OPB deve essere sempre uguale a 32;

• C_BAR: generic di tipo std_logic_vector che indica il base address del com-

ponente, se i bit dell’indirizzo chiamato dal master identificati dal C_AB

corrispondono ai bit del C_BAR, anch’essi identificati dal C_AB, allora

significa che il master ha chiamato proprio il componente al quale la pselect

appartiene, in questo caso viene posto ad 1 il segnale PS.

Di seguito vengono descritti i segnali:

• A: segnale di input avente la stessa larghezza del bus indirizzi (C_AW),

questo segnale dovrà essere connesso al segnale OPB_ABus;

• Avalid: segnale in input da un bit che dovrà essere connesso con il segnale

OPB_select;

• PS: segnale in output da un bit chiamato Peripheral Select, per la descrizione

vedere il generico C_BAR.

Se il componente da interfacciare richiede una maggiore varietà e complessi-

tà di servizi offerti, questa logica di decodifica indirizzi risulterà scomoda ed

incompleta, pertanto si dovrà ricorrere OPB IPIF, descritta nella prossima sezione.

38

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

Figura 3.2: Schema dei servizi e dei segnali IPIF

3.1.2 OPB IPIF

Xilinx, oltre a PSelect, ha sviluppato OPB IPIF (IP-Core Interface) [20], un’inter-

faccia più completa che offre una codifica degli indirizzi maggiormente comoda

e funzionale, e molti servizi aggiuntivi che PSelect non fornisce. In figura 3.2 si

può vedere uno schema che identifica i vari servizi di cui IPIF è composta, oltre

ai suoi vari segnali sia lato core che lato bus. Mediante l’uso dei generic è data

possibilità allo sviluppatore di attivare o disattivare una parte di questi servizi a

seconda delle necessità dell’IP-Core che si vuole interfacciare; in questo caso il

valore di tali generic è assegnato in modo automatico da parte di IPGen. La parte

dell’interfaccia che rappresenta l’insieme dei segnali direttamente connessi al core

viene chiamata IP-Core InterConnect (IPIC).

39

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

3.1.2.1 I Servizi

Prima di analizzare in dettaglio il meccanismo di codifica degli indirizzi ed il sig-

nificato dei vari segnali IPIC, viene fornita una panoramica dei vari moduli che

compongono l’interfaccia. L’elemento base di IPIF è lo Slave Attachment; es-

so è infatti il responsabile della mediazione diretta tra il bus e IPIC, gestisce il

protocollo di comunicazione con OPB e fornisce le porte di I/O per tutti i se-

gnali indispensabili alla comunicazione con il bus. Un servizio opzionale inter-

no allo Slave Attachment è il Burst Support, il quale permette di utilizzare una

modalità di trasferimento dati che consente velocità elevate con accesso a indirizzi

sequenziali.

Un secondo componente è il Byte Steering, che permette la trasmissione in

entrambe le direzioni di dati con una larghezza inferiore di quella del bus (32

bit). Grazie a questo componente possono essere letti o scritti solo alcuni byte

dei registri interessati grazie alla sua capacità di instradare questi blocchi nelle

corrette byte lanes del bus.

Oltre a questi due servizi, presenti in ogni configurazione di IPIF, vi sono i

servizi opzionali. Fa parte di questo gruppo il servizio Hardware/Software Reset.

Esso è aggiuntivo rispetto al normale evento di reset sollevato quando il segna-

le OPB_Rst viene reso attivo, infatti permette un reset dell’IP-Core eseguito dal

processore via software, scrivendo un particolare valore chiave all’interno del re-

gistro dedicato a questo particolare servizio. Inoltre H/S Reset è accompagnato

dall’istanziazione di un particolare registro chiamato MIR (Module Information

Register) contenente le informazioni indicanti la configurazione di default del mo-

dulo; tramite questo registro l’IP-Core può essere riportato in uno stato di partenza

“sicuro” prestabilito dal progettista.

Un’altra funzionalità che può essere attivata riguarda la gestione degli inter-

rupt. L’Interrupt Service Controller mette a disposizione un componente che

è in grado di ricevere le varie richieste di interrupt, sia da parte del core che

dall’interfaccia stessa, e di collassarle in un unico segnale che verrà portato a

OPB.

Infine vi sono i servizi di Write FIFO e Read FIFO. Questi vengono utilizzati

40

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

quando l’IP-Core necessita di “bufferizzare” i dati, e possono essere attivati in-

dipendentemente l’uno dall’altro a seconda delle direzioni (lettura/scrittura) nelle

quali vi è la necessità di un buffer.

IPGen è in grado di sfruttare l’address decoding di IPIF insieme a tutte le sue

funzioni di base; tra i possibili sviluppi futuri del software vi è il pieno suppor-

to ai restanti servizi di IPIF. Si noti comunque che alcuni di questi servizi ven-

gono implementati automaticamente da porzioni di logica generate dal software.

Per esempio esso è in grado di gestire segnali con dimensioni maggiori di 32 bit

tramite un particolare protocollo descritto dettagliatamente nella sezione 5.3.5. Il

motivo di queste scelte è da ricercare nel fatto che spesso i servizi messi a dis-

posizione da IPIF comportano un overhead non trascurabile e la gestione di essi

risulta in molti casi molto macchinosa.

3.1.2.2 Decodifica degli indirizzi

IPIF gode di un sistema di decodifica degli indirizzi che rende molto agevole l’i-

dentificazione dei vari registri all’interno di un core per operazioni di lettura e

scrittura. Poiché l’interfaccia deve essere flessibile e potersi integrare a qualsiasi

tipo di core, questa decodifica avviene raggruppando i vari registri interni al core

in Address Ranges ognuno dei quali ha delle proprietà ben definite che coinvol-

gono tutti i registri appartenenti ad uno stesso range. IPIF è in grado di trattare

adeguatamente i diversi “range” poiché questi vengono definiti in apposite Ad-

dress Range Definitions. Queste vengono dichiarate all’interno di un set di cinque

array di generic caratterizzati dal prefisso “C_ARD”:

• C_ARD_ID_ARRAY: array che associa un numero intero di identificazione

ad ogni address range;

• C_ARD_ADDR_RANGE_ARRAY: in questo array vengono dichiarati, a

coppie, il base address e l’high address di ogni address range;

• C_ARD_DWIDTH_ARRAY: qui viene specificata la dimensione dei sin-

goli registri appartenenti allo stesso address range, ovviamente tutti i re-

gistri di uno stesso address range avranno la stessa dimensione. Grazie a

41

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

queste informazioni IPIF sarà in grado di operare byte steering su registri di

dimensione inferiore a quella del bus OPB;

• C_ARD_NUM_CE_ARRAY: la codifica di indirizzi di IPIF permette di as-

segnare un Chip Enable (CE) per ogni registro di un address range. Questo

rappresenta una caratteristica molto utile nell’interfacciamento di un core

in quanto, come descritto nel prossimo paragrafo, permette una gestione dei

registri più semplice e intuitiva;

• C_ARD_DEPENDENT_PROPS_ARRAY: in questo array vengono dichiarate

proprietà dei registri che dipendo dal particolare tipo di address range di

appartenenza.

È importante sottolineare che l’impostazione di questi parametri all’interno di

IPIF viene svolta in automatico da IPGen. Il risultato di questa decodifica viene

propagato al core attraverso alcuni dei segnali uscenti da IPIC, che viene descritto

nel paragrafo seguente.

3.1.2.3 IPIC

IPIC è la parte dell’interfaccia rivolta verso il core; attraverso i suoi molteplici

segnali permette al core di comunicare con l’interfaccia e quindi con il bus. Di

seguito sono mostrati brevemente i segnali più importanti.

• Segnali in uscita da IPIC:

– Bus2IP_Clk: segnale che trasmette il clock di sistema dal bus al core;

– Bus2IP_Reset: segnale che trasmette al core il segnale di reset di

sistema;

– Bus2IP_Data: bus dati in scrittura sui registri del core, la grandezza è

variabile e dipende da come è stata impostata l’interfaccia;

– Bus2IP_Addr: di grandezza 32 bit, è una copia esatta dell’indirizzo

che arriva ad IPIF tramite il bus indirizzi di OPB;

42

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

– Bus2IP_RNW: questo segnale identifica se un’operazione è di scrit-

tura (0) o di lettura (1);

– Bus2IP_CS: la grandezza di questo segnale dipende dal numero di

voci presenti nell’array di generic C_ARD_ID_ARRAY ed ha la fun-

zione di abilitare un address range per permettere di effettuare opera-

zioni su di esso.

– Bus2IP_RdCE: la grandezza in questo caso rappresenta il numero to-

tale di registri di tutto il dispositivo; vi sarà al più un 1 e rappresenta il

registro sul quale verrà effettuata l’operazione di lettura;

– Bus2IP_WrCE: identico al precedente, utilizzato per le operazioni di

scrittura;

• Segnali in ingresso ad IPIC:

– IP2Bus_IntrEvent: segnale con grandezza dipendente dal numero di

interrupt che sono stati dichiarati, tramite un apposito generic, e che

l’Interrupt Service Controller è stato eventualmente predisposto a ge-

stire;

– IP2Bus_Data: bus dati in lettura dei registri del core, la dimensione

viene fissata a priori nel momento in cui viene configurata l’interfac-

cia;

– IP2Bus_Ack: segnale di acknowledge, per una transazione di scrittura,

il dato viene considerato correttamente scritto quando il clock è sul

fronte di salita e questo segnale è attivo;

– IP2Bus_Retry: questo segnale è reso attivo quando l’IP-Core non è

stato in grado di completare un’operazione e chiede che essa venga

riproposta da parte del Master;

– IP2Bus_Error: segnale che, se posto ad 1, indica un errore verificatosi

durante l’operazione corrente;

43

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

Oltre ai segnali sopra elencati vi sono set di segnali per la gestione dei registri

Read FIFO e Write FIFO e per il supporto del protocollo di Burst, questi segnali ed

i relativi servizi non sono attualmente supportati da IPGen e rientrano nei possibili

sviluppi futuri del tool.

3.1.2.4 Modalità di utilizzo

IPIF, ed in particolare la sua logica di decodifica degli indirizzi, può essere sfrut-

tata dal progettista seguendo due modelli o modalità di utilizzo. Il primo di questi

modelli si chiama Register Model. Il progettista opta per questo modo d’uso

quando vuole utilizzare appieno la logica di decodifica offerta dall’interfaccia e

prevede, come descritto sopra, l’assegnamento ad ogni registro interno al core di

un bit di Chip Enable (CE) che lo identificherà univocamente. In questo caso

le operazioni sul core vengono pilotate dai segnali Bus2IP_CE, Bus2IP_RdCE e

Bus2IP_WrCE a seconda della tipologia di registro utilizzato in un dato momen-

to. Vi possono essere registri di sola lettura, di sola scrittura o entrambe. IPGen è

stato programmato per fare uso di questa modalità per la gestione dei registri.

La seconda modalità si chiama Memory Model o SRAM Model. In questo caso

si fa uso della codifica tramite Chip Select (CS); l’informazione data da tale segna-

le, che identifica gli address range e non più i singoli registri, deve essere accom-

pagnata dall’informazione sul tipo di operazione da effettuare (lettura/scrittura) e

dai bit di indirizzo per identificare il punto nell’address range dove effettuare l’op-

erazione. Questo secondo modello è più di “basso livello” e, pur avendo il pregio

di lasciare più libertà d’azione nello spazio degli indirizzi, si presta meno ad es-

sere automatizzato rispetto al precedente, quindi il suo utilizzo nel framework è

stato scartato prediligendo il register model.

3.2 Wishbone

Viene analizzata ora il secondo tipo di infrastruttura, costituita dal bus Wishbone

e dai suoi protocolli [21]. Questo bus è stato implementato da Silicore per fornire

un canale di comunicazione ai vari moduli di un SoC, e così come il precedente ha

44

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

Figura 3.3: Le interfacce Wishbone lato master e lato slave

il grande pregio di essere di dominio pubblico e di poter quindi essere utilizzato

nel design di circuiti integrati senza l’obbligo di pagarne la licenza d’uso. Un altro

punto di forza di Wishbone sta nella sua semplicità d’uso, infatti non sono state

sviluppate delle interfacce dedicate, come per OPB, proprio perché non ve ne è

la necessità. E’ stato definito da Silicore uno standard per l’utilizzo di questo bus

che descrive in dettaglio il modo in cui i componenti devono essere interfacciati,

il protocollo per lo scambio di informazioni tra master e slave, e quattro tipologie

di modalità di interconnessione tra master e slave. Vengono dapprima descritti

i segnali di interfaccia del master e dello slave e a seguire le varie tipologie di

connessione.

3.2.1 Le interfacce

Vi sono due tipologie di interfaccia, una per il componente master ed una per lo

slave, queste devono essere adottate da tutti i componenti del sistema che fa uso di

Wishbone. Le due interfacce sono molto simili la tra di loro, dato che si differen-

ziano solamente per la direzione dei segnali che le compongono. In figura 3.3

sono indicati i vari segnali; con il prefisso “_I” vengono indicati i segnali entranti,

mentre con “_O” quelli uscenti. Di seguito vengono descritti questi segnali dal

punto di vista del master:

45

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

• RST_I: segnale di reset del sistema, se sollevato indica al componente di

ritornare al suo stato iniziale;

• CLK_I: clock di sistema;

• ADR_O: rappresenta il bus indirizzi di Wishbone; può avere dimensione

variabile fino ad un massimo di 32 bit e viene utilizzato dal master per

indicare al sistema il registro di un particolare slave;

• DAT_I: bus dati da 32 bit, in ingresso;

• DAT_O: bus dati da 32 bit, in uscita;

• WE_O: segnale Write Enable, indica se l’operazione corrente è di scrittura

o di lettura. Segnale alto indica scrittura da parte del master su un registro

di uno slave, mentre segnale basso indica lettura da registro.

• SEL_O: indica quali dei byte che compongono il bus dati sono da con-

siderarsi validi. Poiché il bus dati ha grandezza 4 byte, questo segnale è

costituito da 4 bit, uno per ogni byte selezionabile;

• STB_O: segnale sollevato indica che tutti i segnali di controllo sono pronti

e stabili. Da questo momento può iniziare una fase di lettura o scrittura;

• ACK_I: indica la fine di un processo completato correttamente da parte

dello slave;

• ERR_I: indica un malfunzionamento dello slave con conseguente esito ne-

gativo di un’operazione;

• RTY_I: se posto ad 1 lo slave non è temporaneamente disponibile, il master

dovrà ricontattarlo in un secondo momento;

• CYC_O: indica l’inizio di un ciclo di controllo da parte del master.

Non viene fornito l’elenco dei segnali slave poiché è identico a meno dei versi di

I/O. Fanno eccezione a questa regola i segnali di clock e reset, essendo entranti

per entrambe le interfacce.

46

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

3.2.2 Protocollo di comunicazione

I segnali sopra citati vengo utilizzati seguendo un protocollo di comunicazione, di

questo protocollo vengono mostrate le parti fondamentali, ovvero i cicli di lettura

da slave e scrittura su slave.

• Ciclo di lettura:

1. Il master pone ad 1 il segnale CYC_O, in questo modo prende il

controllo del bus;

2. Pone sul bus indirizzi ADR_O l’indirizzo dello slave interessato dal

ciclo di lettura, contemporaneamente pone a 0 il segnale WE_O;

3. Solleva STB_O ad indicare che tutti i segnali sono correttamente im-

postati e stabili, l’operazione di lettura può avere inizio;

4. Lo slave indirizzato precedentemente controlla che i segnali CYC_I e

STB_I siano alti, scrive sul bus dati in uscita DAT_O il dato richiesto,

che verrà letto dal master dal proprio ingresso DAT_I;

5. Lo slave innalza ACK_O;

6. Quando il master rileva su ACK_I il segnale di acknowledgement du-

rante il seguente fronte di salita del clock legge il dato presente su

DAT_I;

7. Il master abbassa CYC_O e STB_O;

8. Quando lo slave rileva il passaggio a 0 dei segnali abbassati al punto

precedente, pone il proprio ACK_O a 0.

• Ciclo di scrittura:

1. Il master pone ad 1 il segnale CYC_O, in questo modo prende il

controllo del bus;

2. Pone sul bus indirizzi ADR_O l’indirizzo dello slave interessato dal

ciclo di scrittura, contemporaneamente pone a 1 il segnale WE_O e

scrive il dato da trasmettere su DAT_O;

47

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

Figura 3.4: Schema della connessione “Data Flow”

3. Solleva STB_O ad indicare che tutti i segnali sono correttamente im-

postati e stabili, l’operazione di scrittura può avere inizio;

4. Lo slave indirizzato aspetta che i segnali CYC_I e STB_I vengano

alzati, successivamente legge il dato su DAT_I;

5. A questo punto lo slave pone ACK_O ad 1;

6. Riconosciuto l’ack, il master tiene il dato sul bus dati fino al successivo

fronte di salita del clock;

7. Il master abbassa CYC_O e STB_O;

8. Quando lo slave rileva il passaggio a 0 dei segnali CYC_O e STB_O,

abbassa il proprio segnale di ack.

3.2.3 Tipi di connessione

I vari componenti di un SoC possono essere connessi, tramite Wishbone, seguendo

quattro modalità di connessione. La scelta tra le varie tipologie dipende dalla

complessità del sistema e dagli IP-Core presenti al suo interno. Segue una breve

descrizione di questi tipi di connessione in ordine di complessità.

• Point to Point: questa è la connessione più semplice e consiste in un col-

legamento punto a punto tra un solo master con un solo slave. La semplicità

di questo sistema fa si che non sia richiesta nè un logica di decodifica degli

indirizzi nè un meccanismo di collision detection sul bus.

48

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

Figura 3.5: Schema della connessione “Shared Bus Interconnection”

• Data Flow: sfrutta il principio della connessione punto a punto preceden-

temente illustrato, ma in questo caso è consentito collegare una serie di

IP-Core contenenti una coppia Master-Slave in cascata tra di loro. Questa

configurazione, mostrata in figura 3.4, è molto utile in applicazioni dove un

flusso di informazioni deve subire molte elaborazioni successive, ognuna

delle quali necessita dell’output della precedente. In questo caso vi è la ne-

cessità di una semplice logica di decodifica di indirizzi per indirizzare i dati

al componente corretto.

• Shared Bus Interconnection: questo scenario rispecchia la configurazione

più tipica di interconnessione, ovvero il bus condiviso tra i vari compo-

nenti (figura 3.5), ovviamente è obbligatoria la presenza di una logica di

decodifica di indirizzi e di un sistema di collision detection.

• Crossbar Interconnection: si tratta della tipologia più complessa di con-

nessione. Anziché avere un unico bus condiviso, permette la comunicazione

tra differenti coppie master-slave contemporaneamente tramite una rete di

49

CAPITOLO 3. INFRASTRUTTURE DI COMUNICAZIONE

Figura 3.6: Schema della connessione “Crossbar Interconnection”

connessioni tra componenti e degli switch che fisicamente allacciano e sgan-

ciano le linee di comunicazione tra di loro. Una possibile combinazione

viene mostrata in figura 3.6.

Tra le varie alternative proposte, il framework fa uso della Shared Bus Intercon-

nection. Per sfruttare la condivisione del bus, l’interfaccia generata da IPGen

contiene una logica di decodifica degli indirizzi che permette di rilevare la volon-

tà del master di effettuare un’operazione sull’IP-Core, oltre ad identificarne un

particolare registro.

L’architettura che fa uso di questo tipo di connessione deve avere uno spazio

di indirizzamento ad 8 bit di cui: i primi 3 da sinistra costituiscono il Core Ad-

dress mentre i restanti 5 compongono il Register Address. Da ciò si deduce che

potranno essere istanziati un massimo di 8 core nel sistema e ciascun core avrà

non più di 32 registri. La logica di decodifica confronta il Core Address con i 3

bit più significativi del base address dell’IP-Core, se questi coincidono significa

che il master vuole interagire con l’IP-Core. A questo punto viene identificato il

corretto registro confrontando i bit del Register Address con gli indirizzi assegnati

a ciascuna porta del core.

50

Capitolo 4

Metodologia

Questo capitolo ha la finalità di fornire una descrizione di IPGen dal punto di vista

metodologico. Nel paragrafo seguente vengono spiegate le motivazioni che hanno

spinto alla creazione di un software per l’interfacciamento automatico, assieme

agli obiettivi preposti alla sua realizzazione. Successivamente è mostrato come

IPGen si possa collocare in un contesto più ampio, costituito dal workflow di

Caronte (sezione 1.1.4). Dopo aver descritto in dettaglio la struttura degli IP-

Core generati, illustrandone i vari componenti, viene descritto il procedimento

metodico che il programma compie per passare dall’input dell’utente al risultato

finale. Il capitolo si conclude con un confronto tra la metodologia proposta da

questo lavoro e quelle adottate dagli approcci precedenti (sezione 2) al problema

dell’interfacciamento automatico, evidenziando differenze, analogie e possibili

integrazioni.

4.1 Motivazioni

Il processo di realizzazione di un sistema hardware richiede lo sviluppo di molti

prototipi prima di poter arrivare ad un risultato soddisfacente e quindi ad un siste-

ma che può essere messo sul mercato. La fase di progettazione quindi può far si

che il time-to-market del prodotto si allunghi notevolmente, con un conseguente

ritardo per chi lo dovrà commercializzare o utilizzare per attività di ricerca. Buona

51

CAPITOLO 4. METODOLOGIA

parte del tempo impiegato nello sviluppo di un prototipo deriva dal problema di far

comunicare i componenti costituenti il sistema complessivo tra di loro mediante

un’opportuna infrastruttura di comunicazione, per esempio un bus.

L’interfacciamento dei moduli è una fase molto ripetitiva e poco creativa per

il progettista, il quale ha come principale obiettivo lo sviluppo di un componente

in quanto risolutore di un problema o comunque esecutore di una preposta funzio-

nalità. Da questo punto di vista l’interfacciamento risulta essere un problema con

il quale ci si deve per forza confrontare, ma costituisce un collo di bottiglia nel

processo di sviluppo di un sistema hardware. Essendo esso però molto ripetitivo

è un’operazione che può essere automatizzata.

Ogni singolo componente di un’architettura è un IP-Core nel quale, come visto

nella sezione 1.1.2.2, possono essere ben distinte la parte funzionale, il core, e la

parte costituente l’interfaccia verso il resto del sistema. Se ci fosse un meccanismo

che, dato il core, riuscisse a creare l’interfaccia in modo automatico, il tempo

speso da parte del progettista nell’implementazione di questa verrebbe azzerato.

Questo è l’intento di IPGen.

Grazie a questo strumento il progettista può implementare la sua funziona-

lità senza curarsi della tipologia di architettura nella quale andrà ad inserirsi il

suo componente finale. In questo modo viene aumentato il grado di riusabilità di

un core, in quanto esso potrà essere inserito e riutilizzato in una molteplicità di

sistemi differenti. Esso rimarrà sempre inalterato, sarà la parte relativa all’inter-

facciamento ad essere rigenerata ogni volta in modo automatico dal software, in

base alle necessità e alle scelte progettuali riguardanti l’architettura ospite. Tutto

questo senza perdite di tempo da parte del progettista.

4.1.1 IPGen nel flusso di Caronte

IPGen ha un ruolo fondamentale nel flusso di Caronte, essendo necessario durante

la fase di generazione delle Foto Statiche (HW-SSP, vedere sezione 1.1.4). Questo

processo può essere completamente automatizzato tramite due fasi, descritte in

figura 4.1:

52

CAPITOLO 4. METODOLOGIA

• IPGen Phase. In questa fase viene utilizzato IPGen, che prende i sin-

goli core e li trasforma in IP-Core aggiungendovi l’interfaccia opportuna

e rendendoli quindi pronti ad essere inseriti in una Static Photo.

• EDK System Creator Phase. EDK System Creator [22] è uno strumen-

to sviluppato all’interno del Politecnico di Milano che permette di inserire

un IP-Core in un’architettura compatibile con EDK in modo automatico.

Questo programma riceve in ingresso l’IP-Core da inserire e il sistema

nel quale verrà integrato, assieme ad un file di configurazione contenente

gli indirizzi fisici che determinano l’allocazione dell’IP-Core sulla FPGA.

Fondamentalmente EDK System Creator esegue due operazioni:

– importa l’IP-Core settando tutti i parametri in modo tale che esso possa

essere trattato come un componente EDK;

– inserisce l’IP-Core nell’architettura ricevuta in input dal programma.

In questo caso il sistema ospite è costituito da un’architettura come quella

descritta nella sezione 1.1.4.1, le cui black box sono completamente vuote,

denominato EDK general system. Grazie ad un opportuno file di confi-

gurazione contenente le informazioni sulle varie HW-SSP da generare, è

possibile rendere la creazione di queste ultime completamente automatica.

Come si può notare l’uso congiunto di IPGen e EDK System Creator permet-

te di ottenere un rilevante risparmio di tempo grazie ad un elevato automatismo

dell’intero processo.

4.2 Struttura dell’IP-Core generato

Nonostante la struttura di un IP-Core generato da IPGen cambi a seconda del tipo

di bus con il quale esso viene interfacciato, il principio base comune è quello

di incapsulare il core dato in input dall’utente all’interno di un componente più

grande che lo istanzi assieme alla logica di interfacciamento.

53

CAPITOLO 4. METODOLOGIA

Figura 4.1: Flusso di creazione delle HW-SSP

Come si può osservare da un confronto tra le figure 4.2 e 4.3, poiché OPB

richiede l’istanziazione di un’interfaccia che è un vero e proprio componente di-

verso rispetto al core di partenza, vi saranno due livelli di incapsulamento nell’IP-

Core generato in output, mentre per quanto riguarda il bus Wishbone ne avremo

soltanto uno. Viene ora fornita una descrizione di queste due diverse strutture

partendo dal livello più basso fino ad arrivare al top level.

4.2.1 Core

Esso è l’input fornito dall’utente ad IPGen e rappresenta il cuore del componente,

ovvero la funzionalità che esso svolge. Nel core si trovano i registri e la logica atti

ad espletare la funzionalità propria del componente, senza riferimenti all’infras-

truttura di comunicazione. Proprio per questo esso è la parte riusabile dell’IP-Core

in quanto è indipendente dal sistema nel quale verrà inserito. Per quanto detto non

vi è alcuna differenza strutturale tra i core in figura 4.2 e 4.3.

54

CAPITOLO 4. METODOLOGIA

Figura 4.2: Struttura di un core interfacciato con OPB

Figura 4.3: Struttura di un core interfacciato con Wishbone

55

CAPITOLO 4. METODOLOGIA

4.2.2 Stub

Questo componente viene generato separatamente dalla struttura dell’IP-Core so-

lo in caso di interfacciamento OPB; nel caso Wishbone le funzionalità presenti in

questo livello vengono integrate all’interno del top level. La necessità di questo

componente aggiuntivo nasce dal fatto che la connessione con OPB richiede l’u-

so di un’interfaccia complessa che è un componente a parte rispetto alla logi-

ca contenuta nel core. Lo Stub permette al core e all’interfaccia di comunicare

correttamente; in particolare esso istanzia il core e fornisce la logica che con-

sente di sfruttare i segnali IPIC (vedi sezione 3.1.2.3) per effettuare le proce-

dure di scrittura, lettura, sollevamento di interrupt ed elaborazione dei segnali

di acknowledgement.

Esso si comporta come un demultiplexer per i segnali provenienti dal siste-

ma verso il core e come un multiplexer per i segnali diretti nel verso opposto;

questo comportamento viene ottenuto mappando opportunamente le linee dati in

ingresso/uscita sulle porte del core utilizzando i segnali derivanti dalla decodifi-

ca degli indirizzi attuata dall’interfaccia, ottenendo in questo modo un corretto

indirizzamento nei vari registri.

4.2.3 IP-Core

Con il termine IP-Core si intende il top level di un componente interfacciato;

esso rappresenta ciò che viene visto da parte del sistema. Per i motivi visti in

precedenza, è diverso a seconda del bus adottato dal sistema nel quale dovrà essere

inserito.

Nel caso di bus OPB è infatti necessaria l’istanziazione di una delle due inter-

facce CoreConnect descritte nella sezione 3.1 e dello stub. I segnali provenienti

dal bus sono in contatto con una di queste due interfacce, che tramite i loro servizi

forniscono allo Stub le informazioni necessarie a compiere tutte le operazioni sul

core.

Nell’interfacciamento con bus Wishbone invece il top level integra tutte le fun-

zioni che nel caso precedente sono incluse nello Stub; questo è possibile poiché,

56

CAPITOLO 4. METODOLOGIA

come descritto nella sezione 3.2.3, questo tipo di collegamento non ha bisogno di

una logica di decodifica particolarmente elaborata e viene quindi integrata diretta-

mente da IPGen senza necessità di componenti esterni. In definitiva, la descrizione

di un IP-Core in questo secondo tipo di interfacciamento conterrà la definizione

di tutte le porte che si rivolgono verso il sistema, l’istanziazione del core dato

in input dall’utente, la logica di decodifica degli indirizzi necessaria ad attuare i

processi di lettura e scrittura, e il mappaggio dei segnali tra core e bus.

4.3 Workflow di IPGen

Per generare un IP-Core partendo dalla funzionalità descrittà nel core, IPGen per-

corre un workflow diviso in due fasi principali; esse sono sequenziali e sono (in

ordine di esecuzione) la fase di lettura e quella di scrittura. La prima di esse si

occupa di ricevere e scansionare il core dato in input dall’utente, mentre la secon-

da si occupa della generazione dei file che descrivono l’IP-Core in output. Come

verrà visto più in dettaglio nella sezione 5.1, ognuna di queste fasi viene svolta

da un componente del framework dedicato: avremo quindi il reader per la fase di

lettura ed il writer per quella di scrittura.

4.3.1 Lettura

In figura 4.4 è schematizzato il flusso della fase di lettura eseguita dal “reader”

all’inizio dell’esecuzione di IPGen. Questo componente, in base al percorso del

file VHDL dato in input, dopo averne verificato l’esistenza, dà inizio ad una pro-

cedura chiamata clean phase. Essa viene eseguita da un modulo sussidiario al

reader chiamato cleaner, il quale legge la dichiarazione della entity del core e la

pulisce da eventuali commenti VHDL che potrebbero generare problemi di par-

sing nella fase successiva. Il reader quindi prosegue il suo flusso lavorando sulla

dichiarazione pulita precedentemente, effettuandone il parsing e, nel caso in cui

riconosca una dichiarazione ben formata, crea la lista dei segnali descritti in essa.

La stessa operazione viene eseguita nella sezione di dichiarazione dei generic, in

cui viene creata una lista contenente tutte le informazioni relative ad essi. A questo

57

CAPITOLO 4. METODOLOGIA

Figura 4.4: Flusso operativo del reader

punto viene richiesto all’utente quale modalità di interfacciamento desidera per il

suo core; avvenuta questa scelta il programma ha tutte le informazioni necessarie

alla generazione dell’IP-Core. Se i passi descritti fino ad ora terminano senza er-

rori, il reader passa il controllo del flusso di esecuzione e le liste precedentemente

salvate al “writer” predisposto a generare l’interfaccia selezionata.

4.3.2 Scrittura

Il tipo di writer che entra in funzione a questo punto dipende dal tipo di inter-

faccia selezionato dall’utente. Sono stati infatti implementati tre writer separati,

ognuno dedicato alla generazione di una delle interfacce descritte. Pur essendo

componenti a sé stanti, seguono lo stesso tipo di workflow. Il writer legge le infor-

mazioni elaborate nella fase precedente: il path del core, le liste dei segnali e dei

generic, e il nome della entity specificata nel core; in base a questi dati crea un file

58

CAPITOLO 4. METODOLOGIA

Figura 4.5: Flusso operativo del writer

VHDL per ogni livello della struttura dell’IP-Core da generare così come è sta-

ta descritta in precedenza. Tutti i dettagli implementativi di questa fase vengono

trattati nel capitolo 5.

4.4 Confronti con gli altri approcci

Avendo mostrato la metodologia proposta da questa tesi, è possibile a questo pun-

to effettuare dei confronti tra la nostra soluzione e quelle descritte nel capitolo

59

CAPITOLO 4. METODOLOGIA

2. Vengono presi inizialmente in considerazione i primi due approcci, cioè OCP

Socket e IAL, come già detto molto simili tra loro. Il primo punto fondamentale

da analizzare è l’intento che sta alla base delle diverse metodologie: si può dire

che l’obiettivo primario di questi due approcci è il riutilizzo degli IP-Core, tramite

il quale è possibile creare delle librerie di moduli utilizzabili in applicazioni e con-

testi architetturali differenti, con il risultato di velocizzare il flusso di lavoro per lo

sviluppo di sistemi hardware e disporre di IP-Core solidi e funzionanti. Per quan-

to riguarda IPGen, l’obiettivo primario è invece quello di velocizzare la creazione

degli IP-Core, soprattutto nell’ambito della riconfigurabilità dinamica. Il risultato

che si spera di ottenere è quello di un flusso completamente automatizzato che,

partendo da specifiche di alto livello, produca un sistema dinamicamente ricon-

figurabile passando tramite il workflow di Caronte (sezione 1.1.4). All’interno di

questo processo IPGen è necessario per generare in un tempo brevissimo e in mo-

do completamente automatizzato gli IP-Core necessari. In ogni caso, il software

sviluppato è utilizzabile con ottimi risultati anche in un’ottica di riutilizzo degli

IP-Core, in quanto esso è in grado di generare interfacce differenti per core che

sono generali, non essendo dipendenti dall’architettura che li ospita.

Dopo avere mostrato questa lieve discrepanza di intenti, si può notare che tutti

questi approcci adottano un metodo che si basa sulla stessa considerazione: per

ottenere un core che sia portabile su sistemi differenti è necessario stratificare la

struttura dell’IP-Core. La stratificazione implica infatti un disaccoppiamento tra

il core e l’architettura ospitante. Proprio in quest’ottica è possibile definire due

tipologie di componenti: core-centric, i quali sono indipendenti dall’infrastrut-

tura di comunicazione, e bus-centric, nei quali il collegamento con un particolare

mezzo trasmissivo è integrato e spesso impossibile da isolare e sostituire. Ovvia-

mente è la prima categoria di core che i diversi approcci utilizzano come punto di

partenza per raggiungere i propri obiettivi.

Da un punto di vista metodologico, si vede chiaramente come IPGen si col-

lochi ad un livello architetturale differente rispetto a OCP e IAL. Infatti, mentre il

primo si occupa di generare un IP-Core che opera mediante interfacce già esistenti

e diffuse, i secondi propongono uno standard di interfaccia nuovo, da diffondere

60

CAPITOLO 4. METODOLOGIA

il più possibile. Adottando però un’interfaccia comune, è necessario adottare dei

convertitori logici che colleghino in modo opportuno i segnali di comunicazione

dell’IP-Core con quelli molto spesso diversi del bus: tali componenti vengono

chiamati bus wrapper. Si perviene quindi alla seguente considerazione: se per

allacciare un IP-Core ad una particolare infrastruttura di comunicazione si rende

obbligatorio nella nostra metodologia implementare un writer opportuno (se non

già esistente), mentre negli altri due approcci è necessario scrivere un bus wrap-

per. Nonostante questa apparente equità, emerge a questo punto un dato a favore

di IPGen: esso è infatti in grado di generare automaticamente lo stub, il quale

contiene logica che non costituisce un overhead, in quanto comunque necessaria

alla comunicazione con un bus; gli altri due approcci introducono invece un com-

ponente aggiuntivo, il bus wrapper, che appesantisce necessariamente l’IP-Core

risultante. Quanto spiegato si può vedere chiaramente in figura 4.6. Inoltre la

funzione svolta dallo stub deve essere implementata manualmente dallo sviluppa-

tore adottando una della altre due metodologie, incrementando quindi il tempo di

creazione del core.

Figura 4.6: Confronto degli IP-Core risultanti utilizzando differenti approcci

61

CAPITOLO 4. METODOLOGIA

Dato che, come è stato appena mostrato, IPGen e OCP/IAL operano a livel-

li differenti, si può addirittura considerare una potenziale integrazione tra i due

differenti approcci: è infatti possibile pensare di creare un writer per IPGen che

adotta, per esempio, il Socket OCP.

Viene ora preso in considerazione EDK Create/Import Peripheral Wizard. Come

già detto, quest’ultimo opera solamente con le interfacce OPB IPIF e PLB IPIF, in

quanto è orientato ad interagire con EDK, che adotta i bus della famiglia CoreCon-

nect. Questo strumento possiede dunque una ristretta area di applicazione. Inoltre,

esso non si occupa in nessun modo dell’interfacciamento di core già esistenti con

uno specifico bus, poiché l’unica funzione significativa che offre è quella di gene-

rare un template vuoto nel quale collocare manualmente ed in un secondo momen-

to la descrizione VHDL della funzionalità. Quello che invece IPGen fa è generare

l’interfaccia prendendo in ingresso il core, fornendo in uscita un prodotto comple-

to. Anche in questo caso si può delineare in modo semplice un’integrazione tra

le due metodologie: un core generato automaticamente dal framework con inter-

faccia OPB IPIF può essere importato in un sistema EDK tramite la funzionalità

“import” fornita da EDK Create/Import Peripheral Wizard.

Impulse CoDeveloper offre la possibilità di generare l’interfaccia per collegare

il componente sintetizzato a una varietà di architetture molto vasta. In tal senso

esso si dimostra uno strumento molto versatile. Ciò nonostante, esso lavora, come

detto in precedenza, su moduli hardware che esso stesso genera, sintetizzandoli a

partire da una specifica C di alto livello. In generale dunque, il valore di questo

software non è da ricercare tanto nell’interfacciamento dei moduli, operazione

che a questo punto risulta quasi meccanica e banale, quanto nella capacità di sin-

tetizzare una specifica di alto livello in un sistema integrato hardware e software

in un tempo breve e in modo semplice per l’utente. Ovviamente una limitazione

ineliminabile di questa metodologia risiede nel fatto che l’utente deve apprendere

l’utilizzo delle librerie ImpulseC per scrivere il codice della specifica. Volendo ef-

fettuare un confronto con IPGen, si può affermare che quest’ultimo è stato proget-

tato tenendo conto di un core in ingresso che sia veramente “generico”, ossia non

presenti necessariamente un determinato set di porte. Questo perché, pur essendo

62

CAPITOLO 4. METODOLOGIA

stato pensato come componente integrante di un flusso che prende in ingresso una

specifica di alto livello e genera un sistema dinamicamente riconfigurabile, esso

mantiene comunque intatta la propria identità di software stand-alone.

63

Capitolo 5

Implementazione

Questo capitolo è dedicato alla descrizione degli aspetti implementativi di IPGen,

ossia il modo in cui la metodologia descritta nel capitolo 4 viene messa in pra-

tica. Per una migliore comprensione, si è deciso di organizzare la trattazione in

quattro sezioni. Si inizia con la descrizione della struttura del programma, ossia

la presentazione del framework dal punto di vista dell’ingegneria del software.

Successivamente è mostrato il funzionamento del software, cioè l’interazione con

l’utente e i passi compiuti per generare il codice VHDL in uscita. Proprio quest’ul-

timo è l’argomento della sezione 5.3, nella quale si descrive in dettaglio l’output

prodotto dal programma. L’ultima sezione presenta alcune linee guida da seguire

per realizzare un core VHDL che sia interfacciabile con successo tramite IPGen.

5.1 Struttura del programma

La struttura software di IPGen ricalca praticamente in tutto la metodologia sulla

quale si fonda, descritta nel precedente capitolo. Il programma è stato implemen-

tato con il linguaggio C++. L’impiego di tale linguaggio ha permesso di conferire

una struttura modulare al software, la quale è la chiave dell’espandibilità del soft-

ware: sarà sufficiente aggiungere una nuova classe per espanderne la funzionalità.

Viene quindi analizzata l’organizzazione delle classi che compongono IPGen, il

cui class diagram è mostrato in figura 5.1.

65

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.1: Class diagram di IPGen

Il software possiede innanzitutto una classe Main, adibita all’inizializzazione

del programma, alla creazione delle istanze di classi necessarie e alla chiamata dei

relativi metodi.

La classe Signal definisce il tipo “segnale”, indispensabile affinché il reader

possa creare un lista contenente i segnali di input/output del core per potere poi

implementare un’opportuna interfaccia. La classe possiede molti metodi qui di

seguito elencati e brevemente spiegati:

• in(). Restituisce “true” se il segnale costituisce un ingresso del core;

• out(). Restituisce “true” se il segnale costituisce una uscita del core;

• vector(). Restituisce “true” se il segnale è di tipo std_logic_vector;

• name(). Restituisce il nome del segnale;

• type(). Restituisce il tipo del segnale (std_logic oppure std_logic_vector);

• direction(). Restituisce la direzione del segnale (“in” oppure “out”);

66

CAPITOLO 5. IMPLEMENTAZIONE

• initial(). Nel caso in cui il segnale sia di tipo std_logic_vector,

restituisce l’indice iniziale del vettore;

• final(). Nel caso in cui il segnale sia di tipo std_logic_vector,

restituisce l’indice finale del vettore;

• length(). Nel caso in cui il segnale sia di tipo std_logic_vector,

restituisce la lunghezza del vettore;

• to(). Nel caso in cui il segnale sia di tipo std_logic_vector, resti-

tuisce la direzione di ordinamento del vettore (to oppure downto).

Si potrebbe dire che alcuni tra i metodi elencati siano ridondanti in quanto sem-

brano fornire la stessa informazione. In effetti è così, ma l’apparente ridondanza

è giustificata dalla diversità dell’ambito in cui tali metodi vengono invocati. Per

esempio, se in una espressione condizionale è necessario verificare il fatto che il

segnale sia un vettore, è molto più comodo utilizzare il metodo vector(), il

quale restituisce una variabile booleana, che invocare il metodo type() ed ef-

fettuare un confronto sulla stringa ottenuta. Se invece è richiesto di scrivere sul

file destinazione il tipo di segnale, sarà molto comodo invocare type() rispetto

a verificare il tipo tramite il metodo vector().

Per quanto concerne la classe Generic, la quale descrive appunto il tipo “gener-

ic”, ossia un parametro della descrizione VHDL, tale oggetto possiede degli at-

tributi che possono essere ottenuti invocando i seguenti metodi:

• name(). Restituisce il nome del generic;

• type(). Restituisce il tipo del generic;

• def(). Restituisce, se assegnato, il valore di default del generic.

Verranno ora presentate le classi che rappresentano il cuore dell’applicazione. La

classe Reader costituisce l’oggetto adibito a leggere il file VHDL la cui locazione

è fornita in ingresso e a riconoscerne sostanzialmente la dichiarazione di entity,

costruendo una lista di segnali e una lista di generic. Sono presenti i seguenti

metodi:

67

CAPITOLO 5. IMPLEMENTAZIONE

• read(). Tramite questa funzione viene avviato il processo di lettura;

• getList(). Restituisce la lista di Signal costruita dal metodo read();

• getListg(). Restituisce la lista di Generic costruita dal metodo read();

• getComponent(). Restituisce il nome del componente, cioè quello che

appare nella dichiarazione di entity.

La classe Writer rappresenta l’oggetto che effettua la creazione e la scrittura dei

file VHDL in uscita. Come si vede nel diagramma, non vi è un’unica classe Wri-

ter: è infatti presente una classe per ogni interfaccia supportata dal framework. Al

momento il programma è in grado di generare core con tre differenti tipi di inter-

faccia (vedere sezione 3): OPB PSelect, OPB IPIF e Wishbone. Ognuna di questa

classi è figlia di un’unica classe astratta, denominata appunto Writer, in modo

da mantenere una struttura identica e permettere in questo modo una maggiore

espandibilità tramite l’aggiunta di Writer per nuove interfacce. Vi sono dunque

tre classi: PSelect_Writer, IPIF_Writer e Wishbone_Writer, ognuna delle quali

definisce per “override” il metodo write() della classe madre. Si noti invece

che la classe Reader è unica, e non cambia passando da un tipo di interfaccia ad un

altro, in quanto il processo di lettura del file in ingresso e di costruzione delle liste

è identico qualunque sia il tipo di infrastruttura di comunicazione che si vuole

adottare. In sintesi, se si vuole aggiungere supporto per una nuova interfaccia,

è sufficiente scrivere un’opportuna classe _Writer e aggiungere la scelta di tale

interfaccia come opzione all’interno della classe Main.

L’ultima classe che si trova in figura è Cleaner. Essa fornisce due importanti

metodi per la gestione dei file VHDL, che sono:

• CleanComments(std:string Component). Questo metodo è ne-

cessario per pulire il file VHDL in ingresso da commenti che possono risultare

molto fastidiosi in fase di lettura della entity. Per esempio tra due linee che

contengono dichiarazioni di porte potrebbe trovarsi un commento: questo,

se non identificato come tale ed eliminato, potrebbe essere interpretato come

una dichiarazione di porta generando una palese situazione di errore. Il

68

CAPITOLO 5. IMPLEMENTAZIONE

metodo CleanComment opera nel seguente modo: apre il file VHDL identi-

ficato dalla stringa in ingresso e ne scansiona la entity in cerca di commenti,

producendo in uscita una stringa contenente la stessa dichiarazione di entity

priva di eventuali commenti. Si noti che non è necessario fornire in usci-

ta tutto il contenuto del file VHDL, in quanto la sezione che interessa al

reader è solamente quella in cui si trovano la descrizione delle porte e degli

eventuali generic.

• CleanGenerics(). Anche questo metodo opera sul file VHDL che de-

scrive il core. Si occupa dell’identificazione dei generic presenti e provvede

a cancellarne l’eventuale valore di default. Questa operazione è necessaria

poichè, se il valore di default venisse lasciato indicato nel core, esso ge-

nererebbe una discrepanza di valori con il dato impostato dall’esterno. È

molto importante sottolineare il fatto che questo metodo non sovrascrive il

file originale ma crea un ulteriore file contenente il codice senza i valori di

dafault dei generic. Questo perché in tal modo il core fornito dall’utente

viene preservato completamente intatto.

Nella prossima sezione verrà descritto come queste classi e i relativi metodi ven-

gono utilizzati nel flusso di lavoro di IPGen.

5.2 Utilizzo e funzionamento del framework

IPGen non è dotato per il momento di interfaccia grafica (GUI), ed è quindi ac-

cessibile solamente da riga di comando. Il motivo per il quale non è stata data la

priorità allo sviluppo di una GUI per il tool è semplice: esso è nato come compo-

nente del flusso di lavoro di Caronte e dunque viene invocato direttamente da tale

framework, senza bisogno di una interfaccia grafica indipendente. L’implemen-

tazione di questa è comunque in cantiere per sviluppi futuri, in quanto l’utilità del

framework si è dimostrata notevole anche al di fuori dell’ambito nativo, al punto

che esso potrebbe essere visto come un software a sé stante.

69

CAPITOLO 5. IMPLEMENTAZIONE

Il flusso di esecuzione del software è stato suddiviso per chiarezza in quattro

fasi, che sono:

• inizializzazione;

• fase di lettura;

• scelta dell’interfaccia e fase di scrittura;

• terminazione.

Ognuna di queste sarà descritta dettagliatamente nei prossimi paragrafi.

5.2.1 Inizializzazione

Per invocare IPGen l’utente digita la stringa ./ipgen seguita dal percorso del

file VHDL che descrive il core da interfacciare. Se tale percorso non viene fornito,

o è inesistente, viene generato immediatamente un messaggio di errore. Se invece

il file indicato esiste, viene creato un oggetto di tipo Reader e uno di tipo Cleaner,

del quale viene invocato il metodo cleanComments, che apre il file in esame, e

genera una stringa contenente la entity del core priva di eventuali commenti. Tale

stringa viene poi passata al Reader invocando su di esso il metodo read. Si noti

che a questo punto si è preferito utilizzare una stringa, piuttosto che un ulteriore

file, soprattutto per motivi di efficienza: è infatti noto che un accesso alla RAM,

possibile se si utilizza una stringa, è molto meno dispendioso che un accesso su

disco, necessario in caso fosse stato utilizzato un file di passaggio.

5.2.2 Fase di lettura

A questo punto è il Reader a controllare l’esecuzione: esso analizza la stringa in

ingresso in cerca della parola chiave “entity”, che indica l’inizio delle dichiarazioni

di interesse. Una volta trovata sonda la presenza di eventuali generic, verificando

la presenza della parola chiave “generic”, a cui seguono le dichiarazioni di questi

parametri. Se essa è presente il Reader procede riga per riga, inserendo in un’op-

portuna lista di oggetti di tipo Generic i parametri identificati, sicuro sul fatto che

70

CAPITOLO 5. IMPLEMENTAZIONE

non possano esserci dei commenti che lo conducano a una condizione di errore. In

un file VHDL i generic possono essere presenti o meno. Al contrario un core deve

per forza possedere delle porte di input/output, e quindi il Reader deve trovare

la parola chiave “port”, che precede la dichiarazione di tali segnali. Se questa

non viene identificata il Reader si blocca e genera un messaggio di errore. Se in-

vece il file è corretto le linee seguenti vengono scansionate e i segnali identificati

vengono inseriti in una lista di oggetti di tipo Signal. Durante questo processo

il Reader scrive a video il nome e le caratteristiche di tutte le porte identificate,

offrendo così all’utente la possibilità di verificarne la correttezza. Una volta con-

clusa la lettura della stringa fornita dal Cleaner, il controllo passa di nuovo al

main il quale stampa a video le dimensioni complessive (in byte) degli ingressi e

delle uscite del core, invocando sul Reader i metodi getSpaceIn e getSpaceOut.

In figura 5.2 è mostrato un esempio dell’output video di IPGen. In questo caso

il core fornito è un addizionatore avente oltre ai segnali di clock, di interrupt e di

reset, due operandi di 32 bit in ingresso e una uscita, sempre di 32 bit.

5.2.3 Scelta dell’interfaccia e fase di scrittura

A questo punto dell’esecuzione viene chiesto all’utente di scegliere il tipo di in-

terfaccia da integrare nell’IP-Core. Al momento il software supporta tre tipi di

interfaccia: OPB PSelect, OPB IPIF e Wishbone. Nel caso particolare in cui ven-

ga scelta l’interfaccia verso il bus Wishbone, viene chiesto all’utente di indicare il

numero di bit che vanno a costituire l’indirizzo che identifica l’IP-Core all’interno

del sistema (vedere capitolo 3), corrispondente a tre nel caso di architettura YaRA.

Una volta effettuata questa eventuale scelta, viene creata un’istanza del parti-

colare writer in base alla preferenza dell’utente e su di esso si invoca il metodo

write, che prende in ingresso il Reader e il Cleaner precedentemente creati. In

questa sezione non verranno trattati singolarmente i tre tipi di Writer, in quanto il

flusso di esecuzione è sostanzialmente lo stesso. Si può suddividere l’esecuzione

del metodo write in tre fasi: inizializzazione, creazione dello stub e creazione

dell’IP-Core.

71

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.2: Esempio dell’output video di IPGen

72

CAPITOLO 5. IMPLEMENTAZIONE

• Per “inizializzazione” si intendono una serie di operazioni che precedono

la scrittura vera e propria: innanzitutto viene invocata la funzione cleanGe-

nerics(). Essa analizza il file VHDL che descrive il core e produce in uscita

un nuovo file, identico a quello letto ma privo dell’eventuale valore di de-

fault dei generic, qualora essi fossero presenti. Nella sezione 5.3.4 verrà

spiegato nel dettaglio il motivo della necessità di tale operazione. Successi-

vamente vengono caricate la lista di segnali e la lista di generic, invocando

sul reader i metodi getList e getListg, le quali vengono salvate in due oppor-

tune variabili. L’ultima tra le operazioni di inizializzazione, necessaria se è

stata selezionato l’interfaccimento con IPIF, è il calcolo della lunghezza del

vettore di Chip Enable (CE, vedere sezione 3.1.2).

• A questo punto tutto è pronto per iniziare la scrittura del file VHDL che

descrive lo stub. Questo è composto da una struttura fissa, nella quale si

innestano alcune parti variabili, che cambiano a seconda del core da inter-

facciare. La tecnica impiegata è stata dunque quella di creare una costante

contenente una stringa che corrisponde alla struttura fissa. Questa viene

caricata in memoria dal metodo write, che la legge carattere per carattere e

simultaneamente scrive i caratteri letti nel file VHDL in uscita. All’interno

della stringa, laddove vi è la necessità di inserire una parte di descrizione

che dipende dal particolare core in ingresso, è presente un identificatore,

“#”, seguito da un carattere. Quando, durante la lettura della stringa, il Wri-

ter incontra tale identificatore, il flusso di esecuzione entra in un costrutto

di tipo case. A seconda del carattere letto dopo “#”, viene scritta nel file in

uscita un’opportuna sezione, per esempio la dichiarazione o l’istanziazione

del core, utilizzando le informazioni che pervengono in larga parte dalle

liste provenienti dal Reader. Una volta eseguite le istruzioni corrispondenti

all’opzione selezionata all’interno del costrutto case, il Writer riprende nor-

malmente il ciclo di lettura da stringa e scrittura su file, fino alla successiva

occorrenza dell’identificatore “#”. La scrittura dello stub termina ovvia-

mente quando viene raggiunta la fine della stringa. In figura 5.3 è mostrato

schematicamente il flusso di esecuzione corrispondente alla tecnica appena

73

CAPITOLO 5. IMPLEMENTAZIONE

descritta.

Figura 5.3: Flusso di creazione dei file in uscita

• Il file VHDL che descrive l’IP-Core, ossia la top-architecture del compo-

nente interfacciato, viene creato in modo del tutto analogo allo stub. Si uti-

lizza infatti un’altra stringa costante, che contiene la parte fissa del codice

che descrive l’IP-Core. Anche in questo caso è necessario creare delle parti

dipendenti dal core da interfacciare, e quindi è presente un costrutto case

che funziona allo stesso modo di quello descritto nel precedente paragrafo.

Si tenga però presente che per generare un’interfaccia verso il bus Wishbone

non è necessario creare questo secondo file, in quanto lo stub, che a questo

punto verrà chiamato esso stesso IP-Core, presenta come porte di ingresso e

uscita esattamente i segnali del bus Wishbone. Quindi tale IP-Core non uti-

lizza un’interfaccia che costituisce un modulo da istanziare (come avviene

74

CAPITOLO 5. IMPLEMENTAZIONE

invece per PSelect o IPIF), e lo stub svolge tutte le funzioni richieste ai fini

di supportare un corretto protocollo di comunicazione.

5.2.4 Terminazione

Se non vengono riscontrati errori, il processo di scrittura si conclude e il controllo

passa di nuovo al main, il quale termina l’esecuzione di IPGen. L’intero processo

di esecuzione del software (nel caso si adotti un’interfaccia “da istanziare”, per

esempio IPIF, e quindi rispettando la struttura classica dell’IP-Core come presen-

tata in figura 1.1) è sinteticamente mostrato nel sequence diagram UML di figura

5.4. In questo diagramma, le etichette collegate da frecce tratteggiate al termine

dell’esecuzione dei metodi cleanGenerics e write indicano la creazione dei file il

cui nome è riportato all’interno dell’etichetta stessa.

5.3 Caratteristiche delle descrizioni VHDL genera-

te

In questa sezione verranno presentate le caratteristiche delle descrizioni VHDL

prodotte da IPGen. Alcune di queste caratteristiche sono comuni a tutte le inter-

facce, mentre altre si differenziano a seconda della tipologia dell’infrastruttura di

comunicazione selezionata dall’utente. La trattazione è suddivisa in ambiti fun-

zionali; per ognuno di questi si mostreranno le eventuali differenze presenti tra i

tre diversi tipi di interfacce.

5.3.1 Visione d’insieme

In generale, i file VHDL prodotti da IPGen rispecchiano la struttura dell’IP-

Core come mostrata in figura 4.2. L’output del programma è infatti solitamente

composto da tre file:

• La descrizione VHDL del core, denominata nomecomponente_core.vhd,

dove “nomecomponente” va sostituito con il nome reale del componente

75

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.4: Sequence diagram dell’esecuzione di IPGen

che viene interfacciato. Questo file è sostanzialmente uguale a quello che

viene fornito dall’utente, dal quale si differenzia soltanto per l’assenza del

valore di default di eventuali generic. Il motivo di tale scelta è spiegato nella

sezione 5.3.4.

• La descrizione VHDL dello stub, denominata nomecomponente_stub.vhd.

Questo file rappresenta, come dice il nome, lo stub dell’IP-Core genera-

to, ossia la parte di logica che permette la comunicazione tra il core e

l’interfaccia.

• La descrizione VHDL dell’IP-Core, denominata nomecomponente_IPCore.vhd.

Questo file descrive l’IP-Core nel suo complesso. Esso è la top architecture

del componente, indicando con questo termine la parte di logica più ester-

76

CAPITOLO 5. IMPLEMENTAZIONE

na, cioè quella che viene vista dal bus, all’interno della quale sono istanziate

le parti che compongono l’IP-Core. Volendo utilizzare l’IP-Core, tutto ciò

che importa è il set di segnali che questo file presenta come porte di ingres-

so e uscita; sono infatti questi segnali, e solo questi, che rientrano nel file

Microprocessor Peripheral Definition (MPD, vedere sezione 2.3) utilizzato

da EDK per gestire correttamente un IP-Core che si vuole inserire in un

sistema.

Il file che rappresenta la vera e propria interfaccia di comunicazione non è presente

tra gli output del software, in quanto, come già scritto, IPGen si avvale di interfac-

ce già esistenti e diffuse. Per citare un esempio, i file che descrivono le interfacce

OPB IPIF e OPB PSelect, fanno parte della libreria di core fornita da Xilinx con il

framework EDK. La struttura dei file sopra illustrata non è però sempre identica,

in quanto esistono delle situazioni che potremmo definire “degeneri”. È questo il

caso dell’interfaccia verso il bus Wishbone: interfacciando un core verso questo

bus, infatti, non è necessario introdurre un ulteriore componente (l’interfaccia di

cui si è scritto prima) tra lo stub e il bus, in quanto i segnali di ingresso e uscita

dello stub coincidono già con i segnali del bus Wishbone. Tutta la logica neces-

saria per implementare un collegamento che permetta la corretta comunicazione

dell’IP-Core con gli altri componenti del sistema è contenuta nello stub, in quanto

non sono richiesti ulteriori mappaggi tra segnali. Per questi motivi lo stub viene

a coincidere con l’IP-Core stesso, e quindi si avranno solamente due file in usci-

ta: nomecomponente_core.vhd e nomecomponente_IPCore.vhd. In figura 5.5 è

mostrata sia la struttura generale che quella che è stata definita “degenere”.

Si descrive ora brevemente il funzionamento dell’IP-Core generato facendo

riferimento alla struttura dell’IP-Core generale. I segnali del bus si collegano, in

fase di “placement” del componente all’interno di un sistema, alle omonime porte

presenti in ingresso e in uscita dall’IP-Core. Si noti che la dichiarazione delle

porte dell’IP-Core non cambia a seconda del core interfacciato, in quanto esse

corrispondono ai segnali del bus adottato. Questi vengono filtrati da quella che è

stata chiamata interfaccia, che li elabora per generare un set di segnali solitamente

più semplice da gestire, offrendo spesso una varietà di servizi, come quelli visti nel

77

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.5: Diverse strutture di file generati

caso di OPB IPIF (sezione 3.1.2). I segnali generati dall’interfaccia costituiscono

le porte dello stub, il quale viene istanziato all’interno dell’IP-Core e svolge le

funzionalità descritte nel capitolo 4. All’interno di questo componente, a sua

volta, è istanziato il core, ossia la funzionalità implementata dall’utente con il

proprio set particolare di porte. Nelle seguenti sezioni sarà fornita una descrizione

più dettagliata del funzionamento descritto.

5.3.2 Istanziazione dei componenti e mappaggio delle porte

Come affermato nel paragrafo 5.3.1, all’interno dell’IP-Core vengono istanziati

l’interfaccia e lo stub. Nel caso di infrastrutture complesse, come OPB IPIF, il

mappaggio delle porte dell’interfaccia è abbastanza complicato; trattandosi co-

munque di una parte di logica fissa, cioè non dipendente dal particolare core,

esso non deve essere effettuato ogni volta. Inoltre l’interfaccia suddetta presen-

ta numerosi parametri da impostare, i quali determinano l’utilizzo o meno di un

determinato servizio offerto. Ad eccezione della decodifica degli infirizzi, al mo-

mento si è scelto di non adottare alcun servizio opzionale implementato in OPB

IPIF, poiché questi comportano spesso un overhead di occupazione non ridotto, il

che andrebbe ad aumentare l’area occupata e il tempo necessario alla riconfigu-

razione del componente nell’ambito di un’architettura quale Caronte. Nel futuro

si potrebbe attrezzare IPGen del supporto necessario a offrire all’utente la possi-

78

CAPITOLO 5. IMPLEMENTAZIONE

bilità di utilizzare o meno un determinato servizio. Per quanto riguarda lo stub,

anch’esso presenta, per ogni singolo tipo di interfaccia, un set di porte standard,

che non varia (nel caso di OPB IPIF esso è composto dai segnali IPIC). Quindi

l’istanziazione di esso risulta semplice e soprattutto fissa.

Diversamente da quanto appena scritto riguardo l’istanziazione dell’interfac-

cia e dllo stub, l’inserimento del core all’interno dello stub è più problematico,

in quanto non si conoscono a priori le porte del core. Queste, come descritto

nella sezione 5.2, vengono salvate dal reader in un’opportuna lista, utilizzata dal

writer per effettuare la dichiarazione del core nello stub. Per ogni porta del core

diversa dal segnale di clock, di reset e di interrupt (vedere sezione 5.4.2), viene

creato nello stub un corrispondente registro denominato register_nomesegnale,

dove “nomesegnale” è ovviamente il nome attribuito alla particolare porta, avente

tipo e dimensione del segnale del core corrispondente. Sono tali registri che ven-

gono collegati alle porte del core in fase di istanziazione dello stesso, come si vede

nell’esempio di figura 5.6.

La gestione di questi registri all’interno dello stub è l’argomento della prossi-

ma sezione.

5.3.3 Processi di lettura e scrittura

I registri creati all’interno dello stub devono essere opportunamente gestiti. In-

fatti, come precedentemente spiegato, lo stub deve svolgere una funzione di de-

multiplexer verso l’interno (dalla linea dati del bus ai vari registri) e multiplexer

verso l’esterno (dai registri alla linea dati del bus). Queste funzionalità vengono

svolte da due processi implementati nello stub: il processo di lettura, denomi-

nato reg_read_process, e il processo di scrittura, denominato reg_write_process.

Adottando la terminologia usata nell’ambito dei componenti logici sopra citati, si

può dire che il segnale di selezione corrisponde alla linea indirizzi del bus, o a

un suo derivato. Utilizzando OPB IPIF, per esempio, si dispone dei due vettori di

selezione Bus2IP_RdCE e Bus2IP_WrCE (vedere sezione 3.1.2), che fungono da

surrogati della linea indirizzi, ma ne permettono un’interpretazione più intuitiva.

Nel seguito si farà riferimento senza perdere generalità al caso OPB IPIF.

79

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.6: Dichiarazione e istanziazione del core di un addizionatore binario a 32 bit

Il processo di lettura è costituito sostanzialmente da un costrutto di tipo case,

il quale viene attivato ad ogni fronte di salita del clock. Quando un bit del vet-

tore read_reg_select, che corrisponde all’ingresso Bus2IP_RdCE, è posto a ’1’,

significa che è necessario porre sul bus la corrispondente uscita del core, rappre-

sentata all’interno dello stub dal registro a cui è mappata. Nel caso particolare in

cui l’uscita che si vuole leggere è costituita da un segnale di tipo std_logic, tale va-

lore viene posto per convenzione sul bit meno significativo (Least Significant Bit -

LSB) del bus dati, cioè quello più a destra. Se il segnale è di tipo std_logic_vector

ed ha lunghezza inferiore a 32 bit, che è la dimensione del bus dati nei tre tipi di

interfaccia supportati, anche in questo caso, per convenzione, il valore viene posto

sui bit più a destra della linea dati del bus. Il caso di segnali con dimensione mag-

giore di 32 bit è più complesso e viene esposto nella sezione 5.3.5. Un esempio

chiarificatore è mostrato in figura 5.7.

80

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.7: Esempio di processo di lettura dei registri

Il processo di scrittura è molto simile a quello di lettura. Anche in questo caso

si ha un costrutto case il cui segnale di selezione è reg_write_select, corrispon-

dente all’ingresso Bus2IP_WrCE. In modo analogo a quanto detto per il processo

di lettura, i registri aventi lunghezza minore di 32 bit prelevano il proprio valore

dai bit meno significativi del bus dati. Nel processo di scrittura, è presente anche

la parte riguardante il reset dei registri in ingresso. Semplicemente, si controlla

all’inizio del processo se l’ingresso Bus2IP_Reset è attivo, e, in caso affermati-

vo, si procede ponendo a zero il contenuto dei registri di scrittura dello stub. Un

esempio è mostrato in figura 5.8.

5.3.4 Gestione dei generic

Se nel core sono presenti dei generic, essi possono possedere un valore di default.

Tale valore, se lasciato indicato nel core, potrebbe essere fonte di errori o problemi

di interpretazione. Infatti, dato che un generic è un parametro che si può impostare

81

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.8: Esempio di processo di scrittura dei registri

quando l’IP-Core viene collocato in un sistema (per esempio tramite EDK), il

framework deve essere in grado di propagare verso l’esterno, dal punto di vista

della consueta struttura del componente, tale parametro; in questo modo il generic

è impostabile agendo sul file che descrive l’IP-Core. Ora, impostando dall’esterno

un valore per un determinato generic, potrebbe darsi che esso sia differente dal

valore di default indicato nel core.

Per ovviare a questo problema, IPGen sfrutta un meccanismo molto semplice:

salva una lista dei generic in fase di lettura, e in fase di scrittura effettua due

mappaggi consecutivi per ognuno di essi prima dal core allo stub, e poi dallo stub

all’IP-Core. Inoltre esso genera, come scritto in precedenza, un file uguale al

core, ma privo dei valori di default di eventuali generic; tali valori vengono poi

indicati ragionevolmente nella dichiarazione dello stesso generic a livello di IP-

82

CAPITOLO 5. IMPLEMENTAZIONE

Core. Sembrerebbe inutilmente dispendioso creare una copia quasi identica di un

file, ma effettivamente questa scelta si rivela sensata: grazie ad essa infatti il file

originale viene preservato in tutto e per tutto, rendendo possibile il suo riutilizzo

in un altro ambito.

5.3.5 Gestione di porte con dimensione maggiore di 32 bit

Figura 5.9: Processo di lettura per un core avente una uscita da 128 bit

Per consentire ad IPGen di essere applicabile ad una maggiore varietà di core,

si è deciso di implementare un supporto per i segnali di tipo std_logic_vector

aventi dimensione maggiore della linea dati del bus, che in tutti e tre i casi di

interesse corrisponde a 32 bit. Dopo attente analisi, è stato adottato il seguente

meccanismo di comunicazione: ogni segnale “grande” viene segmentato in regi-

stri di dimensione uguale a 32 bit, ad eccezione dell’ultimo, che può avere una

dimensione compresa tra 1 e 32 bit, in quanto la lunghezza segnali non è neces-

sariamente multipla di 32. Ad ogni segmento viene associato un indirizzo; per

accedere in lettura o scrittura a ciascun pezzo del segnale, il driver che gestisce

l’IP-Core deve quindi fornire l’indirizzo preciso del registro corrispondente.

Per quanto riguarda il processo di lettura, esso non si discosta molto da quanto

presentato nella sezione 5.3.3. In figura 5.9 si può vedere un esempio di processo

di lettura per un core avente un segnale di lunghezza 128 bit.

La questione è nettamente più complessa per quanto riguarda la scrittura di

83

CAPITOLO 5. IMPLEMENTAZIONE

tali segnali. Questo perché se un core possiede un ingresso, per esempio, di 64

bit, esso si aspetta certamente di riceverlo tutto in una volta, e non scaglionato in

segmenti da 32 bit. Per rispettare questa condizione IPGen crea all’interno dello

stub, per ogni ingresso del core più grande di 32 bit, i seguenti segnali, il cui

utilizzo viene spiegato successivamente:

• il consueto registro, denominato register_nomesegnale;

• un segnale di tipo std_logic_vector, denominato buffer_nomesegnale, avente

dimensione pari a quella dell’ingresso del core;

• un segnale di tipo intero, denominato count_nomesegnale;

• un segnale di tipo std_logic, denominato ready_nomesegnale.

Nel processo di scrittura, in presenza di un segnale “grande”, viene generata una

sorta di macchina a stati, la quale pone al driver il vincolo di rispettare obbliga-

toriamente la sequenzialità nella trasmissione del segnale, la quale può avvenire

anche in modo non consecutivo. In pratica, all’indirizzo di ogni segmento del

segnale viene assegnato un numero intero partendo da 0; se, quando si riceve l’n-

esimo segmento, il contatore count_nomesegnale ha un valore pari alla posizione

del segmento all’interno del segnale, cioè n, il valore in ingresso viene corretta-

mente copiato nella giusta posizione all’interno di buffer_nomesegnale. In caso

contrario il contatore viene annullato e il buffer posto interamente a ’0’, effettuan-

do perciò un reset della comunicazione. Quando l’ultimo segmento del segnale

viene correttamente ricevuto, viene posto al valore ’1’ il flag ready_nomesegnale,

in modo che un opportuno controllore possa, nel ciclo di clock successivo, copia-

re l’intero contenuto del buffer in registro_nomesegnale e riazzerare il flag. Un

esempio di questa operazione è mostrato in figura 5.10, nella quale si considera

un segnale di lunghezza pari a 96 bit.

Il meccanismo appena descritto non è al momento stato implementato per

quanto riguarda l’interfaccia OPB PSelect, mentre è supportato utilizzando OPB

IPIF e Wishbone.

84

CAPITOLO 5. IMPLEMENTAZIONE

Figura 5.10: Processo di scrittura per un core avente un ingresso da 96 bit

5.4 Come scrivere un core interfacciabile automati-

camente

In questa sezione vengono analizzati quelli che sono i requisiti che un core deve

possedere, affinché la creazione del relativo IP-Core tramite IPGen possa avvenire

con successo. Questi requisiti si dividono in due gruppi:

• requisiti concettuali, la cui inosservanza non genera errori nel flusso di

esecuzione di IPGen;

85

CAPITOLO 5. IMPLEMENTAZIONE

• requisiti pratici, riconosciuti dal framework, la cui inosservanza blocca ef-

fettivamente l’esecuzione dello stesso.

5.4.1 Requisiti concettuali

Si tratta in realtà di un unico principio fondamentale da tenere a mente, e non di

una serie di regole da seguire. Sostanzialmente, si può dire che lo sviluppatore del

core, cioè colui che ne scrive la descrizione in VHDL, deve occuparsi solamente

della funzionalità svolta dal componente che sta implementando, senza curarsi, in

nessun modo, della connessione di questo con il sistema in cui verrà inserito. In

altre parole, tutta e sola la funzionalità reale che il componente svolge va descrit-

ta nel core, lasciando ad altri il compito di occuparsi del collegamento con una

particolare infrastruttura di comunicazione. Portando il discorso ad un livello più

pratico, si può affermare che l’insieme degli ingressi e delle uscite del core non

deve contenere elementi in qualche modo riconducibili al collegamento dell’IP-

Core nel sistema, in quanto la logica necessaria a tale scopo viene interamente

creata da IPGen. Viene presentato un esempio per esplicare meglio quanto si in-

tende dire: si prenda il caso in cui si voglia realizzare un addizionatore binario

con operandi di 32 bit. In tal caso, è ovvio che gli ingressi saranno costituiti dagli

addendi, e da eventuali segnali di clock (se il componente è sincrono) e di re-

set. Le uscite saranno invece il risultato e eventualmente un interrupt, utilizzabile

ad esempio per segnalare un overflow. Come si vede, non si fa in nessun modo

riferimento alla linea dati del bus o agli indirizzi dei registri che permettono di ef-

fettuare operazioni di lettura scrittura sul componente. Questo è possibile poiché

è lo stub, generato automaticamente, che si occupa di questioni quali lo smista-

mento degli operandi in ingresso, provenienti da un’unica linea dati del bus, o la

lettura del risultato in uscita, il quale va posto sulla stessa linea dati.

Se un core contenente porzioni di logica necessari alla comunicazione con il

sistema viene dato in ingresso ad IPGen, si ottiene un prodotto non sintatticamente

scorretto, ma contenente inutili e dannose ridondanze. Un tale IP-Core risulta

necessariamente inutilizzabile, sia a causa dei ritardi introdotti da inutili livelli di

comunicazione, sia perché non si assicura un corretto collegamento tra ingressi del

86

CAPITOLO 5. IMPLEMENTAZIONE

core e segnali provenienti dal bus. Per citare un caso, si consideri un core avente

un segnale in ingresso che rappresenta l’indirizzo posto sul bus. Tale segnale

non verrebbe in nessun modo riconosciuto e verrebbe collegato, come un ingresso

“normale”, alla linea dati del bus, anziché a quella degli indirizzi.

Il requisito fondamentale qui discusso non pone in realtà alcun vincolo al-

lo sviluppatore, che anzi si trova sgravato dalla necessità di implementare una

porzione di logica generabile automaticamente. Si noti inoltre che questo requisi-

to costituisce la base per il riuso degli IP-Core, in quanto un componente che non

contiene accenni al sistema in cui verrà posto è necessariamente “universale”.

5.4.2 Requisiti pratici

Si passa ora all’analisi dei requisiti cosiddetti “pratici”. In primo luogo un core

può possedere due tipologie di porte corrispondenti due gruppi di segnali:

• Segnali custom: sono segnali propri della funzionalità implementata, come,

ad esempio, gli ingressi di una funzione;

• Segnali standard: sono porte solitamente presenti in tutti i core implemen-

tati. Svolgono funzioni standard (da qui il nome) come il segnale di clock,

quello di reset e quello di interrupt. Solitamente a questo tipo di segnali

vengono assegnate linee dedicate del bus.

Le porte appartenenti al secondo tipo devono essere gestite in modo specifico dal-

lo stub, per permettere un collegamento corretto con le corrispondenti linee del

bus. Sarebbe infatti un errore, per esempio, non riconoscere come tale il segna-

le di clock e collegarlo alla linea dati del bus, come se fosse un segnale custom,

in quanto il bus possiede una linea separata per la trasmissione di questo parti-

colare segnale. Quindi, affinché il writer sia in grado riconoscere tali segnali, è

necessario introdurre delle condizioni di nomenclatura, elencate qui di seguito:

• Il segnale di clock deve essere denominato “clk”;

• Il segnale di reset deve essere denominato “reset”;

87

CAPITOLO 5. IMPLEMENTAZIONE

• Il segnale di interrupt deve essere denominato “intr”.

Oltre a queste convenzioni, ci sono altre due regole da seguire. IPGen gestisce so-

lamente core aventi porte di tipo std_logic e std_logic_vector; altri tipi

non sono supportati. Se un core possiede al suo interno segnali di altro tipo, spetta

allo sviluppatore implementare la logica di conversione dal tipo in esame e uno

dei due tipi prima menzionati. Siccome ciò avviene in realtà in pochi casi, poiché

solitamente il livello di astrazione utilizzato scrivendo codice VHDL è piutto-

sto basso, sarebbe ingiustificatamente oneroso scrivere una parte di software che

generi in automatico la logica per effettuare queste conversioni, considerando an-

che che l’insieme dei tipi utilizzabili nella dichiarazione di porte e segnali interni è

potenzialmente infinito. Infine, il software non supporta al momento dichiarazioni

del tipo:

port1, port2 : std_logic;

Tale dichiarazione va sviluppata nel modo consueto:

port1 : std_logic;

port2 : std_logic;

Non vi sono altri vincoli da rispettare per scrivere un core gestibile da IPGen.

88

Capitolo 6

Risultati sperimentali

Sono stati effettuati numerosi test con l’obiettivo di validare in pratica IPGen.

Questi test sono stati condotti con due strumenti: ISE Project Navigator e Mo-

delSim, entrambi presentati nella sezione 1.2. Essi si possono suddividere in due

categorie: test di prestazione e di funzionamento. Nei primi sono stati valutati

parametri quali il tempo di esecuzione del software e l’area occupata sulla FPGA

dagli IP-Core generati, mentre i secondi hanno come obiettivo la dimostrazione

dell’effettivo funzionamento delle soluzioni adottate.

6.1 Test di prestazione

Per valutare le prestazioni di IPGen e degli IP-Core prodotti, si è scelto di foca-

lizzare l’attenzione sull’interfaccia OPB IPIF. Questa è una scelta che non toglie

assolutamente generalità al discorso. Anzi, addirittura potremmo identificare tale

interfaccia come il “caso pessimo” in quanto, come si evince dal capitolo 3, essa

è l’infrastruttura di comunicazione più complessa da gestire e che comporta un

maggiore overhead in termini di area occupata sulla FPGA.

Sono stati attentamente analizzati due parametri:

• Il tempo di esecuzione del software, espresso in millisecondi, che descrive

la bontà del software;

89

CAPITOLO 6. RISULTATI SPERIMENTALI

• L’area occupata dall’IP-Core sulla FPGA, espressa in numero di slice, che

esprime una caratteristica non del software, bensì del codice VHDL gene-

rato.

In una prima sessione sono stati utilizzati otto core, partendo da componenti molto

semplici e leggeri a core piuttosto complessi. Essi sono qui di seguito elencati:

• Un semplice Counter, che conta da 0 al valore in ingresso n;

• Un Adder con operandi da 32 bit con controllo di overflow;

• Uno Squarer, che calcola il quadrato del numero binario in ingresso;

• Un contatore di frequenza;

• Un lettore hardware di file con filesystem di tipo FAT16;

• Una Division Unit;

• Una Unità Aritmetico Logica (ALU);

• Una Floating Point Unit (FPU), che esegue operazione su numeri binari

espressi in floating point.

All’interno della tabella 6.1 sono mostrati i risultati ottenuti nell’ambiente di

sviluppo ISE Project Navigator, simulando la collocazione degli IP-Core su una

FPGA Xilinx VirtexIIPro xc2vp7, con l’unica eccezione della FPU, per la quale,

a causa della notevole dimensione, è stata virtualmente utilizzata una VirtexIIPro

xc2vp30.

In primo luogo è stata effettuata la sintesi con XST del core preso singolar-

mente. Successivamente, è stato sintetizzato lo stub, e infine l’IP-Core. Prima di

analizzare i dati mostrati in tabella è necessario fare una premessa sul funziona-

mento di XST. Come descritto in [23], esso effettua in fase di sintesi di un IP-Core

importanti ottimizzazioni, con l’obiettivo di raggiungere un compromesso tra la

massimizzazione della frequenza di utilizzo e la minimizzazione dell’area occu-

pata. Tale processo si basa fondamentalmente su due operazioni: la duplicazione

90

CAPITOLO 6. RISULTATI SPERIMENTALI

Counter Adder Squarer F. Counter FFR-Fat16 Div Unit ALU FPU

Core (# slice) 26 35 63 85 168 317 997 5394

Stub (# slice) 19 37 26 29 91 39 48 -123

Core+Stub (# slice) 45 72 89 114 259 356 1045 5271

IPIF (# slice) 39 62 24 35 80 60 17 153

IP-Core (# slice) 84 134 113 149 339 416 1065 5424

Overhead (# slice) 58 99 50 64 171 111 68 30

Overhead % 69,05 73,88 44,22 42,95 50,44 26,68 6,38 0,01

Dimensione delle 33 96 11 34 42 80 140 115

porte (bit)

Tempo (ms) 53 60 55 59 64 60 67 59

Tabella 6.1: Risultato dei test sugli otto core utilizzati

di registri (per minimizzare il “tempo di attraversamento” e quindi aumentare la

frequenza di utilizzo), e l’eliminazione di registri ridondanti o inutilizzati (per

minimizzare l’area occupata).

A livello teorico, è ragionevole supporre che l’interfaccia IPIF necessiti di

una quantità di area costante per tutti gli IP-Core; in realtà, proprio a causa delle

ottimizzazioni operate dallo strumento di sintesi, questo non si verifica. Ciò no-

nostante, l’area occupata dalla IPIF non mostra alcun trend particolare, quindi si

può escludere che essa dipenda in qualche modo dalla dimensione o dalla com-

plessità del core interfacciato. È altresì intuitivo aspettarsi che, al crescere della

dimensione del core istanziato, l’occupazione percentuale di overhead introdotto

da IPGen, relativa alla dimensione totale dell’IP-Core, decresce in modo netto,

come è mostrato in figura 6.1. Dalla tabella emerge un dato senz’altro “strano”:

la dimensione dello stub insieme al core è in un caso minore di quella del core

stesso; ancora una volta questo è un effetto del processo di ottimizzazione operato

da XST.

Viene valutato ora il tempo di esecuzione del software; per ottenere una misura

il più reale possibile, tale dato è costituito dalla media di dieci tempi ottenuti

da altrettante esecuzioni del framework per ogni core. Si nota facilmente che

esso è indipendente dalla dimensione e dalle porte dei core e risulta con buona

approssimazione costante.

91

CAPITOLO 6. RISULTATI SPERIMENTALI

Figura 6.1: Occupazione percentuale di overhead introdotto da IPGen

Successivamente è stata condotta una seconda sessione di test. Sono stati uti-

lizzati, in qualità di core da dare in ingresso a IPGen, dei dummy core opportu-

namente implementati. Per dummy core si intende una descrizione VHDL con-

tenente, nella parte architetturale, il livello minimo di logica necessaria a far sì

che le porte dichiarate nella entity siano effettivamente utilizzate. Molto spesso si

tratta di un semplice assegnamento tra uscite e ingressi. Anche se questi non de-

scrivono funzionalità utili e reali, offrono in fase di test numerosi vantaggi: infatti,

si possono condurre delle prove “mirate” a verificare l’efficacia o meno del frame-

work in una data situazione, semplicemente scrivendo un dummy core adeguato.

Inoltre, possedendo una logica molto semplice (addirittura inesistente nella quasi

totalità dei casi), essi sono meno soggetti alle pesanti ottimizzazioni operate in

fase di sintesi da XST.

Il fatto che un dummy core abbia di per sé un’occupazione di area quasi sem-

pre nulla non rappresenta un risvolto negativo: infatti è stato mostrato nella prece-

dente sessione che i parametri considerati non dipendono in alcun modo dalla

dimensione del core. Tra le misure considerate non appare la dimensione del-

92

CAPITOLO 6. RISULTATI SPERIMENTALI

l’interfaccia IPIF: tale scelta deriva sia da una considerazione teorica già espressa

sopra, cioè che l’occupazione della IPIF dovrebbe essere costante, sia dal risultato

pratico ottenuto precedentemente, ossia la mancanza di correlazione tra comples-

sità del core e occupazione dell’interfaccia. Ci si riferirà quindi solamente allo

stub, la cui dimensione dovrebbe ragionevolmente cambiare al variare del numero

e della larghezza dei segnali di ingresso e uscita dal core.

Per valutare a fondo le prestazioni di IPGen, sono stati creati nove dummy

core. I risultati dei test si possono vedere nella tabella 6.2, mentre in figura 6.2

si può osservare l’andamento dell’occupazione (espresso in numero di slice) del-

lo stub al variare del dummy core considerato. Per esprimere i dati di interesse

di ciascun componente, cioè le porte di ingresso e di uscita, è stata adottata la

seguente simbologia: il primo numero rappresenta la quantità delle porte e il nu-

mero tra parentesi indica la dimensione in bit del segnale. Per esempio, “2 x (64)”

significa che il core ha (in ingresso o in uscita) due porte di dimensione pari a 64

bit.

Porte in Porte out Tempo (ms) Core (slice) Stub (slice)

dummy01 1 x (1) 1 x (1) 42,7 0 2dummy02 1 x (32) 1 x (32) 44,2 0 37dummy03 2 x (1) 2 x (1) 42,9 0 4dummy04 2 x (32) 2 x (32) 45,7 0 69dummy05 4 x (32) 4 x (32) 45,9 0 107dummy06 2 x (64) 2 x (64) 44,3 0 196dummy07 1 x (128) 1 x (128) 55,3 0 193dummy08 1 x (64) 3 x (64) 44,2 0 115dummy09 3 x (64) 1 x (64) 58,3 37 252

Tabella 6.2: Risultato dei test sui “dummy core”

Vengono ora fatte alcune considerazioni sui risultati ottenuti. Innanzitutto si

può notare che l’overhead di logica costituito dallo stub è molto basso quando gli

ingressi e le uscite del core sono segnali costituiti da un singolo bit. Si nota anche

che, al raddoppiare del numero di porte di dimensione 32 bit (si considerino i core

dummy02, dummy04 e dummy05), l’occupazione dello stub risulta anch’essa quasi

raddoppiata. Un altro risultato rilevante é il seguente: osservando i componenti

93

CAPITOLO 6. RISULTATI SPERIMENTALI

Figura 6.2: Occupazione dello stub generato per i “dummy core”

dummy05 e dummy06 si vede che, a parità di dimensione complessiva in bit sia

degli ingressi che delle uscite, la dimensione dello stub è molto maggiore nel caso

in cui si utilizzino segnali più grandi di 32 bit. Tale risultato è frutto del meccani-

smo particolare implementato per la gestione di questi segnali, soprattutto quelli

in ingresso (si veda la sezione 5.3.5). Proprio per verificare questa affermazione,

sono stati creati dummy08 e dummy09, che utilizzano porte da 64 bit. Il primo

presenta un segnale in scrittura e tre in lettura, mentre il secondo ne è il duale,

possedendo tre ingressi e una sola uscita. Lo stub di dummy08 ha un’occupazione

che, come era lecito aspettarsi, è minore di quello di dummy06 e maggiore di dum-

my05. La dimensione dello stub di dummy09 è invece maggiore di quella di tutti

gli altri essendo l’unico core che presenta bene tre ingressi di dimensione 64 bit.

Per quanto riguarda i tempi di esecuzione, essi sono pressoché costanti, anche

se rivelano un leggero trend crescente all’aumentare del numero e della dimen-

sione dei porte di ingresso dei core.

94

CAPITOLO 6. RISULTATI SPERIMENTALI

6.2 Test di funzionamento

Con l’intento di validare la metodologia proposta, è stato necessario effettuare

alcune simulazioni del funzionamento degli IP-Core generati dal framework, con-

dotte utilizzando ModelSim (sezione 1.2.3). Il core scelto per verificare il cor-

retto funzionamento dei componenti generati è un addizionatore a 32 bit, il quale

possiede due ingressi, gli addendi, e un’uscita, il risultato. Sono necessarie quindi

due operazioni di scrittura e una di lettura al fine di compiere un ciclo comple-

to di applicazione del modulo. Sono stati simulati i tre IP-Core generati con le

interfacce supportate.

Figura 6.3: Simulazione di un IP-Core con interfaccia PSelect

In primo luogo viene considerato l’IP-Core che integra l’interfaccia PSelect

sul bus OPB, la cui simulazione è mostrata nel grafico temporale in figura 6.3,

dove i segnali che rappresentano dati o indirizzi sono espressi per chiarezza in

codifica esadecimale. Il valore iniziale dell’indirizzo presente sul bus corrisponde

al base address assegnato al componente in fase di istanziazione nel sistema. in

quanto il primo registro è posizionato all’interno dello spazio di indirizzamento

dell’IP-Core in posizione zero. In tal modo, essendo l’ingresso opb_rnw posto

a zero (indicando così un’operazione di scrittura), il contenuto della linea dati

entrante viene copiato nel registro corrispondente al primo addendo. In modo

identico viene successivamente scritto il valore del secondo operando, il cui regi-

stro si trova all’indirizzo 4. A questo punto il core computa la somma che viene

letta dal master, innalzando il segnale opb_rnw e ponendo sulla linea indirizzi il

valore 0, che corrisponde in fase di lettura al registro contenente il risultato.

95

CAPITOLO 6. RISULTATI SPERIMENTALI

Figura 6.4: Simulazione di un IP-Core con interfaccia OPB IPIF

La simulazione dell’IP-Core interfacciato tramite OPB IPIF è raffigurata in

figura 6.4; il procedimento di scrittura/lettura è sostanzialmente simile a quello di

PSelect. Si noti che in questo caso lo stub, per gestire i registri, utilizza i vettori di

CE forniti da IPIF. Inoltre, durante la fase di lettura del risultato, si vede che esso

viene posto sul segnale IPIC IP2Bus_data sul fronte di discesa del clock; questo

è necessario poiché, se tale valore venisse scritto durante il fronte di salita, la IPIF

non farebbe in tempo a elaborarlo e verrebbe perso in tal modo un intero ciclo di

lettura, corrispondente generalmente a tre cicli di clock.

Figura 6.5: Simulazione di un IP-Core con interfaccia Wishbone

L’interfacciamento con Wishbone (figura 6.5) si dimostra meno complesso dei

precedenti. In questo caso il valore della linea indirizzi del bus è espressa in co-

difica binaria, in quanto composta da soli 8 bit. Dopo aver impostato il valore dei

parametri necessari a inizializzare la comunicazione (secondo il protocollo de-

96

CAPITOLO 6. RISULTATI SPERIMENTALI

scritto nella sezione 3.2), si procede con la fase di scrittura dei registri in ingresso,

innalzando il segnale we_i e ponendo a “011” il valore dei primi tre bit del segnale

adr_i, che corrispondente al numero identificativo dell’IP-Core all’interno del si-

stema. Assegnando in successione i valori “00000” e “00001” ai cinque bit meno

significativi di adr_i, il valore presente nel bus dati viene copiato nei registri cor-

rispondenti agli ingressi del core. Per leggere la somma, il master abbassa we_i e

scrive l’indirizzo opportuno, in modo tale che il risultato il risultato venga copiato

sulla linea dati in uscita dall’IP-Core.

97

Capitolo 7

Conclusione e sviluppi futuri

Durate la fase di progettazione di un sistema embedded, la realizzazione delle

interfacce dei componenti che devono dialogare tra di loro mediante un’opportuna

infrastruttura di comunicazione è la parte meno creativa e più meccanica di tutto

il processo. Questo lavoro di tesi è stato concepito per sgravare il progettista da

questo lavoro ripetitivo, migliorando il time-to-market del dispositivo prodotto

e dando la possibilità all’utente di focalizzare la propria attenzione sulla parte

realmente funzionale della propria architettura: il core.

IPGen, per come è stato concepito, ha una struttura interna fortemente modu-

larizzata (sezione 5.1). Questo aspetto permette al framework di essere espanso

senza la necessità di modificare porzioni consistenti di codice già scritto. In fu-

turo potranno essere implementati nuovi writer al fine di supportare un maggior

numero di bus assieme alle loro interfacce.

Come mostrato nel capitolo 6, IPGen è uno strumento già funzionante con

discrete prestazioni. Si può dire con tutta sicurezza che esso rappresenta una vera e

propria novità all’interno del settore della progettazione di IP-Core. Infatti, come

si può vedere nel capitolo 2 e nella sezione 4.4, non esiste un altro strumento che

attualmente offra funzionalità analoghe. Inoltre, sebbene IPGen è stato pensato

per essere impiegato all’interno di un flusso di riconfigurabilità dinamica, esso è in

realtà un software indipendente, che può essere utilizzato ogniqualvolta si debba

creare un IP-Core. Ovviamente, l’ampiezza del campo di utilizzo del software

99

CAPITOLO 7. CONCLUSIONE E SVILUPPI FUTURI

dipende dal numero delle interfacce supportate.

Allo stato attuale, esso supporta il bus OPB con interfacce PSelect, IPIF e

Wishbone. L’interfaccia OPB PSelect viene sfruttata dal software utilizzando

tutte le funzionalità che essa mette a disposizione. Ciò non vale per IPIF, della

quale IPGen sfrutta le capacità di decodifica degli indirizzi, ma non i servizi ag-

giuntivi quali Interrupt Service Controller e registri FIFO. Il bus Wishbone viene

supportato in modalità Point-to-Point e Shared Bus, mentre le ulteriori tipolo-

gie di connessione non vengono utilizzate. Quindi, sebbene IPGen garantisca

un interfacciamento sia con OPB che con Wishbone, possibili sviluppi compren-

dono, oltre all’aggiunta del supporto a altre eventuali interfacce, l’ampliamento e

l’irrobustimento del supporto a questi bus.

Al fine di allargare il campo di applicazione del framework, è in fase di studio

l’implementazione del supporto per l’interfacciamento di IP-Core di tipo master,

e in particolare di componenti con accesso diretto alla memoria (DMA).

100

Bibliografia

[1] Alberto Donato, Fabrizio Ferrandi, Massimo Redaelli, Marco D. Santam-

brogio, and Donatella Sciuto. Caronte: A complete methodology for the

implementation of partially dynamically self-reconfiguring systems on fpga

platforms. In FCCM, pages 321–322, 2005.

[2] Fabrizio Ferrandi, Marco D. Santambrogio, and Donatella Sciuto. A de-

sign methodology for dynamic reconfiguration: The caronte architecture. In

IPDPS, 2005.

[3] Xilinx Inc. Development System Reference Guide. Xilinx, Inc., 2001.

[4] Semiconductor intellectual property core. Wikipedia, the free encyclopedia.

[5] IP core. Whatis.com, the leading IT encyclopedia and learning center.

[6] Andrew S. Tanenbaum. Structured Computer Organization - 4th Edition.

Prentice Hall, 1999.

[7] Xilinx Inc. Two flows for Partial Reconfiguration: Module Based or

Difference Based. Technical Report XAPP290, Xilinx Inc., September 2004.

[8] Xilinx Inc. Embedded System Tools Reference Manual. Xilinx Inc., 2005.

[9] Xilinx Inc. XST User Guide. Xilinx Inc., 2005.

[10] MentorGraphics. ModelSim GUI Reference. MentorGraphics, 2004.

[11] OCP-IP Association. The importance of Sockets in SOC Design.

101

[12] OCP-IP Association. Open Core Protocol Specification 2.1.

[13] Tien-Lung Lee and Neil W. Bergmann. An Interface Methodology for Re-

targettable Fpga Peripherals. In Engineering of Reconfigurable Systems and

Algorithms, pages 167–173, 2003.

[14] Tien-Lung Lee and Neil W. Bergmann. Interfacing Methodologies for

IP Re-use in Reconfigurable System-On-Chip. Microelectronics: Design,

Technology and Packaging, Vol. 5274, 2004.

[15] Impulse Accelerated Technologies. Impilse CoDeveloper User Guide.

Impulse Accelerated Technologies, 2006.

[16] System-on-chip. Wikipedia, the free encyclopedia.

[17] IBM corporation. The CoreConnect Bus Architecture, white paper.

International Business Machines Corporation., 2004.

[18] IBM Corporation. On-Chip Peripheral Bus, Architecture Specification

version 2.1.

[19] Xilinx Inc. Designing Custom OPB Slave Peripherals for MicroBlaze.

Xilinx, Inc., 2002.

[20] Xilinx Inc. OPB IPIF (v3.01a). Xilinx, Inc., 2004.

[21] Silicore OPENCORES.ORG. WISHBONE system-on-chip (SoC) inter-

connection architecture for portable IP cores. September 2002. Revision:

B.3.

[22] F. Ferrandi, G. Ferrara, R. Palazzo, V. Rana, and M. D. Santambrogio. Vhdl

to fpga automatic ipcore generation: A case study on xilinx design flow.

In 20th IEEE International Parallel and Distributed Processing Symposium

(IPDPS’06) - Reconfigurable Architecture Workshop - RAW, 2005.

[23] Hitesh Patel. Synthesis and Implementation Strategies to Accelerate Design

Performance. Xilinx White Paper 229, 2005.

102

Ringraziamenti

È stata dura, ma ce l’abbiamo fatta.

Sono passati tre anni dall’inizio di questo percorso, e abbiamo finalmente rag-

giunto la prima tappa fondamentale. Tre lunghi anni che hanno comportato molte

fatiche e preoccupazioni, ma non solo; fortunatamente abbiamo incontrato tan-

ta gente, tanti amici che hanno contribuito a rendere questo cammino molto ma

molto più sereno e divertente: Alessio, Cesco, Malex, Marco, Paco, Pasca, Ste,

Supremo e tutti gli altri con cui abbiamo trascorso questo periodo. Il primo

ringraziamento va a loro.

Questa tesi non sarebbe mai esistita se non ci fosse stata una persona a istruirci,

spronarci e motivarci. Un grazie di cuore a Santa!!!, che ci ha fatto capire come

lavorando in gruppo si possano ottenere grandi risultati. A proposito di gruppo, ci

teniamo a ringraziare tutti i ragazzi di DRESD, in particolare Matteo e Vincenzo

per l’aiuto che ci hanno dato.

Matteo

Innanzitutto un grazie immenso alla mia famiglia, grazie per il sostegno che mi

dà ogni giorno e grazie per tutti i principi che mi ha insegnato nel corso di questi

22 anni. Questa tesi è il mio ringraziamento per tutto questo.

Voglio ringraziare tanto, infinitamente, colei che mi è vicina da due anni, che mi

ha aiutato, consolato, spronato nei momenti difficili, grazie a lei sono diventato

migliore. Ste, ti voglio bene.

103

E adesso è arrivato il momento di ringraziare un uomo che è venuto dalle Valli

per allietare e rendere produttiva ogni mia giornata! Con Alessandro ho condiviso

esperienze di studio, di lavoro, di festa, di estremo divertimento. Grazie per aver

condiviso con me queste esperienze di vita.

Infine voglio ringraziare tutti i miei amici, soprattutto perchè nonostante le mie

sparizioni per (anche lunghi) periodi di tempo, mi fanno comunque sentire sem-

pre la loro amicizia ed ogni volta che ci ritroviamo siamo sempre legatissimi,

come se trascorressimo assieme ogni ora del nostro tempo.

Alessandro

Ho tante persone da ringraziare... inizio da coloro che mi hanno supportato e

sopportato per tutto questo tempo: i miei genitori. Grazie veramente di cuore per

tutto quello che avete fatto e fate per me. Restando in ambito familiare, è doveroso

ringraziare il bassista più virtuoso della Valle Seriana: mio fratello Massimo, colui

che mi ha avvicinato alla Musica, compagna fidata di sempre.

E poi, come dimenticare la Compagnia (sì, con la C maiuscola)? Grazie per tutti i

week-end "shalli" che abbiamo passato insieme, non sapete quanto abbiano con-

tribuito al raggiungimento di questo risultato.

E inoltre vorrei ringraziare ma veramente dibbruno il mio egregio collega Matteo,

validissimo compagno di studi e soprattutto grande amico.

Infine desidero ringraziare la persona meravigliosa che mi sta vicino da quattro

anni e che mi ha reso migliore: grazie amore mio, grazie di tutto.

104

Tesi scritta in LATEX 2ε

Stampata il 21 Settembre 2006