Progetto di Reti Logiche A: realizzazione di un sistema dedicato … · 8 Progetto di Reti Logiche...
Transcript of Progetto di Reti Logiche A: realizzazione di un sistema dedicato … · 8 Progetto di Reti Logiche...
Progetto di Reti Logiche A: realizzazione di un sistema
dedicato che implementa una parte dell’algoritmo KERNIGHAN-LIN
Autori: Redaelli Francesco Sacchi Davide Revisori: Marco D. Santambrogio
Data: 20/07/2005 Versione: 1.0 Stato: Draft
2
Progetto di Reti Logiche A: Algoritmo KL
Diffusione del documento
Documento interno al laboratorio di Microarchitetture, Dipartimento di Elettronica e Informazione, Politecnico di Milano.
3
Progetto di Reti Logiche A: Algoritmo KL
Revisioni
Data Versione Stato Commento
10/7/2005 1.0 Draft Prima stesura del documento
4
Progetto di Reti Logiche A: Algoritmo KL
Indice delle figure
Figura 1 : Matrice costi del caso di studio..………………………………………………………15 Figura 2 : Percorrenza codice C…………………………………………………………………..16 Figura 3 : Codice C della funzione Calcola_g...………………………………………………….17 Figura 4 : Diagramma ASM………………………………………………………………………18 Figura 5 : Risultato Simulazione…………..…...…………………………………………………21 Figura 6 : Risultati Sintesi….…………..…...…………………………………………………….22 Figura 7 : Partizione Iniziale….…………..…...………………………………………………….23
5
Progetto di Reti Logiche A: Algoritmo KL
Indice
Revisioni ______________________________________________________________________ 3
Indice delle figure _______________________________________________________________ 4
Indice _________________________________________________________________________ 5
Introduzione ___________________________________________________________________ 6
Specifica del progetto ______________________________________________________ 6
Il partizionamento _________________________________________________________ 6
Algoritmi NP-completi ______________________________________________________ 7
Algoritmo Kerninghan Lin __________________________________________________ 8
Descrizione del lavoro___________________________________________________________ 13
Strumenti e ambiente di sviluppo__________________________________________ 13
Descrizione Codice C ______________________________________________________ 13
Profiling___________________________________________________________________ 14
Da C a VHDL: ASM _________________________________________________________ 16
Descrizione VHDL _________________________________________________________ 19
Testbench_________________________________________________________________ 21
Risultati della sintesi ______________________________________________________ 22
Conclusione e sviluppi futuri_______________________________________________ 23
Bibliografia ___________________________________________________________________ 24
6
Progetto di Reti Logiche A: Algoritmo KL
Introduzione
Specifica del progetto
Lo scopo di questo progetto è lo studio e l’analisi dell’algoritmo per il partizionamento di
grafi chiamato KERNIGHAN-LIN partendo dalla descrizione ad alto livello dello stesso. Tale
analisi punta al trasferimento in hardware di parte dell’algoritmo per renderne più
efficiente e veloce l’esecuzione.
Siamo partiti dalla descrizione in pseudo-codice dell’algoritmo in questione e ne abbiamo
ricavato una versione funzionante scritta in C; abbiamo poi effettuato il Profiling decidendo
quale parte dell’algoritmo convenisse tradurre in VHDL.
Per fare ciò è stato necessario realizzare il diagramma ASM mettendo in evidenza gli stati
della FSA ricavata.
Una volta tradotto in VHDL si è potuto testare l’efficienza effettiva derivata dall’utilizzo
della nostra tecnologia.
Il partizionamento
Il problema del partizionamento si applica a diverse realtà presenti in ogni campo della
vita, a tutti quei problemi modellizzabili tramite grafi costituiti da nodi e archi pesati e si
pone come obiettivo quello di trovare la migliore suddivisione di un grafo in due o più
sottoinsiemi secondo determinati criteri, il criterio fondamentale è ottimizzare il costo delle
interconnessioni tra i vari sottografi.
Per capire appieno il perché di un algoritmo di suddivisione di grafi partiamo con un
esempio:
pensiamo alla realizzazione di un sistema complesso: questo sarà implementato come un
insieme di sistemi più piccoli e più semplici interconnessi tra loro in vari modi; riuscendo
ad ottimizzare la suddivisione del sistema di partenza in sotto-sistemi ed applicando una
opportuna connessione tra di essi si potrà ottenere il miglior compromesso in termini di
costo e performance.
7
Progetto di Reti Logiche A: Algoritmo KL
In pratica avendo a che fare con un sistema complesso l’approccio efficace per
semplificarne l’utilizzo è il seguente:
• Decomposizione del un sistema complesso in opportuni sotto-sistemi;
• Lo schema di decomposizione deve minimizzare le interconnessioni tra i sotto-
sistemi (Partioning);
• Ogni sotto-sistema può essere realizzato ed implementato in modo indipendente
velocizzando il processo di sviluppo;
• La decomposizione è gerarchica cioè si effettua finché i sotto-sistemi non
raggiungono la dimensione desiderata o il livello di semplicità che si era previsto.
Algoritmi NP-completi
Il problema fondamentale degli algoritmi di partizionamento esatti è che sono NP-completi
ed impiegano un tempo di esecuzione di ordine esponenziale rispetto al numero dei nodi
presenti nel grafo.
Per migliorare le prestazioni di algoritmi NP-completi si utilizzano dei metodi euristici, cioè
metodi che non ricercano più la soluzione migliore, ma soltanto una soluzione ottimale
dipendente dallo stato di iniziale e dei metodi di scelta per il proseguimento dell’algoritmo.
Questa scelta causa la perdita di qualità della soluzione, anche se è possibile ridurre
questa perdita di molto senza rimettere in velocità partendo da uno stato iniziale
opportuno, ma permette di ottenere risultati in fatto di tempo e di spazio di ordine
polinomiale rispetto al numero di nodi presenti nel grafo.
È quindi opportuno ricercare un algoritmo di buona efficienza sia in fatto di complessità sia
in fatto di qualità delle soluzioni; questo compromesso è essenziale per poter utilizzare in
maniera reale ed effettivamente utile il metodo di risoluzione.
I metodi euristici sono detti metodi greedy, cioè sono quei metodi che permettono di
incorrere in soluzioni non ottimali: se consideriamo lo spazio delle soluzioni di un problema
NP-complete si avrà un minimo assoluto che rappresenta la soluzione ottima da
raggiungere ed alcuni minimi relativi che rappresentano delle soluzioni ottimali
raggiungibili con determinati stati di partenza. Un algoritmo greedy ha la particolarità di
fermarsi su una soluzione ottimale senza capire di essere incappato in un minimo relativo,
non avendo a disposizione i mezzi per farlo, altrimenti si tornerebbe a dover cercare tutte
8
Progetto di Reti Logiche A: Algoritmo KL
le soluzioni con l’abbandono dell’euristica. A causa di questa particolarità la scelta dello
stato iniziale è essenziale.
Per scegliere lo stato iniziale in maniera ottimale è necessario l’intervento di un algoritmo
di scelta con complessità esponenziale rispetto al numero di nodi presenti nel grafo,
oppure è necessario un intervento umano. La prima situazione rende inutile la scelta
dell’euristica, mentre la seconda impedisce una totale automazione del processo ed è
inoltre fattibile soltanto per un numero di nodi molto basso. Si opta allora per partire da
soluzioni standard studiate precedentemente tramite analisi probabilistica del modo di
distribuirsi delle soluzioni.
Un ulteriore metodo per velocizzare l’esecuzione dell’algoritmo è la trasposizione di una
parte di esso in hardware, questo perché con l’aumentare del numero di nodi nel grafo si
ottengono comunque tempi abbastanza elevati. Portando parte del codice in hardware si
realizza un IP-core, cioè un processore dedicato appositamente alla nostra applicazione
che effettua operazioni in maniera efficiente senza introdurre i classici ritardi di un normale
processore(riconoscimento dell’istruzione, somma di istruzioni per fare un’operazione
elementare, ecc.).
Algoritmo Kerninghan Lin
L’algoritmo trattato permette di effettuare la decomposizione tramite il metodo del min-cut
e si pone come obiettivo quello di suddividere in due sottografi dello stesso ordine di nodi
un dato grafo.
Il problema di partizionamento tramite min-cut, ovvero della suddivisione di un grafo in
due sottoparti interconnesse da legami a costo minore, è un problema NP-completo
(completo non-polinomico) quindi richiederebbe una quantità di tempo enorme di ordine
esponenziale rispetto al numero di nodi: per implementare una soluzione esatta del
problema si avrebbero grossi problemi sia di tempo che di spazio. Per ovviare a questa
situazione si utilizzano delle euristiche in maniera da trovare non la soluzione ottima ma
una soluzione ottimale, naturalmente con tutti i limiti causati da questa scelta come la
dipendenza della soluzione dal punto di partenza e la possibilità di arenarsi in minimi
relativi e trovare così una partizione ottima in un suo intorno ma non quella esatta.
L’euristica su cui si basa il Kenighan-Lin è così sintetizzabile: si parte da un’arbitraria(punto
9
Progetto di Reti Logiche A: Algoritmo KL
iniziale da cui dipenderà la soluzione) partizione P1’ e P2’ del grafo P, successivamente
tramite iterazioni successive modifica i nuovi grafi scambiando sottoinsiemi di P1’ e P2’
utilizzando appunto la tecnica del min-cut in modo che il costo del ‘taglio’ effettuato risulti
il maggiore possibile in modo da ottenere due sottografi divisi da archi a minor peso.
L’algoritmo K-L effettua lo scambio, da una partizione all’altra, unicamente tra coppie di
nodi e questo viene effettuato con una complessità temporale di classe Θ(n2 log n) con
n=|P| e n2=|P1’|.
L’idea alla base dell’algoritmo di iterazione è la seguente:
finché il costo dei collegamenti tra i sottografi(costo di taglio) decresce:
• Le coppie di vertici che danno luogo a un decremento o al minimo incremento del
costo di taglio vengono scambiate;
• Questi vertici sono bloccati e non verranno più considerati come scambiabili da un
sottoinsieme all’altro;
• Il processo viene iterato finché tutti i vertici non sono bloccati
• Fatto questo l’algoritmo trova quali sono effettivamente gli scambi che hanno
apportato delle migliorie e li rende permanenti
• Sblocca tutti i vertici e ripete il procedimento fino a che si ottengono delle migliorie.
Procedendo in questa maniera è possibile quindi semplificare di molto un problema
utilizzando una tecnica molto simile a quella del Top-Down usata in programmazione; le
varie parti possono essere così sviluppate ed implementate da persone o team diversi
sfruttando una visione specialistica all’interno di ogni singola area. Una volta che i singoli
sottoproblemi sono stati affrontati nel migliore dei modi, utilizzando la soluzione data
dall’algoritmo è possibile interconnettere i vari frammenti senza perdere ulteriore tempo e
mantenendo un ottimale livello prestazionale.
Per usufruire della tecnica del min-cut è necessario poter assegnare un peso ai singoli
archi del grafo. Le strade percorribili sono due:
• se le interconnessioni non sono responsabili di ritardi significativi o comunque non
sono di grande rilevanza ai fini del partizionamento allora è preferibile assegnare ad
ognuna di esse un costo costante, di norma il più basso possibile(es.: 1); con
questa soluzione si ottiene una divisione che ha la particolarità di avere il minimo
numero di archi tra le sottoparti;
10
Progetto di Reti Logiche A: Algoritmo KL
• se le interconnessioni sono invece portatrici di ritardi e dalla loro efficienza dipende
appunto la qualità del partizionamento allora deve essergli assegnato un peso;
questo peso dipenderà dal ritardo introdotto, dalla lunghezza dell’arco o della
probabilità di incontrare traffico su di esso e da ogni altra considerazione che possa
influire sulla divisione.
Nel caso in cui i collegamenti tra i nodi siano pesati, ad ogni iterazione si devono calcolare
per ogni nodo dei valori che permetteranno di determinare il costo effettivo del taglio.
I valori determinati sono:
• costo esterno di a∈A: Ea = Σv∈B cav, cioè la sommatoria di tutti i costi degli archi
tra l’elemento a e gli elementi appartenenti all’altro sottografo;
• costo interno di a∈A: Ia = Σv∈A cav, cioè la sommatoria di tutti i costi degli archi
tra l’elemento a e gli elementi appartenenti allo stesso sottografo.
Una volta calcolati Ea e Ia è possibile ottenere una stima della bontà del posizionamento
del nodo a nella situazione attuale del partizionamento tramite il D-value del vertice a:
Da= Ea –Ia
Questo dato viene poi a sua volta utilizzato per il calcolo del guadagno ottenibile dallo
scambio di ogni coppia di vertici a∈A e b∈B:
gab= Da+ Db – 2cab
dove cab rappresenta il costo tra il nodo a ed il nodo b.
seguendo l’algoritmo sopra descritto si scelgono i nodi che ottengono il g maggiore, li si
scambiano e li si bloccano, dopodiché si ricomincia con il calcolo dei Dv in questo modo:
se a e b sono scambiati tra loro allora il nuovo valore D’ è calcolato come:
D’x=Dx+ 2cxa - 2cxb , ∀x∈A-{a}
D’y=Dy+ 2cya - 2cyb , ∀y∈B-{b}
Una volta che tutti i vertici sono bloccati si cercano gli scambi sequenziali che hanno la
caratteristica di mantenere la somma dei guadagni di taglio(gxy) maggiore di zero; finchè
questo si verifica significa che gli spostamenti di vertici hanno portato delle migliorie nella
situazione globale del partizionamento. Si deve inoltre prestare attenzione ai minimi
relativi: se un particolare gxy rende la sommatoria minore di zero non è detto che i nodi
che l’hanno generato debbano rimanere esclusi dallo scambio effettivo, poiché se il
successivo gkh fa tornare la sommatoria maggiore di zero allora tutti gli scambi precedenti
a questo sono considerati come effettivi.
11
Progetto di Reti Logiche A: Algoritmo KL
L’algoritmo sviluppato nel progetto e descritto precedentemente è il seguente:
Input: G = (V, E), |V| = 2n.
Output: Bi-partizione bilanciata composta da A e B con il minimo costo di taglio.
1 Inizio
2 Bipartizione di G in A e B tali che |VA| = |VB| , VA ∩VB = ∅ e VA ∪ VB = V.
3 Ripeti:
4 Calcola Dv, ∀ v ∈ V.
5 Per n volte (da i=1 a i<n)
6 Trova un paio di vertici sbloccati vai ∈ VA e vbi ∈ VB il cui scambio
apporta il più grande decremento o il più piccolo incremento del
costo di taglio;
7 Marca vai e vbi come locked(bloccati), memorizza il guadagno gi , e
ricalcola i nuovi Dv, per ogni vertice sbloccato v ∈ V;
8 Trova k, tale che Gk = Σki=1gi sia massima;
9 Se Gk > 0 allora
10 Sposta va1, …, vak da VA in VB e vb1, …, vbk da VB in VA;
11 Sblocca tutti i vertici v, ∀ v ∈ V.
12 Ripeti da 3 finchè Gk ≤ 0;
13 Fine
Da quanto si può vedere e da quanto detto l’algoritmo K-L è
• Iterativo, cioè si itera il procedimento finché la soluzione non migliora ulteriormente
rispetto al ciclo precedente; questo è particolare di ogni euristica poiché questo non
migliorare rispetto al ciclo precedente è la causa dei cosiddetti minimi relativi;
• 2-way: si vogliono ottenere due sottoinsiemi disgiunti di nodi;
• Bilanciato (bi-sectioning) la soluzione è composta da due insiemi della stessa
dimensione.
Fondamentale per il corretto funzionamento dell’algoritmo è che il numero di nodi sia pari
e che il grafo che modellizza il problema sia completamente connesso. Per ovviare al
secondo problema è possibile giocare sui costi degli archi: se due nodi non sono connessi
il peso attribuito al collegamento dovrà assumere valore infinito, o meglio un valore
12
Progetto di Reti Logiche A: Algoritmo KL
superiore a quello che ha l’anello con costo maggiore presente nel grafo non
completamente connesso.
Il numero di nodi deve essere pari poiché l’algoritmo è bilanciato, per poter gestire grafi di
diversa fattura oppure per poter partizionare in sottoinsiemi aventi dimensioni diverse si
utilizzano altri algoritmi come il Fiduccia-Mattheyses.
13
Progetto di Reti Logiche A: Algoritmo KL
Descrizione del lavoro
Strumenti e ambiente di sviluppo
La parte implementativa di questo progetto è stata sviluppata utilizzando principalmente i
seguenti strumenti:
• ISE (Integrated Software Environment) versione 6.3i
• ModelSim SE Plus 6.0
ISE è un prodotto della Xilinx che consente lo sviluppo completo del design di un
componente. Fornisce un ambiente completo per la realizzazione di sistemi dedicati.
Di questo ambiente è stato utilizzato Project Navigator, uno strumento che permette di
creare un sistema e seguirne tutte le fasi di sviluppo con un controllo diretto su ciascuna
di esse.
ModelSim è uno strumento prodotto dalla Mentor Graphics che permette la simulazione e
la verifica delle descrizioni hardware di un componente o di un intero sistema.
Descrizione Codice C
Partendo dallo pseudo-codice (vedi algoritmo Kerninghan Lin) abbiamo realizzato il codice
C. Per implementare il progetto abbiamo usato un approccio top down evidenziando le
funzioni principali che si potevano realizzare:
Calcola_Dv: calcola i valori dei Dv di tutti i nodi
Calcola_g: calcola il miglior guadagno ottenibile dallo scambio di una
determinata coppia di nodi
RiCalcola_Dv: usando una formula che prende in considerazione i nodi
scambiati ricalcola i valori dei Dv.
Cerca_Gk_max: calcola il numero massimo di scambi consecutivi che
mantengono il guadagno di taglio maggiore di zero.
Il codice è composto da una prima parte di acquisizione dati, inizializzazione variabili e
creazione di una prima partizione, lo stato iniziale, del grafo. Si è optato per dividere i nodi
14
Progetto di Reti Logiche A: Algoritmo KL
in ordine numerico inserendo nel primo sottoinsieme quelli con cardinalità inferiore od
uguale a n/2(con n numero di nodi presenti nel grafo) ed i restanti nel secondo
sottoinsieme.
Utilizzando un ciclo do…while che termina quando il guadagno del taglio apportato è
minore o uguale a zero, cioè quando ulteriori scambi di nodi non migliorerebbero la
situazione, si analizzano le possibili coppie di nodi.
Prima di tutto si calcolano i valori dei Dv per tutti i nodi poi si entra in un ciclo for che
richiamando la funzione Calcola_g cerca i nodi sbloccati da scambiare, poi vengono
bloccati tenendo conto del numero di iterazione raggiunto, si effettua lo scambio e
attraverso la formula semplificata si ricalcolano i Dv. Il for termina e attraverso la funzione
Cerca_Gk_max vengo scelti gli scambi effettivi da eseguire quando il guadagno Gk
restituito risulta maggiore di zero. Infine vengono sbloccati tutti i nodi e si chiude il ciclo
while.
Per verificare la validità del codice abbiamo eseguito l’algoritmo sulla base di un esempio
già risolto costituito da un grafo di 6 nodi completamente connesso controllando passo per
passo i risultati ottenuti. Abbiamo effettuato ulteriori prove con matrici di costo critiche con
diverse cardinalità di nodi: n=10, n=20, n=40.
Profiling
Per verificare quale parte di codice viene eseguita più volte e che quindi è preferibile
ottimizzare con il nostro progetto abbiamo verificato quanto tempo viene utilizzato in
media da ogni singola funzione o ramificazione dell’algoritmo ed abbiamo verificato quante
volte viene percorsa ognuna di queste. Per poter ricavare questi dati abbiamo posto dei
semplici contatori da incrementare ogni volta che si passa per un determinato punto del
codice, mentre per verificare il tempo di esecuzione abbiamo usato il seguente codice:
QueryPerformanceCounter(&t1);
//codice…
QueryPerformanceCounter(&t2);
delta = (double) (t2.QuadPart-t1.QuadPart);
racchiudendo tra le due funzioni QueryPerformanceCounter il codice da valutare.
15
Progetto di Reti Logiche A: Algoritmo KL
Il valore delta non risulta in secondi o millisecondi, ma serve ad effettuare una stima e
relazionare la parte di codice con le altre porzioni.
Abbiamo così valutato la tempistica per le parti rilevanti dell’algoritmo considerando inoltre
che il codice sopra riportato costa un valore pari a 4 dovuto al fatto che nella rilevazione di
t2 conta anche il tempo destinato ad eseguire la funzione QueryPerformanceCounter(&t2).
Per le funzioni eseguite più volte durante un’intera esecuzione è stata effettuata una
media, come si può notare dai calcoli.
I dati riportati sono relativi a un grafo composto da 20 nodi completamente connessi con
la seguente matrice di costi:
Figura 1 – Matrice costi del caso di studio
Questi i risultati:
Totale: 211 - 4 = 207 pari a 100%
Inizializzazione variabili: 5 pari a 2,4%
Calcola_Dv: (39 - 4*3 = 27)/3 = 9 pari a 13,0%
Calcola_g: (252 - 4*30 = 132)/30=4,4 pari a 63,8%
Swap + RiCalcola_Dv: (163 - 4*30 = 43)/30= 1.433 pari a 20,8%
Cerca_Gk_max: (13 - 4*3=1)/3=0,333 pari a 0,48%
do while: (197 - 4*3=185)/3=61,666 pari a 89,3%
for interno: (162- 4*3=150)/3=50 pari a 72,5%
16
Progetto di Reti Logiche A: Algoritmo KL
Il numero di volte che ogni singola porzione di codice è stata richiamata è rappresentato
dalla quantità che sta al denominatore nei calcoli precedenti; un’analisi più approfondita
sulla frequenza di esecuzione delle singole parti di codice ha riportato i seguenti risultati:
Figura 2 – Percorrenza codice C
Considerando il numero di chiamate (30) e il costo complessivo (63,8%) è risultato
evidente che l’ottimizzazione del tempo di esecuzione della funzione Calcola_g apporta un
notevole guadagno in termini di prestazioni.
Da C a VHDL: ASM
La parte di codice da tradurre nel linguaggio di descrizione Hardware VHDL è la funzione
Calcola_g.
Il passo intermedio tra C e VHDL è realizzare una macchina a stati finiti che rispecchi il
funzionamento dell’algoritmo desiderato; per fare ciò è necessario individuare il flusso
delle operazioni, suddividerlo nei vari stati dell’automa e ricavare le relative transizioni.
A tale scopo si stila un diagramma a blocchi chiamato ASM simile a un diagramma di
flusso che si compone di elementi di base quali:
• blocchi di stato nei quali vengono effettuate le operazioni parallele.
• blocchi decisionale che dirigono il flusso sulla base di una condizione che può
assumere valore vero o falso.
17
Progetto di Reti Logiche A: Algoritmo KL
In questo modo è possibile suddividere le operazioni dalle transizioni realizzando due
macro blocchi di istruzioni ovvero strutturare il sistema in data path e controllore.
Il data path esegue le espressioni regolari e aggiorna i registri di stato dell’automa; il
controllore gestisce le transizioni e imposta i segnali di controllo per il data path.
Poiché nel data path vi erano solo operazioni di modifica ai segnali di controllo, le variabili
modificate vengono tutte utilizzate nello stato successivo, abbiamo optato per unificare i
due processi.
Figura 3 – Codice C della funzione Calcola_g
Di seguito è riportato il diagramma a blocchi ASM.
19
Progetto di Reti Logiche A: Algoritmo KL
Descrizione VHDL
In questo capitolo, vengono commentate ed illustrate le parti più significative della stesura
del codice VHDL per la realizzazione della nostra macchina a stati finiti. Per poter giungere
alla scrittura della versione definitiva del codice VHDL si sono però attraversate diverse fasi
i cui ci siamo scontrati con un metodo di sviluppo diverso da quello da noi normalmente
utilizzato nell’implementazione software. Normalmente un approccio concettuale di questo
tipo permette di ricavare codice VHDL perfettamente giusto dal punto di vista sintattico,
ma completamente errato dal punto di vista semantico: non si tiene conto della diversa
sincronizzazione che viene ottenuta via hardware e non si utilizzano le variabili
accumulatrici nella maniera corretta. Siccome si tratta di descrivere hardware tutto ciò che
viene scritto sequenzialmente all’interno di un singolo processo viene poi tradotto in
blocchi logici sequenziali, cioè si creano aggregati di porte logiche inutili e lenti. Si è
dovuto prestare attenzione alla tempistica con cui le variabili vengono aggiornate, poiché
in VHDL è possibile modellizzarle con due costrutti:
- variable: ogni aggiornamento avviene istantaneamente;
- signal: l’aggiornamento viene eseguito al ciclo di clock successivo.
Dalla prima versione del codice, che conteneva fondamentalmente molti di questi errori
concettuali, siamo passati a nuove versioni cercando di sincronizzare al meglio le varie
parti in modo da ottenere l’esatta risposta semantica. Oltre a queste considerazioni
abbiamo anche apportato modifiche significative in termini di prestazioni sostituendo le
numerose moltiplicazioni per due con degli shift verso sinistra del valore binario
dell’operando. Questo ci ha permesso di trasformare tutti i segnali precedentemente
dichiarati integer in std_logic_vector risparmiando molto sull’occupazione di area; questa
semplice modifica è risultata poi fondamentale per gestire in maniera corretta gli indici di
scorrimento degli array. Infatti nella prima versione esistevano singole righe di istruzione
che facevano più operazioni elementari, per lo più indirizzamenti, per questo non
sintetizzabili in hardware con la giusta semantica e la scelta di vettori di bit ha semplificato
la disgregazione di queste macro istruzioni.
L’ultima versione VHDL è stata poi ulteriormente migliorata: sono stati tolte le ripetizioni di
codice all’interno del controllore, creando un nuovo processo per ogni blocco di istruzioni
20
Progetto di Reti Logiche A: Algoritmo KL
condiviso da più stati. In questo modo abbiamo ottenuto un aumento del parallelismo del
nostro automa, migliorandone le prestazioni in quanto si sono accorciati i percorsi di porte
logiche più lunghi. Una volta creati questi processi è stata necessaria una nuova fase di
sincronizzazione poiché è fondamentale che ognuno di essi abbia a disposizione al
momento giusto tutte le sue variabili di controllo. Un altro comune errore che si è cercato
di evitare è il multi-source. Con questo termine si intende la scrittura di un determinato
segnale da parte di più processi contemporaneamente perdendo naturalmente
consistenza.
Un ulteriore problema riscontrato è che il nostro VHDL descrive fondamentalmente una
ROM poiché il componente ha al suo interno una memoria in cui sono memorizzate tutte le
informazioni che servono per l’esecuzione: da quanto si può notare dal prototipo della
funzione Calcola_G il componente ha al suo interno i seguenti dati:
• A (vettore della parta A del grafo)
• B (vettore della parta B del grafo)
• Dv vettore che memorizza per ogni nodo i costi dei collegamenti esterni meno i
costi dei collegamenti interni
• M matrice costi
A causa di queste informazioni necessarie abbiamo deciso di procedere nello sviluppo del
processo su un grafo di 20 nodi, poiché con 40 nodi l’occupazione di area era insostenibile.
Oltre a questi dati abbiamo inserito come costanti n ed n/2 in modo da semplificare e
velocizzare le varie operazioni: n/2 è stato inserito per evitare la divisione per due,
velocizzando così il componente e diminuendone l’area di occupazione.
Per gestire l’input/output del componente abbiamo lasciato in ingresso un clock ed un
segnale di reset, mentre in uscita si hanno:
. indiceA e indiceB, che rappresentano gli indici dei due nodi da scambiare;
. valmax, che rappresenta il guadagno di taglio apportato dallo scambio dei nodi scelti.
Una volta ottenuto un codice VHDL corretto sia dal punto di vista sintattico che semantico
si è potuto procedere alla fase successiva, cioè alla verifica del corretto funzionamento
dell’algoritmo implementato.
21
Progetto di Reti Logiche A: Algoritmo KL
Testbench
Conclusa la stesura della descrizione del componente si passa alla simulazione per mezzo
di Modelsim per valutare l’effettiva correttezza del comportamento.
Siccome il componente ha al suo interno una rom e non ha ingressi che possano influire
direttamente sulle uscite presentate non è stato necessario inserire un file di testbench, è
stato sufficiente inizializzare il clock e il segnale di reset in fase di pre-simulazione; per
questo si otterranno sempre le stesse uscite a meno di modificare da codice la rom.
Per giungere all’ultima stesura del codice abbiamo simulato il tutto per scoprire eventuali
errori di sincronizzazione e rendersi conto attraverso analisi delle forme d’onda delle
effettive transizioni tra stati.
In Figura è possibile vedere l’ultima parte della simulazione e la generazione del risultato:
Figura 5 – Risultato Simulazione
22
Progetto di Reti Logiche A: Algoritmo KL
Fatto ciò abbiamo verificato che i risultati ottenuti (sia i valori delle uscite che i valori
intermedi dei segnali) corrispondessero a quelli della funzione C.
Risultati della sintesi
Affinché il componente possa diventare un IP-Core ed essere importato ed inserito
all’interno dell’architettura, è necessario che il codice che lo descrive sia sintetizzabile.
Questo vuol dire che a partire dalla descrizione hardware del componente, deve essere
possibile realizzare la rete di porte logiche che lo implementa.
Nella prima versione la rom era stata scritta in modo non corretto poiché la sintesi non
terminava. Successi miglioramenti del codice hanno permesso di realizzare l’algoritmo nel
modo richiesto dalla specifica ed una accelerazione della sintesi fino a raggiungere
all’incirca un minuto.
Figura 6 – Risultati Sintesi
23
Progetto di Reti Logiche A: Algoritmo KL
Conclusione e sviluppi futuri
Durante il progetto abbiamo appreso l’uso dei tool di sviluppo ed una buona conoscenza
del linguaggio VHDL. In particolare siamo riusciti a risolvere problematiche non semplici
relative all’organizzazione della struttura del componente sfruttando in maniera efficace il
parallelismo, i processi e la gestione di variabili di controllo multiple.
Il componente realizza la funzione Calcola_g solo per la prima iterazione dell’algoritmo,
cioè partendo dalla partizione
Figura 7 – Partizione Iniziale
ed utilizzando la matrice di costi in figura 1 si ottiengono i risultati esatti:
• valmax= 333, cioè costo di taglio pari a 333;
• indiceA= 0 e indiceB= 6 cioè i nodi da scambiare sono “A” e “S”.
In futuro ciò che si vuole ottenere è la completa automatizzazione di inserimento dei dati
in ingresso togliendo la rom dal componente e integrando quest’ultimo in un’opportuna
architettura come IP-Core. Si dovrà quindi gestire la fase di interscambio dati tra parte
software, che farà la parte del master, e la parte di hardware dedicato.
Un ulteriore sviluppo può essere quello di considerare la riconfigurabilità dinamica per
poter processare grafi di dimensione diverse da 20 nodi.
A B C D E F G H I L
M N O P Q R S T U V
Partizione B
Partizione A
24
Progetto di Reti Logiche A: Algoritmo KL
Bibliografia
[1] Xilinx “Embedded System Tools Guide”, versione 6.2, 16 giugno 2004, cap.
4/7/15/16/17/19/21.
[2] Xilinx “Platform User Studio Guide”, versione 6.3, 20 agosto 2004, cap. 5.
[3] Xilinx "Synthesis and Verification Design Guide", all'interno di "Xilinx ISE 6 Software
Manuals".
[4] IEEE Standard for VHDL Register Transfer Level (RTL) Synthesis, IEEE Std 1076.6-
1999.
[5] System Partitioning – Kris Kuchinski
[6] New Faster Kernighan-Lin-Type Graph-Partitioning Algorithms, Shantanu Dutt,
Department of Electrical Engineerig, University of Minnesota, Minneapolis