24
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

Progetto di Reti Logiche A: realizzazione di un sistema dedicato … · 8 Progetto di Reti Logiche A: Algoritmo KL le soluzioni con l’abbandono dell’euristica. A causa di questa

  • Upload
    lamdat

  • View
    218

  • Download
    1

Embed Size (px)

Citation preview

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.

18

Progetto di Reti Logiche A: Algoritmo KL

Figura 4 – Diagramma 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