Desenvolupament d’un Traductor de Fitxers BLIF a VHDL per a la...

157
Desenvolupament d’un Traductor de Fitxers BLIF a VHDL per a la Simulació de Dissenys en Lògica Reconfigurable Multi-Context Titulació: Enginyeria Tècnica Industrial en Electrònica AUTOR: Josep Cid Prades DIRECTOR: Enric Cantó Navarro DATA: setembre de 2003.

Transcript of Desenvolupament d’un Traductor de Fitxers BLIF a VHDL per a la...

Desenvolupament d’un Traductor de Fitxers BLIF aVHDL per a la Simulació de Dissenys en Lògica

Reconfigurable Multi-Context

Titulació: Enginyeria Tècnica Industrial en Electrònica

AUTOR: Josep Cid PradesDIRECTOR: Enric Cantó Navarro

DATA: setembre de 2003.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

2

ÍNDEX

ÍNDEX..........................................................................................................................2

1 Introducció .............................................................................................................6

1.1 Descripció del projecte ..................................................................................6

1.2 Antecedents....................................................................................................7

1.3 Objectius ........................................................................................................7

1.4 Descripció de la memòria ..............................................................................7

2 BLIF.......................................................................................................................9

2.1 .model ............................................................................................................9

2.2 .inputs.............................................................................................................9

2.3 .outputs...........................................................................................................9

2.4 .clock..............................................................................................................9

2.5 .names ..........................................................................................................10

2.6 .buff o .latch .................................................................................................11

2.7 .dbuff............................................................................................................12

2.8 .end...............................................................................................................12

3 Partició Temporal de Fitxers BLIF ......................................................................13

3.1 Exemples d’estructures en fitxers particionats ............................................15

3.1.1 Elements combinacionals i seqüencials. ..............................................15

3.1.2 Circuit combinacional..........................................................................16

3.1.3 Circuit combinacional – seqüencial (1) ...............................................17

3.1.4 Circuit combinacional – seqüencial (2) ...............................................17

3.1.5 Circuit seqüencial (1)...........................................................................18

3.1.6 Circuit seqüencial (2)...........................................................................19

3.1.7 Circuit Seqüencial (3) ..........................................................................20

3.1.8 Flip Flops de dos contexts (1)..............................................................21

3.1.9 Flip Flops de dos contexts (2)..............................................................22

3.1.10 Flip Flops de dos contexts (3)..............................................................23

3.2 Exemples conceptuals de bipartició temporal. ............................................23

3.2.1 Exemple 1 ............................................................................................24

3.2.2 Exemple 2 ............................................................................................25

3.2.3 Exemple 3 ............................................................................................26

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

3

3.3 Exemple pràctic en BLIF de bipartició temporal.........................................26

4 VHDL, Llibreries per a la simulació de fitxers particionats................................29

4.1 LUT (Look Up Table)..................................................................................29

4.1.1 Codi VHDL..........................................................................................30

4.1.2 Exemple gràfic LUT ............................................................................30

4.2 DFF (Flip Flop d’un context/comunicació) .................................................31

4.2.1 Codi VHDL..........................................................................................31

4.2.2 Exemple gràfic DFF.............................................................................32

4.3 DLUT (LUT de dos contexts)......................................................................33

4.3.1 Codi VHDL..........................................................................................34

4.3.2 Exemple gràfic DLUT .........................................................................34

4.4 BDFF (Flip Flop de doble context)..............................................................36

4.4.1 Codi VHDL..........................................................................................37

4.4.2 Exemple gràfic BDFF..........................................................................38

4.5 Recursos de rutatge de fitxers particionats. .................................................38

4.5.1 RUT_IN (Recursos de rutatge d’entrada) ............................................39

4.5.2 RUT_OUT (Recursos de rutatge de sortida) .......................................41

5 Software de Traducció BLIF- VHDL..................................................................43

5.1 Especificacions del BLIF i del VHDL que cal tenir en compte. .................43

5.1.1 Noms dels Senyals ...............................................................................43

5.1.2 Senyals Primaris ..................................................................................45

5.1.3 Senyals No Primaris.............................................................................45

5.1.4 Senyals Multiplexats............................................................................45

5.1.5 Llistes de senyals de més d’una línia..................................................49

5.1.6 Senyals OUT en VHDL.......................................................................50

5.1.7 Rutatges ...............................................................................................50

5.1.8 Contingut de les LUTs.........................................................................52

5.2 Entorn del programa Traductor....................................................................52

5.2.1 Pas de paràmetres.................................................................................53

5.3 Programa Traductor en llenguatge C++.......................................................55

5.3.1 Aspectes generals del programa ..........................................................55

5.3.2 Anàlisi del BLIF en memòria. .............................................................55

5.4 Fitxers que componen el projecte. ...............................................................58

5.4.1 Tabinterface.cpp ..................................................................................58

5.4.2 Traductor.cpp .......................................................................................59

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

4

5.4.3 Entity.cpp .............................................................................................62

5.4.4 Lut.cpp .................................................................................................63

5.4.5 Buff.cpp ...............................................................................................64

5.4.6 DBuff.cpp ............................................................................................65

5.4.7 Rut_in.cpp............................................................................................65

5.4.8 Rut_out.cpp..........................................................................................66

5.4.9 Printer_1ctx.cpp...................................................................................66

5.4.10 Pinter.cpp .............................................................................................67

6 Gràfiques i resultats experimentals......................................................................71

6.1 Exemple adder .............................................................................................71

6.1.1 adder.bli ...............................................................................................71

6.1.2 adder.vhd..............................................................................................72

6.1.3 adder_0.bli ...........................................................................................73

6.1.4 adder_1.bli ...........................................................................................74

6.1.5 adder_2ctx.vhd.....................................................................................75

6.1.6 Gràfiques d’ adder.vhd ........................................................................77

6.1.7 Gràfiques d’ adder_2ctx.vhd ................................................................78

6.2 Exemple comptador .....................................................................................81

6.2.1 comptador.bli .......................................................................................81

6.2.2 comptador.vhd .....................................................................................82

6.2.3 comptador_0.bli ...................................................................................83

6.2.4 comptador_1.bli ...................................................................................84

6.2.5 comptador_2ctx.vhd ............................................................................84

6.2.6 Gràfica de comptador.vhd....................................................................87

6.2.7 Gràfica de comptador_2ctx.vhd...........................................................87

6.3 Exemple S27_n ............................................................................................88

6.3.1 s27_n.bli...............................................................................................88

6.3.2 s27_n.vhd.............................................................................................89

6.3.3 s27_n_0.bli...........................................................................................90

6.3.4 s27_n_1.bli...........................................................................................90

6.3.5 s27_n_2ctx.vhd ....................................................................................91

6.3.6 Gràfica de s27_n.vhd ...........................................................................94

6.3.7 Gràfica de s27_n_2ctx.vhd ..................................................................94

6.4 Exemple S5378_n ........................................................................................94

6.4.1 Gràfica de s5378_n.vhd .......................................................................95

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

5

6.4.2 Gràfica de s27_n.vhd ...........................................................................95

7 Conclusions i futures millores. ............................................................................97

8 Bibliografia. .........................................................................................................99

9 Annex: Codi del Software..................................................................................100

9.1 Tabinterface.cpp ........................................................................................100

9.2 Traductor.cpp .............................................................................................103

9.3 Entity.cpp ...................................................................................................111

9.4 Lut.cpp .......................................................................................................115

9.5 Buff.cpp .....................................................................................................120

9.6 Dbuff.cpp ...................................................................................................123

9.7 Rut_In.cpp..................................................................................................126

9.8 Rut_Out.cpp...............................................................................................127

9.9 Printer_1ctx.cpp.........................................................................................128

9.10 Printer.cpp..............................................................................................133

9.11 Tabinterface.h ........................................................................................145

9.12 Traductor.h.............................................................................................147

9.13 Entity.h...................................................................................................149

9.14 Lut.h .......................................................................................................150

9.15 Buff.h .....................................................................................................151

9.16 Dbuff.h ...................................................................................................152

9.17 Rut_In.h .................................................................................................153

9.18 Rut_Out.cpp...........................................................................................154

9.19 Printer_1ctx.h.........................................................................................155

9.20 Printer.h..................................................................................................156

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

6

1 Introducció

1.1 Descripció del projecte

Aquest projecte consisteix en la realització d’un programa escrit en C++ que permeti obtenir codi VHDL a partir de dos BLIF, per a la simulació de la partició temporal de dissenys digitals sobre lògica reconfigurable multi-context.

És un projecte de tipus Simulació / Programació i vinculat al Suport a la Recerca.

El procés de desenvolupament ha constat de les següents parts, que detallarem al llarg d’aquest informe.

1. Estudi del concepte de partició temporal i lògica reconfigurable multi-context.

2. Estudi del VHDL i simulació lògica basada en aquest llenguatge.

a. Creació de fitxers en VHDL que seran llibreries per als fitxers VHDL generats pel Traductor.

b. Traducció manual de fitxers BLIF i simulació dels mateixos (normals i particionats) utilitzant les anteriors llibreries

c. Comprovació de les simulacions

3. Desenvolupament d’un programa en C++ que “tradueixi” un netlist BLIF a codi VHDL simulable

4. Desenvolupament d’un programa en C++ que “tradueixi” un netlist BLIF particionat temporalment a codi VHDL simulable

5. Comprovació experimental de resultats.

El projecte consisteix en un traductor per a fitxers particionats, però com que no hi havia cap traductor de fitxers “normals” BLIF a VHDL també n’hem implementat un.

D’aquesta manera podem comparar les gràfiques generades per un fitxer VHDL de lògica multi-context i les del fitxer original abans de la partició.

fitxer.bli

fitxer.vhd

fitxer_0.bli

fitxer_2ctx.vhd

fitxer_1.bli

Figura 1.1. Flux del programa

Traductor

BLIF – VHDL

Traductor_2ctx.exe

BIPARTICIÓ

Algoritme

BIPARTICIÓ

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

7

1.2 Antecedents

L’antecedent d’aquest projecte (traductor BLIF - VHDL) el trobem en l’estudi fet pel Dr. Enric Cantó en el camp de la bipartició temporal multiplexada i els seus avenços en l’elaboració d’un software que particiona fitxers BLIF per a poder ésser utilitzats en simulació de circuits implementats en FPGA’s Multi -context.

1.3 Objectius

L’objectiu principal és demostrar que aquest software de bipartició temporal de fitxers BLIF realitzat per Enric Cantó, genera fitxers que són simulables i que aquestes simulacions corresponen a les simulacions del fitxer original abans de la partició.

Per a fer això, s’ha tingut en compte al llarg de tot el procés l’estructura física de l’FPGA Multi -context.

1.4 Descripció de la memòria

Per a l’elaboració d’aquest software s’han estudiat diferents llenguatges, tant de programació com de descripció hardware.

En el capítol 2, farem una petita introducció al llenguatge BLIF i explicarem els elements d’aquest llenguatge que ens han estat necessaris per a entendre les estructures emprades en els fitxers BLIF objecte de traducció pel software de que consta aquest projecte.

El llenguatge de descripció hardware VHDL (Very-High-Speed-Integrated-Circuits Hardware Description Language) no serà explicat en aquest informe ja que és un llenguatge estàndard, a diferència del BLIF, i es pot consultar informació en la bibliografia que s’adjunta al final de la memòria.

En el capítol 3, introduirem la teoria de Partició Temporal i analitzarem per què s’utilitza i com es desenvolupa aquesta partició. Veurem algun exemple i en comentarem les característiques sobre el mateix.

En el capítol 4, veurem els elements en VHDL utilitzats pels fitxers generats pel Traductor. Estudiarem què fa cadascun d’aquests elements i el perquè del seu disseny.

En el capítol 5, ens centrarem en el Software Traductor i explicarem tots els factors que s’han tingut en compte a l’hora d’escriure el codi en C++. Veurem el flux del programa, com funciona, com s’utilitza i com i on es generen els fitxers traduïts. Al mateix temps, sabrem com es comporten els diferents fitxers *.cpp de que consta el projecte Traductor_2ctx.bpr emfatitzant sobre les rutines de més rellevància per tal de comprendre el com i el perquè d’aquestes rutines.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

8

En el capítol 6, analitzarem i aprendrem a interpretar les gràfiques generades pels fitxers VHDL i demostrarem que la bipartició temporal dels fitxers ha estat implementada de manera correcta.

En el capítol 7, exposarem les conclusions que d’aquest projecte s’extreuen i parlarem de les possibles ampliacions per al futur.

Finalment, en l’apartat d’annexes veurem exemple s de traduccions amb el fitxer BLIF i el seu corresponent VHDL tant normals com particionats i veurem el codi del programa en C++.

Per acabar exposarem la bibliografia utilitzada.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

9

2 BLIF

L’objectiu del llenguatge BLIF (Berkeley Logic Interchange Format) é s el de descriure un circuit jeràrquic a nivell lògic en forma de text. Un circuit pot ser vist com a una xarxa de nodes de funcions lògiques combinacionals o seqüencials.

Analitzarem les paraules clau que utilitzen els fitxers BLIF que són traduïts mitjançant aquest software i així entendrem el seu disseny final VHDL. Els comentaris en fitxers BLIF es fan col· locant el caràcter ‘#’ just al davant del text i corresponen a una única línia.

2.1 .model

La paraula que segueix a “.model” ens indica el nom del circ uit modelat amb aquest llenguatge de descripció hardware BLIF.

2.2 .inputs

Quan trobem “.inputs” sabem automàticament que lo que segueix són les entrades primàries del circuit. Si trobem el caràcter ‘\’ se’ns està indicant que a la següent línia continuen les entrades primàries. Aquest caràcter s’utilitza en tot moment al llarg del codi BLIF quan el que segueix una paraula clau no cap en una línia.

Les senyals no primàries del circuit no es declaren, quan el BLIF troba un senyal al llarg del codi que no correspon ni a entrades ni sortides l’assigna automàticament a una senyal no primària.

2.3 .outputs

És l’equivalent de la paraula clau anterior, però en aquest cas relatiu a les sortides primàries del circuit.

2.4 .clock

Com el seu nom indica, ens senyala els diferents rellotges que el circuit pot tenir, en el nostre cas els circuits tenen un únic rellotge que generalment s’anomena “clk”.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

10

2.5 .names

Amb aquest nom identifiquem les Look Up Tables ( LUT’s) del circuit. Una LUT no és més que una zona de memòria, normalment ROM a la que ens adrecem mitjançant uns índexs.

Exemple: .names a b c d Sortida correspondria a un model com el de la Figura 2.1

Sortida (1-0)

(0-1) a

(0-1) b

(0-1) c

(0-1) d

Figura 2-1. Contingut LUT

A la Figura 2-1 observem l’estructura interna d’una LUT, les seves quatre entrades codificades en binari indiquen l’índex d e la taula que conté el valor que desitgem a la sortida, d’aquesta manera per a una combinació d’entrada (a,b,c,d) = (0,0,0,0) la sortida obtinguda serà ‘0’, i així respectivament.

Per a saber quin és el contingut de la LUT hem de mirar les línies que segueixen a la línia on trobem “. names” com s’indica a la continuació de l’exemple anterior.

15 0

14 1

13 1

12 1

11 1

10 1

9 1

8 1

7 1

6 0

5 0

4 0

3 0

2 0

1 0

0 0

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

11

Exemple:

.names a b c d Sortida

0111 1

1-0- 1

10-- 1

1--0 1

Interpretació: les línies que segueixen .names a b c d Sortida són números en binari amb valors ‘1’, ‘0’, ó ‘ -‘. Per a completar la taula de la LUT, hem de convertir aquest número en binari a decimal i aquest ens indicarà l’índex a la taula on tenim el valor (també en binari) de més a la dreta. Quan trobem 1-0- sabem que això és igual a dir 1000, 1001, 1100, 1101. En aquest cas, els índex 8,9,12,13 també contindran el valor ‘1’

2.6 .buff o .latch

És el distintiu de Flip Flop tipus D, en fitxers BLIF sense particionar s’utilitzen com a retard o element de sincronització amb la resta del circuit. En fitxers particionats tenen la funció de buffers de comunicació de dades d’un context a l’altre. En parlarem d’aquestes comunicacions en el capítol 3.

L’estructura habitual amb que ens trobarem és:

.buff Input Output clk re 0

On

“Input” és l’entr ada,

“Output” és la sortida,

“clk” és el rellotge,

“re” indica rising edge que és actiu amb el flanc de pujada,

“0” és el valor inicial del Flip Flop

Figura 2-2. Flip Flop (.buff)

clk

DFF

FF1

D QInput Output

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

12

2.7 .dbuff

És el distintiu de Flip Flop tipus D de doble context, en el proper capítol en parlarem amb profunditat d’aquest element. Només existeix en fitxers particionats i té la funció d’emmagatzemar una dada mentre el circuit canvia de configuració (multiplexa) i alliberar-la quan el context on s’ha emmagatzemat torna a estar actiu. No és un element estàndard i s’ha dissenyat expressament per a fitxers particionats.

És un cas homòleg a l’anterior i l’estructura habitual amb que ens trobarem és:

.dbuff Input Output clk re 0

On

“Input” és l’entrada,

“Output” és la sortida,

“clk” és el rellotge,

“re” indica rising edge que és actiu amb el flanc de pujada,

“0” és el valor inicial del Flip Flop

Figura 2-3. Flip Flop doble context (.dbuff)

2.8 .end

Quan trobem “.end” la descripció ha acabat. És l’indicador de final de c odi.

En el proper capítol veurem un exemple de partició temporal en fitxers BLIF i analitzarem amb més profunditat com s’interpreten totes aquestes paraules clau de forma física en un circuit.

OutputBDFF

FF1

D QInput

clk

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

13

3 Partició Temporal de Fitxers BLIF

Els dispositius lògics FPGAs reconfigurables dinàmicament (DRFPGAs) tenen com a característica la possibilitat de canviar la funcionalitat d’una porció dels seus blocs lògics, mentre la resta del dispositiu executa una altra tasca computacional. Les FPGAs multi-context permeten una reconfiguració dinàmica molt ràpida, degut a que els nous bits de configuració es troben emmagatzemats en una memòria interna.

Gràcies a l’algoritme de bipartició temporal que serveix de base a aquest projecte, es podrà aprofitar l’arquitectura de les FPG As multi-context per tal d’implementar dissenys de major grandària que la capacitat dels recursos hardware del dispositiu.

La partició temporal consisteix en agafar un circuit determinat que té un temps de cicle concret i dividir-lo en altres circuits més petits anomenats contexts que s’executaran de forma consecutiva i amb un nou temps de cicle cadascun d’ells anomenat micro-cicle. El conjunt dels diferents micro-cicles (temps d’execució de cada context) forma el macro -cicle. El macro-cicle és el temps que necessita el conjunt de particions per a implementar el circuit equivalent a l’original.

A la figura 3-1 veiem un esquema conceptual de lo que és la partició temporal. En el nostre cas particular treballarem amb circuits particionats en dos contexts, és el que anomenem bipartició temporal.

Figura 3-1. Partició temporal

Large CircuitII OO

Cycle

IContext#1 Context#2 Context#k

O

Micro-cycle Micro-cycle Micro-cycle

Macro-cycle

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

14

La partició temporal no s’ha de confondre amb la partició espacial o en àrea. Com podem observar en la figura 3-2 (a) un circuit original d’una àrea A i un temps de cicle T determinats, el podem particionar en l’espai obtenint dos particions de tamany la meitat de l’àrea original com veiem a la figura 3-2(b). Això implica un sobrecost en àrea Ac degut als recursos de rutatge. Hem aconseguit que durant el mateix temps de cicle hi hagi dos circuits (particions) executant-se en paral· lel.

Quan es tracta de partició temporal, aquesta no només té la propietat de reduir l’area del circuit de la mateixa forma la partició espacial, sinó que cadascuna de les particions s’executa en un temps de cicle menor al del model anterior. Aquesta propietat juntament amb la possibilitat de multiplexar els dos contexts perquè s’executen en cicles diferents fa que la partició temporal sigui més òptima que l’espacial. Cal tenir en compte que a part del sobre cost en àrea que també trobem en el cas de la partició espacial, en la partició temporal trobem un sobre-cost en temps degut al temps de reconfiguració interna dels circuits.

Figura 3-2. Partició espacial

En els circuits particionats les entrades, sortides, Lut’s i Flip Flop’s i es troben multiplexades és per això que s’utilitzen els recursos de rutatge per tal d’identificar una entrada o sortida amb el context al que correspon. A continuació mostrarem alguns exemples de com s’aplica la partició temporal i com s’agrupen i aprofiten les estructures hardware per tal de poder implementar dissenys de majors dimensions que la capacitat del dispositiu.

VA

T

V/2 V/2A/2

AC

T/2 T/2TC

V/2

V/2A/2

AC

A/2

(a)

(c)(b)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

15

Un dels principals problemes per a la implementació de circuits virtuals en FPGAs multi-context és el mecanisme que s’ha d’utilitzar per a una comunicació eficient de les senyals entre els diferents contexts, ja que comparteixen els mateixos recursos hardware de forma multiplexada. L’arquitectura d’alguns dispositius multi -context permet l’execució d’una partició i l’emmagatzemament de les senyals resultants en uns recursos anomenats de ‘buffering’ ( .buff i .dbuff1 en BLIF).

La partició temporal del disseny per a aquests dispositius es realitza executant el dispositiu en cada micro-cicle2 una partició en un context i disparant un nou canvi de context que mapeja el següent nivell lògic. Cada context obté les seves entrades del context executat durant l’anterior micro -cicle, que té emmagatzemades les sortides en els recursos de ‘buffering’

3.1 Exemples d’estructures en fitxers particionats

3.1.1 Elements combinacionals i seqüencials.

Figura 3-3. LUT i Flip Flop

A la figura 3-3(a) veiem un circuit combinacional que en els nostres fitxers BLIF s’implementaria en forma de LUTs. Observem que la sortida es genera en el mateix m acro-cicle3 [MT].

A la figura 3-3(b) trobem un Flip Flop de tipus D que fa de buffer de comunicació entre dos macro-cicles.

1 El “dbuff” o DFF de doble context és un element que només existeix en fitxers particionats de lògica multi -

context i no és estàndard. 2 Anomenem Macro-cicle al conjunt dels dos contexts, ctx 0 i ctx 1. Cadascuna d’aquestes particions

s’anomenen micro -cicles. 3 Quan parlem de Macro-cicle [Mx] ens referim al conjunt de dos contexts, d’aquesta manera identifiquem el

mT-1 amb el primer context i mT amb el segon context.

Combinational SequentialI O (I )

(a) (b)

MT MT MT

IMT-1

O (I )MT MT-1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

16

3.1.2 Circuit combinacional.

A la figura 3-4 veiem un circuit combinacional on la sortida és llegida en el mateix context utilitzant els recursos de rutatge del dispositiu. A l’esquerra observem el primer context on tenim l’element físic i a la dreta en color més transparent veiem l’espai que es pot utilitzar per a implementar un altra LUT en el segon context.

Figura 3-4. Circuit combinacional (1)

El cas de la figura 3-5 és idèntic amb la diferència de que la LUT es troba en el segon context.

Figura 3-5. Circuit combinacional (2)

MT,m1

O (I )

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

IMT,m1 MT,m1

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT,m2

IMT,m2

I O (I )MT,m2 MT,m2

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

17

3.1.3 Circuit combinacional – seqüencial (1)

A la figura 3-6 veiem un circuit combinacional al primer context la sortida del qual és llegida en el següent context, és per això que s’utilitza el DFF. Observem que el Flip Flop té la seva entrada a m1 i la seva sortida a m2.

Figura 3-6. Circuit combinacional – seqüencial (1)

3.1.4 Circuit combinacional – seqüencial (2)

A la figura 3-7 la sortida d’una funció síncrona mapejada al context C 2 és llegida al següent micro-cicle utilitzant els recursos de rutatge del dispositu.

Figura 3-7. Circuit combinacional – seqüencial (2)

DFF

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT,m1

I

O (I )MT,m1 MT,m1

O (I )MT,m2 MT,m1

O (I )MT-1,m1 MT-2,m2

O (I )MT,m1 MT-1,m2

MT,m2

I

MT-1,m2

I

MT-1

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

18

3.1.5 Circuit seqüencial (1)

La figura 3-8 mostra una funció síncrona mapejada al segon context C2 però el valor de la seva sortida és llegit al mateix context. És per això que utilitzem un DFF.

Figura 3-8. Circuit seqüencial (1)

DFF

MT-1

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT-1,m2

IO (I )

MT-1,m1 MT-2,m2

O (I )MT-1,m2 MT-2,m2

DFF MT,m2

IO (I )

MT,m1 MT-1,m2

O (I )MT,m2 MT-1,m2

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

19

3.1.6 Circuit seqüencial (2)

A la figura 3-9 un DFF és utilitzat com a recurs de buffer si la funció és mapejada al context C1 i la seva sortida é llegida al mateix context.

Figura 3-9. Circuit seqüencial (2)

DFF

MT-1

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

DFF

MT-1,m1

I

MT,m1

I

O (I )MT-1,m2 MT-1,m1

O (I )MT-1,m2 MT-1,m1

O (I )MT,m2 MT,m1

O (I )MT,m2 MT,m1

O (I )MT,m1 MT-1,m1

O (I )MT-1,m1 MT-2,m1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

20

3.1.7 Circuit Seqüencial (3)

Els dos DFFs són utilitzats si la funció és mapejada al context C1 i llegida a C2. Veure figura 3-10.

Figura 3-10. Circuit seqüencial (3)

DFFDFF DFF

MT-1

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

DFFDFF DFF

MT-1,m1

I

MT,m1

I

O (I )MT-1,m2 MT-1,m1

O (I )MT-1,m2 MT-1,m1

O (I )MT,m2 MT,m1

O (I )MT,m2 MT,m1

O (I )MT,m1 MT-1,m1

O (I )MT,m2 MT-1,m1

O (I )MT-1,m2 MT-2,m1

O (I )MT-1,m1 MT-2,m1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

21

3.1.8 Flip Flops de dos contexts (1)

Utilitzant un Flip Flop multi-context s’emmagatzema un recurs de buffer, quan es mapeja una funció síncrona al context C2 que és llegida al mateix context. La sortida del BDFF (Flip Flop de Doble Context) és l’entrada del mateix micro -cicle, però Macro-cicle anterior.

Figura 3-11. BDFF (1)

MT-1,m2

I

O (I )MT,m2 MT-1,m2

O (I )MT-1,m2 MT-2,m2

MT,m2

I

MT

m1 m2

C1 C2

MT

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

22

3.1.9 Flip Flops de dos contexts (2)

Exemple anàlog al context 1. Utilitzant un FF multi-context s’emmagatzem a un recurs de buffer, quan es mapeja una funció síncrona al context C1 que és llegida al mateix context.

Figura 3-12. BDFF (2)

MT

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT-1,m1

I

MT,m1

IO (I )

MT,m1 MT-1,m1

O (I )MT-1,m1 MT-2,m1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

23

3.1.10 Flip Flops de dos contexts (3)

Quan la funció font és mapejada al primer context C1 i llegida al segon C2 , un recurs de buffer (DFF) s’encarrega de mapejar la sortida al següent context.

Figura 3-13. BDFF(3)

3.2 Exemples conceptuals de bipartició temporal.

En aquest apartat veurem que la bipartició temporal pot ser implementada de vàries formes i que en funció de com apliquem aquest algoritme de bipartició temporal obtindrem uns resultats o uns altres.

Els exemples següents mostren diferents opcions de bipartició sobre un mateix circuit i com queden els fitxers particionats finals.

DFFDFF

MT

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

MT-1

m1 m2

C1 C2

DFFDFF

MT-1,m1

I

MT,m1

IO (I )

MT,m1 MT-1,m1

O (I )MT-1,m1 MT-2,m1

O (I )MT,m2 MT-1,m1

O (I )MT-1,m2 MT-2,m1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

24

3.2.1 Exemple 1

Figura 3-14. Partició (1)

En l’exemple de la figura 3-14 la funció síncrona ha estat mapejada al segon context C2 de la cel· la FF, mentre les funcions combinacionals han estat mapejades al primer context C1 de les cel· les de LUT. El valor de la xarxa combinacional és transferit del primer micro-cicle m1 al segon m2 del mateix macro-cicle MT utilitzant un recurs de buffer mapejat al primer context C1 de la mateixa cel· la FF que mapeja la funció síncrona al segon context C2. El valor de la xarxa a m1 és guardat pel flanc del rellotge del micro-cicle, fixant l’entrada de la cel· la FF a la sortida de la cel· la LUT que mapeja la funció combinacional, i aleshores un canvi de context té lloc. Durant l’execució del segon context C2 la senyal combinacional és disponible a la sortida de la cel· la FF que ha mapejat el recurs de buffer al primer context C1 fins que un nou flanc de rellotge de micro-cicle dispara un canvi de context.

LUT1 LUT2

LUT1 LUT1

(a)

(b)

FF1

D Q

DFFFF1

C1C2

LUT2 LUT2

FF1

D Q

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

25

3.2.2 Exemple 2

Figura 3-15. Partició (2)

La figura 3-15 representa una bipartició temporal on la funció combinacional destí ha estat mapejada al segon context C2 de la cel· la LUT, compartint la mateixa cel· la en mode dinàmic que la funció combinacional mapejada al context C1. El recurs de buffer ha d’estar mapejat al primer context com la funció síncrona, per ta nt no poden compartir la mateixa cel· la FF. En aquest cas el nombre de cel· les LUT ha estat reduït, però el nombre de FFs ha estat incrementat si ho comparem amb l’exemple anterior.

LUT1 LUT1

LUT1 LUT1

(a)

FF1

D Q

DFFFF2

FF1

D Q

FF2

C1 C2

FF1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

26

3.2.3 Exemple 3

Figura 3-16. Partició (3)

Finalment, la figura 3-16 representa la bipartició si les funcions destí estan mapejades al segon context C2 d’una cel· la LUT i FF, per tant el primer context d’aquestes cel· les pot estar compartit amb la funció font i el recurs de buffer respectivament. D’aquesta forma, un simple parell d e cel· les constituït per una cel· la LUT i una FF en mode dinàmic, és suficient per a mapejar el circuit virtual.

3.3 Exemple pràctic en BLIF de bipartició temporal.

A continuació veurem un exemple pràctic d’un fitxer molt senzill en BLIF particionat pel software de bipartició.

Veurem el codi BLIF i el corresponent model de blocs gràfic, d’aquesta manera podrem apreciar com es divideix el circuit, com s’apliquen FFs de comunicació i com es comparteixen les cel· les abans explicades.

És important distingir entre entrades i sortides primàries, i senyals intermitjos en fitxers BLIF. Una entrada primària és un senyal d’entrada al circuit que prové de l’exterior del circuit; una sortida primària és un senyal de sortida que prové de l’interior del circuit i el comunica a l’exterior. Les entrades i sortides primàries es defineixen com hem explicat anteriorment mitjançant les sentències .inputs i .outputs. En el següent exemple veurem que les llistes d’entrades . inputs i sortides .outputs dels fitxers particionats no corresponen a les del fitxer BLIF original. Això és perquè s’hi han afegit els senyals de comunicació

LUT1 LUT1

LUT1 LUT1

(a)

(b)

C1 C2

FF1

D Q

FF1

D QDFF

FF1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

27

entre els diferents contexts ja que a efectes de la partició també són entrades exteriors encara que no ho siguin del circuit global original.

Observem que en els fitxers particionats hi ha senyals que porten el caràcter ‘*’ al davant del nom, es tracta de senyals provenint del context anterior mitjançant els FFs de comunicació de que hem parlat. És el que anomenem senyals bufferades.

Figura 3-17. Exemple partició

Es tracta d’un sumador de 2 bits a i b amb sortida add i bit de carry Cout. S’ha implementat mitjançant dues LUT’s i un DFF. Hi ha un senyal intern Cin que funciona de carry d’entrada. La bipartició que s’aplicarà serà la indicada per la línia de punts i que generarà els circuits particionats que veurem a continuació.

Els dos fitxers generats són aquests que tenim a la Figura 3-18 i a sota mateix del seu codi tenim l’esquema circuital corresponent. Podem veure que l’estructura física del circuit ha canviat i hem passat de tenir dos LUTs i un DFF a tenir una única LUT i 4 DFFs. Tots aquests elements són reconfigurables, com hem explicat anteriorment, i podem veure que les LUTs de diferents contexts comparteixen totes dues la mateixa cel· la, a l’igual que el DFF del context 1 comparteix la cel· la del primer DFF del context 0. Els altres tres FFs del context 0 no són utilitzats durant el context 1 és per aquest motiu que tenen un color diferent.

En el capítol 6 d’aquest informe veurem aquest mateix exemple amb les seves gràfiques i els circuits particionats multiplexats.

.model adder

.inputs a b

.outputs add Cout

.clock clk .latch Cout Cin re clk 0

.names Cin a b add 001 1 010 1 100 1 111 1 .names Cin a b Cout 011 1 101 1 110 1 111 1 .end

LUT1

DFFFF1

LUT2

Cin

ab add

Cout

Cin

CinC1

C2

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

28

CONTEXT 0 CONTEXT 1

.model Context#0

.inputs Cin a b

.outputs Cout *Cout *Cin *a *b

.clock clk

.names Cin a b Cout 011 1 101 1 110 1 111 1 .buff Cout *Cout RE clk 0 .buff Cin *Cin RE clk 0 .buff a *a RE clk 0 .buff b *b RE clk 0 .end

.model Context#1

.inputs *Cout *Cin *a *b

.outputs Cin add

.clock clk

.latch *Cout Cin re clk 0

.names *Cin *a *b add 001 1 010 1 100 1 111 1 .end

Figura 3-18. Exemple fitxers particionats

LUT1

FF1

D Q

FF4

FF3

D Q

FF2

D Q

D Q

ab

Cin

Cout *Cout

*Cin

*a

*b

clk

LUT1 FF1

D Q

FF4

FF3

D Q

FF2

D Q

D Q

add Cin*a*b

*Cin

*Cout

clk

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

29

4 VHDL, Llibreries per a la simulació de fitxers particionats.

En aquest capítol veurem els elements emprats en VHDL per a poder simular els circuits BLIF un cop aquests han estat traduïts. Els elements bàsics dels circuits BLIF amb que treballem són les LUTs (Look Up Tables) i els FFs (Flip Flops). És per aquest motiu que els primers dissenys que veurem seran aquests dos elements que són justament els emprats en simulacions d’un context 4; tot seguit veurem els fitxers de doble context.

Durant la realització del projecte, el disseny d’aquests fitxers llibreria és el pas previ al procés de traducció manual de fitxers BLIF i s’ha tingut sempre en compte el funcionament físic del dispositiu modelat.

4.1 LUT (Look Up Table)

Es troba al fitxer LUT.vhd. Físicament consisteix en una zona de memòria indexada a la qual es pot accedir de forma aleatòria. Les LUTs amb que treballarem seran com a màxim de quatre entrades (índex) lo que significa que la seva grandària màxima és de 16 elements (24=16, 0÷15). És per aquest motiu que el valor per defecte de la LUT és de 16 elements inicialitzats tots a ‘U’.

A l’ igual que tots els models dissenyats en VHDL d’aquesta llibreria, s’ha tingut en compte que aquests poden generar retards. D’aquesta manera, se li passa per generic5 el valor d’aquest retard, juntament amb el contingut de la LUT.

El seu funcionament és senzill, quan qualsevol dels valors d’entrada (índex) canvia el seu estat el model s’executa convertint aquest índex de quatre bits en un número en binari que serà utilitzat per a adreçar la taula que conté la informació (bits). Aleshores, la sortida s’actual itzarà amb aquest nou valor després del temps de delay.

Aquest model no forma part dels fitxers particionats però hem decidit incloure’l en aquest apartat perquè aquest disseny ha estat utilitzat per a la traducció de fitxers BLIF normals i ha fet de base del model DLUT (LUT de dos contexts) que veurem a l’ apartat 4-3. Podem veure el seu esquema en la figura 4-1.

Figura 4-1. LUT

4 Descriurem com a fitxers d’un context els traduïts del fitxer BLIF original, i com a fitxers de dos contexts

els traduïts a partir dels dos fitxers BLIF particionats amb les seves entrades i sortides multiplexades i els LUTs i FFs d’un i dos contexts.

5 Veure bibliografia bàsica de VHDL

Table 0

in_3

in_2

in_1

in_0

Sdelaydelay

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

30

4.1.1 Codi VHDL -- Al fitxer LUT.vhd LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; ENTITY LUT IS generic (Delay : Time := 0 ns; Table_0 : STD_LOGIC_VECTOR(0 TO 15):="UUUUUUUUUUUUUUUU" ); port( in_3, in_2, in_1, in_0 : IN STD_LOGIC:='U'; S : OUT STD_LOGIC); END LUT; ARCHITECTURE funcional OF LUT IS BEGIN PROCESS (in_3,in_2,in_1,in_0) variable n : integer:=0; variable entrada : std_logic_vector(3 downto 0); BEGIN entrada(0):=in_0; entrada(1):=in_1; entrada(2):=in_2; entrada(3):=in_3; n:=CONV_INTEGER(entrada); S<=table_0(n) after delay; END PROCESS; END funcional;

4.1.2 Exemple gràfic LUT

La figura 4-2 mostra un exemple de com funciona el model de LUT que hem creat en VHDL. Aquest exemple s’ha extret de traduir les següents línies de codi BLIF a VHDL:

BLIF: .names G3 G2 G1 G0 G17 001- 1 00-1 1

VHDL:constant LUT_G17 : STD_LOGIC_VECTOR(0 TO 15):="0111000000000000";

Es tracta d’una LUT de quatre entrades (16 índexs) on només els índex 1,2 i 3 contenen un ‘1’ lògic (recordem la teoria de l’apartat 2-5). D’aquesta manera descodificant aquests valors binaris, assignem als seus corresponents índexs el valor ‘1’ i creem la taula que veiem en el codi VHDL. Un cop tenim això i sabent que G3 – G0 són les entrades (G3 és el bit de més pes) i que G17 és la sortida, podem observar a la figura 4-2 com canvia la sortida en haver-hi un canvi en qualsevol de les seves entrades. La senyal de rellotge no és transcendent en aquest exemple ja que es tracta d’un model purament combinacional.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

31

Figura 4-2. LUT

4.2 DFF (Flip Flop d’un context/comunicació)

Es troba al fitxer DFF.vhd. Com hem vist en el capítol destinat a la bipartició, els Flip Flops tipus D són utilitzats no solament per a implementar xarxes seqüencials sinó també com a recursos de comunicació entre contexts. Sigui quina sigui la seva funció, internament són el mateix model i tenen el mateix comportament. Als fitxers BLIF poden tenir dos noms .buff o .latch, però en VHDL sempre es diran DFF (Flip Flop de tipus D).

El funcionament és el d’un biestable tipus D. Aquesta entitat rep una ent rada i l’habilita a la sortida al següent flanc de rellotge després d’un cert retard. És un element síncron amb el rellotge del sistema, per tant entre les seves entrades hi figura la senyal de clock.

Podem veure el seu esquema en la figura 4-3.

Figura 4-3. DFF

4.2.1 Codi VHDL -- Al fitxer DFF.vhd LIBRARY ieee; USE ieee.std_logic_1164.all;

DFF

FF1

D Qentrada

clk

Sdelaydelay

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

32

USE ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; ENTITY DFF IS generic (delay : time :=0 ns

); PORT( clk : IN STD_LOGIC; entrada : IN STD_LOGIC; S : OUT STD_LOGIC:='0' ); END DFF; ARCHITECTURE funcional OF DFF IS BEGIN PROCESS (clk,entrada) BEGIN if (CLK'event) and (CLK = '1') then S<=entrada after delay; end if; END PROCESS; END funcional;

4.2.2 Exemple gràfic DFF

La figura 4-4 prové de la mateixa simulació anterior on hem explicat el model LUT. Per a mostrar el funcionament del DFF hem aplicat a la sortida de la LUT un Flip Flop tipus D ( implementat tal i com veiem al codi anterior). Podem observar la variable buffG17(sortida del DFF) com segueix a G17 però amb un cicle de rellotge de retard. És un biestable tipus D.

Aquest exemple s’ha extret de traduir la següent línia de codi BLIF a VHDL:

BLIF: .latch G17 *G17

VHDL: DFF_BuffG17 : DFF generic map (Delay) port map(clk,G17,BuffG17);

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

33

Figura 4-4. DFF

4.3 DLUT (LUT de dos contexts)

Es troba al fitxer DLUT.vhd. No és un element estàndard de les FPGA’s i s’ha dissenyat expressament per a fitxers particionats multiplexats per a simular les FPGA’s multicontext. De forma conceptual segueix el mateix funcionament que el LUT anteriorment explicat, l’única diferència que se’n deriva és que aquest disseny està pensat per a modelar LUTs de dos contexts (una cel· la LUT modela dues funcions diferents en funció del context on es troba). Es tracta d’un element combinacional que actualitza la seva sortida quan les seves entrades canvien. En aquest cas, necessitem saber en quin context ens trobem, per a poder implementar una LUT o una altra. Això s’indica a l’entit at mitjançant la senyal ctx que se li passa com a paràmetre al model juntament amb les entrades. A la llista de genèrics trobem amés del valor del delay, les dues LUTs ( table_0, table_1) una de cada context. Podem veure el seu esquema en la figura 4-5.

Figura 4-5. DLUT

Table 0

in_3

in_2

in_1

in_0

Sdelaydelay

Table 1

ctx

0

1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

34

4.3.1 Codi VHDL -- Al fitxer DLUT.vhd LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; ENTITY DLUT IS generic (Delay : Time := 0 ns; Table_0 : STD_LOGIC_VECTOR(0 TO 15):="UUUUUUUUUUUUUUUU"; Table_1 : STD_LOGIC_VECTOR(0 TO 15):="UUUUUUUUUUUUUUUU" ); PORT( ctx : IN STD_LOGIC; in_3, in_2, in_1, in_0 : IN STD_LOGIC:='0'; S : OUT STD_LOGIC ); END DLUT; ARCHITECTURE funcional OF DLUT IS BEGIN PROCESS (ctx,in_3,in_2,in_1,in_0) variable n : integer:=0; variable entrada : std_logic_vector(3 downto 0); BEGIN entrada(0):=in_0; entrada(1):=in_1; entrada(2):=in_2; entrada(3):=in_3; n:=CONV_INTEGER(entrada); IF (ctx='0') then S<=table_0(n) after delay; ELSE s<=table_1(n) after delay; END IF; END PROCESS; END funcional;

4.3.2 Exemple gràfic DLUT

Si observem atentament la gràfica de la figura 4-6 veurem el funcionament d’una LUT de dos contexts. És important parar molta atenció a la senyal de context. D’aques ta manera haurem de comprovar la sortida en funció de les entrades i el context per a veure que realment aquesta sortida és la corresponent al contingut de la LUT adequada.

Aquest exemple s’ha extret de crear una LUT de doble context a partir de les dues LUT’s descrites en els codis BLIF que trobem a continuació. Cada LUT correspon a un context diferent.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

35

BLIF(ctx 0): .names G3 G2 G1 G0 G15 0 – 1 - 1

- 0 - 0 1

BLIF(ctx 1): .names G3 G2 G1 G0 G17

0 0 1 - 1 0 0 – 1 1

La instanciació en VHDL a l’element DLUT ha estat la següent:

VHDL: DLUT_Sortida : DLUT generic map (Delay,LUT_G15,LUT_G17) port map(ctx,G3,G2,G1,G0,Sortida); on LUT_G15 i LUT_G17 són:

constant LUT_G15 : STD_LOGIC_VECTOR(0 TO 15):="1011001110100000"; constant LUT_G17 : STD_LOGIC_VECTOR(0 TO 15):="0111000000000000";

Com que en aquesta simulació les entrades fan de comptador de 0 a 14 en binari, i el context canvia cada cicle de rellotge (flanc de pujada) podem veure de forma gràfica que la sortida segueix de forma alternada i seqüencial el contingut de les LUTs tal i com es veu a continuació.

Aquesta és la base per a poder interpretar i entendre les gràfiques de simulació de fitxers particionats que veurem al final d’aquest informe.

1 3 5 7 9 11 13

constant LUT_G15 : " 1 0 1 1 0 0 1 1 1 0 1 0 0 0 0 0 ";

constant LUT_G17 : " 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 " ;

0 2 4 6 8 10 12 14

15 17 19 21 23 25 27 29

constant LUT_G15 : " 1 0 1 1 0 0 1 1 1 0 1 0 0 0 0 0 ";

constant LUT_G17 : " 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 " ;

16 18 20 22 24 26 28

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

36

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

Figura 4-6. DLUT

4.4 BDFF (Flip Flop de doble context)

Es troba al fitxer BDFF.vhd. Els BDFFs o Flip Flops de doble context, tenen la funció d’emmagatzemar un cert valor d’entrada d’un context i habilitar -lo a la sortida el pròxim cop que aquest context és disparat, per tant la senyal de context ctx serà necessària igual que a la DLUT anterior. Hem vist el model teòric al capítol anterior, tot seguit veurem la seva estructura interna.

Podem veure el seu esquema en la figura 4-7.

Figura 4-7. DBUFF

entrada

delaydelay

ctx

0

1

DFF 0

D Q

S

clk

DFF 1

D Q

0

1

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

37

4.4.1 Codi VHDL -- Al fitxer BDFF.vhd LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; ENTITY BDFF IS generic (delay : time :=0 ns ); PORT(clk : IN STD_LOGIC; ctx : IN STD_LOGIC; entrada : IN STD_LOGIC; S : OUT STD_LOGIC ); END BDFF; ARCHITECTURE funcional OF BDFF IS BEGIN PROCESS (clk,ctx) variable in_0, in_1 : std_logic:='U'; BEGIN IF (clk'event) and (clk='1') then IF (ctx='0') then in_0:=entrada; ELSE in_1:=entrada; END IF; END IF; if ctx='0' then s<=in_0 after delay; else s<=in_1 after delay; end if; END PROCESS; END funcional;

Quan hi ha un flanc de rellotge, l’entrada pren el valor que es passa per paràmetre i la sortida s’actualitza amb el valor que s’havia emmagatzemat a l’anterior mateix context. Observem que la senyal ctx és qui decideix on s’emmagatzema el valor i quin es co l· loca a la sortida. D’altra banda, com que estem simulant un element físic li hem afegit un retard com en els models anteriors.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

38

4.4.2 Exemple gràfic BDFF

A l’exemple de la figura 4-8 observem el comportament d’un Flip Flop de doble context, on la sortida del Flip Flop és en funció del context on es troba i l’entrada del mateix Flip Flop en el mateix micro-cicle de l’anterior Macro -cicle6.

A efectes visuals veiem que la sortida del FF està desplaçada dos cicles de rellotge, o lo que és el mateix, la sortida del FF en un context és l’entrada del mateix FF en l’anterior mateix context.

Aquest exemple s’ha extret de traduir la següent línia de codi BLIF a VHDL:

BLIF: .dbuff G2 buffG2 RE clk 0

VHDL: BDFF_G2 : BDFF generic map (Delay) port map(clk,ctx,G2,buffG2);

Recordem de l’apartat 2 -6 que el RE indica que treballa per flanc de pujada de rellotge. Tots els nostres models treballaran en aquest mode ja que el software de bipartició sempre genera els models d’aquesta forma. De la mateixa manera, el valor emmagatzema t predeterminat és sempre un ‘0’.

Figura 4-8. DBUFF

4.5 Recursos de rutatge de fitxers particionats.

Com veurem amb més profunditat en el proper capítol, les entrades i sortides dels fitxers particionats estan físicament multiplexades en els dispositius programables multi-context, és per aquest motiu que el programa traductor BLIF-VHDL també ha tingut en compte aquesta propietat i ha multiplexat senyals de tots dos contextes per tal d’apropar -nos al més possible a la realitat. Aquesta multiplexació de senyals és de dues formes, una d’entrada on dues senyals diferents es multiplexen en una de nova i aquesta última pren un valor o un altre en funció del context; o el procés invers quan una senyal multiplexada ha de ser demultiplexada per tal de poder-se utilitzar les dues senyals de forma separada.

6 “Temporal Bipartitioning Techniqu es For Multi-Context FPGAs”, Dr. Enric Cantó Navarro. Juliol 2001,

Barcelona, UPC

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

39

Observem l’esquema a continuació.

a 0 0 d

b 1 a_b d_f 1 f

ctx ctx

RUT_IN RUT_OUT

Figura 4-9. Recursos de rutatge

4.5.1 RUT_IN (Recursos de rutatge d’entrada)

Es troba al fitxer RUT_IN.vhd. En el cas del RUT_IN, l’entitat accepta tres paràmetres que són l’entrada del context 0, l’entra da del context 1 i la senyal que multiplexarà les altres dos. D’aquesta manera i seguint l’exemple de la figura 4-10 la senyal a_b prendrà el valor a en el primer context i el valor b en el segon. Al igual que en els models anteriors, en aquest se li ha afegit un retard.

in_ctx_0 0

in_ctx_1 1 output

RUT_IN

ctx

Figura 4-10. Model del rutatge d’entrada

4.5.1.1 Codi VHDL

--Al fitxer Rut_In.vhd LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; ENTITY RUT_IN IS generic (delay : time :=0 ns ); PORT( ctx : IN STD_LOGIC; in_ctx_0, in_ctx_1 : IN STD_LOGIC; output : OUT STD_LOGIC );

VHDL

VHDL

delaydelay

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

40

END RUT_IN; ARCHITECTURE funcional OF RUT_IN IS BEGIN PROCESS (ctx,in_ctx_0,in_ctx_1) BEGIN if (ctx='0') then output<=in_ctx_0 after delay; else output<=in_ctx_1 after delay; end if; END PROCESS; END funcional;

4.5.1.2 Exemple gràfic RUT_IN

Recordem del capítol anterior que una de les característiques de les FPGAs multi-context és que les entrades i sortides de tots dos contexts estan multiplexades, i això ha d’ésser aplicat al nostre fitxer VHDL traduït. A la figura 4-11 veiem un exemple de rutatge d’entrada on dues senyals de dos contexts diferents G7 i G9 passen a formar-ne una de sola anomenada G7_G9 que tindrà el valor d’una o l’altra en funció del context on ens trobem. La primera senyal correspon al primer context i la segona al segon.

La instanciació a l’element descrit mitjançant el codi anterior és la següent en llenguatge VHDL:

RUT_IN_G7_G9 : RUT_IN generic map (Delay_In)

port map (ctx,G7,G9,G7_G9);

Veiem com la senyal G7_G9 té un valor que es correspon amb el context al que es troba i al seu senyal origen corresponent.

Figura 4-11. Rutatge d’entrada (2)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

41

4.5.2 RUT_OUT (Recursos de rutatge de sortida)

Es troba al fitxer RUT_OUT.vhd. Aquest és el model recíproc de l’anterior. En aquest cas també se li passen tres paràmetres que són (seguint el mateix exemple) els dos senyals d i f i el senyal multiplexat. D’aquesta manera, el valor del senyal multiplexat d_f s’aplicarà al senyal d o al f en funció del context on ens trobem. Un retard és també aplicat.

0 out_ctx_0

input

1 out_ctx_1

ctx

RUT_OUT

Figura 4-12. Model del rutatge de sortida

4.5.2.1 Codi VHDL

--Al fitxer Rut_Out.vhd LIBRARY ieee; USE ieee.std_logic_1164.all; USE ieee.std_logic_arith.all; USE ieee.std_logic_unsigned.all; ENTITY RUT_OUT IS generic (delay : time :=0 ns ); PORT( ctx : IN STD_LOGIC; out_ctx_0, out_ctx_1 : out STD_LOGIC; input : in STD_LOGIC); END RUT_OUT; ARCHITECTURE funcional OF RUT_OUT IS BEGIN PROCESS (ctx,input) BEGIN if (ctx='0') then out_ctx_0<=input after delay;

out_ctx_1<='U' after delay; else out_ctx_1<=input after delay; out_ctx_0<='U' after delay; end if; END PROCESS; END funcional;

VHDL delaydelay

delaydelay

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

42

4.5.2.2 Exemple gràfic RUT_OUT

Aquest és el model recíproc de l’anterior. En aquest cas i com podem veure a la figura 4-13 el valor del senyal m3023_G17 serà aplicat al senyal m3023 o al G17 en funció del context on ens trobem. Com abans, el primer nom correspon al primer context.

El codi VHDL simulat en l’exemple és el següent:

RUT_OUT_m3023_G17 : RUT_OUT generic map (Delay_Out) port map (ctx,m3023,G17,m3023_G17);

Figura 4-13. Rutatge de sortida

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

43

5 Software de Traducció BLIF- VHDL

El llenguatge de programació utilitzat per a la realització d’aquest software Traductor ha estat el C++. Els motius que ens van fer decidir per aquest llenguatge van ser per una banda la quantitat de llibreries VCL de que disposa el compilador escollit C++ Builder a l’hora de treballar en memòria amb llistes d’elements, i per l’altra el fet de que el programa de bipartició temporal de que hem parlat al llarg de l’informe i que serveix de precedent a aquest projecte també ha estat fet en C++. D’ aquesta manera es poden utilitzar tots dos programes en un mateix entorn amb les múltiples aplicacions que d’aquí se’n deriven.

Cal fer esment de que aquest projecte de fet consisteix en dos traductors BLIF-VHDL diferents, un per a fitxers originals BLIF que converteix a VHDL per a circuits no reconfigurables dinàmicament, i un altre de traducció de fitxers particionats per a circuits reconfigurables dinàmicament on s’hauran de tenir en compte molts més factors que veurem en el punt 5.1. Aquest software ha estat dissenyat per a traduir fitxers biparticionats amb l’opció d’ entrades i sortides bufferades que és la que més reflexa el model real.

Aquest capítol està dividit en tres blocs, en primer lloc veurem totes les especificacions dels dos llenguatges BLIF i VHDL que s’han hagut de tenir en compte a l’hora de fer la traducció, seguidament explicarem el flux del programa i ja per acabar enumerarem els fitxers C++ que componen el projecte i farem una explicació de les funcions de cadascun d’ells posant èmfasi en els punts més importants per tal d’entendre el seu funcionament.

5.1 Especificacions del BLIF i del VHDL que cal tenir en compte.

En aquest apartat veurem els problemes més significatius amb que ens hem trobat i quina ha estat l’acció que s’ha dut a terme per tal de solucionar-los.

5.1.1 Noms dels Senyals

5.1.1.1 Situació

El BLIF accepta qualsevol caràcter a l’hora d’escriure el nom d’una variable o senyal. No és el cas del VHDL, on hi ha una sèrie de normes a seguir: els noms dels senyals i/o variables en VHDL han de començar sempre per una lletra ‘a’ -‘z’, ‘A’ -‘Z’ . Sabent que aquest llenguatge no distingeix entre majúscules i minúscules, això redueix molt les possibilitats a l’hora de crear noms de senyals a partir d’un codi BLIF.

Pel que fa als caràcters que segueixen la primera lletra del nom, podem utilitzar els caràcters ‘A’ -‘Z’,’a’ -‘z’,’0’ -‘9’ i ‘_’ amb l’única excepció del darrer caràcter que pot ser qualsevol dels anteriors menys el ‘_’ barra baixa.

5.1.1.2 Procediment

La solució adoptada ha estat la de deixar els noms del codi BLIF que ja són correctes en VHDL tal i com estan, tenint en compte que no existeixin ja abans com a resultat d’una modificació d’un altre senyal anterior. Els senyals que presenten incompatibilitats amb el llenguatge VHDL s’han corregit com es mostr a a continuació en els següents casos:

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

44

• Primer caràcter: Si el nom del senyal en BLIF comença per un número, es canvia aquest caràcter per una lletra seguint la llei: 0 = A, 1 = B, i així fins 9 = J. Els caràcters ascii que van del 33 ‘!’ fins al 47’/’ es canvien per les lletres L fins Z respectivament. Si trobem qualsevol altre caràcter que no sigui els anteriors el substituirem per una ‘K’ que és l’únic caràcter no utilitzat anteriorment.

Hi ha un cas especial, que és quan el primer caràcter és un ‘*’, es tracta d’un senyal de sortida d’un FF (senyal bufferat). En aquest cas la senyal començarà per “ Buff” seguida de la resta del nom.

• Següents caràcters: Aquests caràcters poden ser lletres, números o el caràcter ‘_’ . Si no compleixen cap d’aquestes condicion s tornem a assignar un caràcter a un número o lletra de la mateixa forma que hem fet abans. En aquest cas, com que tornem a tenir més caràcters no permesos que lletres i números, la resta estarà substituïda per ‘_’.

• Últim caràcter: Si l’últim caràcter és ‘_’ o és substituït per ‘_’ l’eliminem.

Tots els noms són revisats per a assegurar-nos de que no en repetim cap, ja sigui perquè apareixen més d’un cop en el codi BLIF o perquè el canvi proposat d’un cert senyal ja existeix. Si ja existeix, li afegim un caràcter ‘a’ al final fins que no coincideixi. S’ha intentat optimitzar al màxim aquesta funció i amb aquesta solució ens assegurem que mai dues senyals diferents tindran el mateix nom.

Podem veure un exemple en la figura 5-1, on es mostren alguns dels casos descrits anteriorment.

Figura 5-1. Canvis de nom

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

45

5.1.2 Senyals Primaris

5.1.2.1 Situació

En l’entitat del fitxer BLIF sense particionar apareixen els senyals primaris tant d’entrada com de sortida. En les declaracions d’entitat dels dos fitxers par ticionats hi tenim entrades i sortides primàries i no primàries.

5.1.2.2 Procediment

Per tal de poder distingir entre senyals primaris i no primaris, en un primer moment es va fer una funció que mirava els senyals d’entrada d’un context que no pertanyien a la sortida de l’altre i el mateix comparant la sortida d’un context amb l’entrada del següent per tal de saber quins d’aquest senyals eren de comunicació i no primaris. Finalment, com que el Software també llegeix el fitxer BLIF original sense particionar, s’ha d ecidit agafar l’entitat d’aquest com a referència.

5.1.3 Senyals No Primaris

5.1.3.1 Situació

Al BLIF els senyals no primaris no estan definits, es defineixen un cop aquest són utilitzats durant el codi i no han estat definits anteriorment en el cos de l’entitat. En e l cas del VHDL aquests senyals s’han de definir abans de la seva utilització.

5.1.3.2 Procediment

Per tal de reconèixer aquests senyals durant la lectura dels fitxers BLIF, hem destinat una zona de memòria per a posar-hi els nous senyals que van sortint, tot comparant el nou senyal amb els que ja existeixen a la llista. D’aquesta manera no repetim declaració de senyals no primaris.

5.1.4 Senyals Multiplexats

5.1.4.1 Situació

Com ja hem explicat en els capítols previs d’aquest informe, per tal d’apropar -nos al màxim al comportament real de les FPGAs multi-context, els senyals de diferents contexts estaran multiplexats. Aquesta multiplexació de senyals es farà de la manera descrita a continuació:

5.1.4.2 Procediment

Cada senyal pertany a un recurs en particular LUT, DLUT, BUFF, DBUFF...; com que aquests elements aniran multiplexats (recordem la teoria de bipartició del capítol 3) els seus senyals també aniran multiplexats. És important dir que l’aparellament d’elements de contexts diferents anirà en funció de l’ordre en que apareixen. Aix í, el primer FF del context 0 anirà aparellat amb el primer FF del context 1, i el mateix per als altres elements.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

46

• LUTs: Les entrades de les LUTs aniran multiplexades i les sortides també. En el cas de que una entrada d’una LUT estigui aparellada amb una entrada d’una altra LUT que no està assignada, se la multiplexarà amb la senyal nil que sempre té el valor zero, veure figura 5-2. El mateix passarà si no hi ha una LUT a l’altre context amb que poder -se multiplexar, les entrades s’aparellaran amb nil i la sortida amb not_used que sempre tindrà el valor ‘U’ en VHDL, veure figura 5-3.

En el següent exemple veiem com es creen els senyals multiplexats a partir de dos senyals normals com és el cas del senyal G6_G5 compost per G6 i G5.

Context 0: Context 1:

.names G0 G1 G6 G7 G15

.names *G0 G5 G9 [3018]

Sentencia VHDL: DLUT_G15_m3018 : DLUT generic map (Delay_Lut,LUT_G15,LUT_m3018)

port map(ctx,G0_nil,G1_BuffG0,G6_G5,G7_G9,G15_m3018);

Figura 5-2. Multiplexació en LUTs (1)

LUT_G15

G0

G1G6

G7

G15

LUT_m3018

*G0G5

G9

[3018]

nil

LUT

G0_nil

G1_buffG0G6_G5G7_G9

G15_m3018

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

47

Context 0: Context 1:

No hi ha cap LUT

.names G5 G9 [3021]

Sentencia VHDL:

DLUT_notused_m3021: DLUT generic map(Delay_Lut,LUT_notused,LUT_m3021) port map(ctx,nil_nil,nil_nil,nil_G5,nil_G9,notused_m3021);

Figura 5-3. Multiplexació en LUTs (2)

• BUFFs: El cas dels FF ‘normals’ és especial ja que a l’hora de multiplexar els senyals hem de fer-ho de manera que per a una cel· la FF determinada (dos FFs de diferents contexts multiplexats) les entrades dels FFs s’aparellen com en l’exemple anterior, però les sortides s’aparellen canviant l’ordre. És a dir, l’entrada d’un FF en el context 0 serà la sortida d’aquest FF al context 1 del mateix Macro-cicle i l’entrada d’un FF en el context 1 serà la sortida d’aquest FF al context 0 del següent Macro-cicle. A la figura 5-4 mostrem un exemple d’una traducció de dos sentències BLIF multiplexades on apareixen FFs.

LUT

nil

nilnil

nil

notused

LUT_m3021

nil

nilG5

G9

[3021]

nil_nil

nil_nilnil_G5nil_G9

notused_m3021

LUT

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

48

Context 0: Context 1:

.buff G15 *G15 RE clk 0

.latch *[3023] G7 re clk 0

Sentencia VHDL:

DFF_G7_BuffG15 : DFF generic map (Delay_Buff) port map(clk,G15_BuffW3023,G7_BuffG15);

Figura 5-4. Multiplexació en DFFs

Observem a part del fet de l’ordre de l’associació de senyals que ja hem comentat, que els senyals BLIF no compilables en VHDL s’han can viat tal i com hem explicat en l’apartat 5.1.1

• DBUFFs: El cas dels FF ‘de doble context’ és anàleg al que acabem d’explicar amb la particularitat de que en aquest cas les sortides es multiplexen en el mateix ordre que en les entrades, això és així perquè la l’entrada d’un DBUFF en el context 0 serà la sortida d’aquest FF al mateix context 0 del següent Macro-cicle i exactament el mateix per al context 1. A la figura 5-5 mostrem un exemple d’una traducció de dos sentències BLIF multiplexades on apareixen BDFFs.

DFF

FF0

D QG15

clk

*G15DFF

FF1

D Q*[3023]

clk

G7

DFF

FF

D QG15_BuffW3023

clk

G7_BuffG15

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

49

Context 0: Context 1:

.dbuff G17 *G17 RE clk 0

.dbuff G8 *G8 re clk 0

Sentencia VHDL:

BDFF_BuffG17_BuffG8 : BDFF generic map (Delay_Buff) port map(clk,G17_G8,BuffG17_BuffG8);

Figura 5-5. Multiplexació en BDFFs

5.1.5 Llistes de senyals de més d’una línia

5.1.5.1 Situació

Els fitxers BLIF tenen la propietat de poder posar les entrades i sortides en més d’una línia mitjançant el caràcter ‘\’.

5.1.5.2 Procediment

Nosaltres ho hem tingut en compte a l’hora de llegir el fitxer BLIF i també hem escrit els fitxers VHDL de manera que hi hagi un numero màxim d’elements per línia per poder llegir i interpretar millor el codi. Hem escollit 8 elements per línia.

*G17BDFF

FF0

D QG17

clk

*G8BDFF

FF1

D QG8

clk

BuffG17_BuffG8BDFFD QG17_G8

clk

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

50

5.1.6 Senyals OUT en VHDL

5.1.6.1 Situació

Els models BLIF amb que treballem són de simulació, és per aquest motiu que els senyals definits com a sortides primàries, en alguns casos es poden llegir i actuar com a entrades no primàries. Això en el cas del VHDL no és exactament així, ja que si són sortides primàries es defineixen com a OUT però no poden ser llegides.

5.1.6.2 Procediment

Hem decidit deixar els senyals de sortida del BLIF com a senyals normals al fitxer VHDL i crear uns nous senyals de tipus OUT en VHDL anomenats OUT_sortida on sortida és el nom del senyal de sortida del BLIF. Al final del codi VHDL assignem els senyals originals de sortida BLIF als nous creats per nosaltres que són de tipus OUT. A continuació veiem un exemple :

CODI BLIF .model adder .inputs a b .outputs add Cout .clock clk

CODI VHDL

entity adder is port( clk,a,b : in STD_LOGIC; OUT_add,OUT_Cout: out

STD_LOGIC); end adder;

--codi VHDL

signal add,Cout : STD_LOGIC :='U';

--codi VHDL

OUT_add<=add; OUT_Cout<=Cout;

Figura 5-6. Exemple senyals sortida

5.1.7 Rutatges

5.1.7.1 Situació

En el cas del rutatge, no tots els senyals s’enrut en de la mateixa manera, uns són d’entrada i d’altres són de sortida. Els senyals multiplexats d’entrada s’han d’enrutar de manera que dues senyals es fusionin en una, els senyals multiplexats de sortida s’han d’enrutar de manera que aquest senyal fa de dr iver per a dos senyals diferents depenent del context.

5.1.7.2 Procediment

Com que els senyals es van associant de manera que una entrada es multiplexa amb una altra entrada de la mateixa cel· la del següent context, i la sortida s’associa amb una

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

51

sortida també de l’altre context, hem distingit entre senyals multiplexats d’entrada i de sortida per a poder aplicar-los-hi un rutatge o un altre.

Pot passar que un mateix senyal multiplexat sigui a l’hora un senyal d’entrada i de sortida. En aquest cas només se li aplicarà el rutatge de sortida per dos motius:

1. Si l’hi apliquéssim tots dos rutatges entraríem en un bucle infinit i els senyals involucrats no tindrien cap valor definit ja s’estarien actualitzant ininterrumpudament. El RUT_IN s’executa al modificar -se qualsevol de les entrades generant una sortida, aquesta sortida és a l’hora entrada del RUT_OUT que generaria al seu temps dos sortides que serien entrades del RUT_IN anterior que es tornaria a executar, i així indefinidament. En la figura 5.7 veiem un exemple conceptual de la situació.

a 0 0 a

b 1 a_b a_b 1 b

ctx ctx

RUT_IN RUT_OUT

Figura 5-7. Recursos de rutatge (1)

2. Ens interessa poder demultiplexar el senyal per poder obtenir els dos valors dels senyals als que correspon. Aquest senyal a_b ja obté un valor pel fet de ser una sortida d’un bloc del circuit, per aquest motiu pot treballar al llarg del circuit sense que li tinguem que aplicar cap rutatge d’entrada.

És per aquests dos motius que el software Traductor identificarà tant els senyals que funcionin d’entrada com de sortida per tal d’aplicar -los hi, en cas de ser entrada i sortida al mateix temps, únicament el rutatge de sortida RUT_OUT. La figura 5-8 mostra de manera conceptual com treballa un senyal multiplexat a_b que és utilitzat durant el codi VHDL i que és demultiplexat per a poder donar lloc als dos senyals que el componen, és el cas que acabem de veure.

VHDL

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

52

0

1VHDL

a_b a

b

CTX

Figura 5-8. Recursos de rutatge (2)

5.1.8 Contingut de les LUTs

5.1.8.1 Situació

Els dos llenguatges BLIF i VHDL tenen formes diferents de fer la descripció d’una LUT i això dificulta el procés de traducció. Ja hem vist en el capítol 2 d’aquest informe com es descriu una LUT en BLIF, en VHDL el que es fa és crear un vector de tipus STD_LOGIC_VECTOR de tants elements com dimensió té la LUT com es pot observar a continuació:

constant LUT_G15 : STD_LOGIC_VECTOR(0 TO 15):="1011001110100000";

Per tant el problema més important a resoldre és el de desxifrar el codi BLIF i passar-ho a VHDL segons el model descrit.

5.1.8.2 Procediment

Recordem que el codi BLIF tal i com hem vist en l’apartat 2 -5 d’aquest i nforme utilitza el caràcter ‘-‘ quan descriu números binaris per a indicar que una entrada no és tinguda en compte “don’t care”. Per tant quan trobem un .names al codi BLIF sabrem que fins que canviï l’element les següents línies s’agafen com números en bi nari que poden contenir tant ‘1’s i ‘0’s com el caràcter ‘-‘. Es comprova aquest fet i si és un número binari pur (sense ‘_’) se’l converteix en decimal per a saber l’índex de la taula que contindrà un ‘1’. En cas que efectivament el número codificat en B LIF contingui el caràcter ‘-‘ el software li aplicarà un algoritme per a que aquest número es converteixi en tots els números binaris necessaris que continguin només ‘1’ i ‘0’ i que tots sumats representin el mateix que en el model BLIF. Un cop tenim tots els possibles valors binaris, els utilitzem com a índexs de la taula LUT per a emmagatzemar-hi en aquella posició un ‘1’ lògic.

5.2 Entorn del programa Traductor.

Com hem explicat anteriorment, aquest software es compon de dos traductors diferents. El primer agafa un fitxer d’extensió *.bli escrit en codi BLIF normal i el segon llegeix dos fitxers d’extensió *.bli corresponents a la partició de l’anterior fitxer normal.

Com que aquest projecte es basa en el software de bipartició temporal de que també hem parlat al llarg d’aquest informe, hem decidit que la seva execució serà dintre del mateix directori on es troba el software de bipartició. D’aquesta manera podem utilitzar la nomenclatura d’aquest software per a adaptar -la al nostre programa i no ens preocuparem de cercar directoris on trobar els fitxers, aquesta nomenclatura consisteix en el següent: el fitxer BLIF original és del tipus nom.bli i els seus corresponents particionats són nom_0.bli i nom_1.bli. Sabent això podem passar-li un únic paràmetre al nostre software i d’aquí extreure’n els altres. Quan executarem el nostre programa aquests tres fitxers ja existiran.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

53

El programa per una part agafa el nom.bli i el tradueix a VHDL generant un fitxer nom.vhd. Per l’altra, agafa els dos fitxers nom_0.bli i nom_1.bli, els multiplexa i els tradueix generant un fitxer nom_2ctx.vhd. Per a la traducció dels dos fitxers particionats també s’agafen les llistes d’entrades i sortides primàries del fitxer nom.bli, pels motius que hem explicat en l’ apartat 3.3 d’aquest inf orme. El programa té un registre d’errors, notificacions i possibles canvis de nom dels senyals que es poden veure en els diferents memos. Al final del programa el contingut d’aquests memos és bolcat en dos fitxers anomenats nom.inf i nom_2ctx.inf

La interfície escollida per al programa és la següent: s’ha decidit fer un únic entorn per als dos traductors separant els resultats de les traduccions en pantalla mitjançant dues pantalles solapades com es mostra en les figures 5-9 i 5-10.

5.2.1 Pas de paràmetres

Com hem dit el programa accepta un únic paràmetre nom.bli.

Suposant que tinguem el programa al directori arrel, si estem treballant en mode MS-DOS hem d’escriure:

“C\:Traductor_2ctx.exe nom.bli”

Si executem el programa en Microsoft Windows sense passar-li cap paràmetre aleshores per tal d’indicar -li al software quin és el fitxer a traduir hem de prémer sobre la pestanya Fitxers 1ctx com es mostra en la figura 5.9. i introduir on posa “Nom del fitxer BLIF” el nom del fitxer.

Figura 5-9. Entorn Fitxers

Un cop introduït, prémer sobre el botó “Executar Traductor” i tot seguit podrem veure en el memo de la dreta la informació referent a la traducció del fitxer original, veure

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

54

figura 5-10 . Si un cop el traductor ha estat executat premem sobre la pestanya Fitxers 2ctx podrem veure en el corresponent memo la informació pertinent a la traducció dels fitxers particionats, veure figura 5-11.

Figura 5-10. Entorn Fitxers 1ctx

Figura 5-11. Entorn Fitxers 2ctx

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

55

5.3 Programa Traductor en llenguatge C++

El programa està estructurat en diversos blocs com es mostra en la Figura 5-12. Cadascun d’aquests blocs correspon amb una classe diferent que té el mateix nom que el fitxer on es troba. El fitxer de major jerarquia és el “ Tabinterface.cpp” que comprova el pas de paràmetres al programa i conté l’entorn gràfic associat. Aquest fitxer crida a funcions del “Traductor.cpp” que a l’hora va cridant els altres fitxers restants en funció de la lectura dels fitxers BLIF. Un cop el “Traductor.cpp” ha acabat la feina, torna el control a “Tabinterface.cpp” que donarà l’ordre d’imprimir els fitxers nom.vhd i nom_2ctx.vhd i acabarà l’execució del programa.

L’algoritme de lectura i anàlisi del programa s’executa intern ament tres cops, un per a cada fitxer que llegeix. La primera passada correspon a la lectura i traducció del fitxer nom.bli i les altres dos són relatives als fitxers nom_0.bli i nom_1.bli.

5.3.1 Aspectes generals del programa

Per tal de poder treballar d’una fo rma més dinàmica i ràpida, treballarem amb tot el contingut dels fitxers a memòria. Un cop en memòria llegirem línia per línia identificant sempre la primera paraula de la línia per saber de quin element es tracta i actuar en funció de l’element, recordem la nomenclatura BLIF explicada en el capítol 2 d’aquest informe. A partir d’ara parlarem sempre de codi BLIF i els elements que ens anirem trobant al llarg de la seva lectura.

Com hem dit, el programa llegeix tres fitxers i en tradueix el seu contingut BLIF passant-lo a VHDL. La primera lectura correspon al fitxer BLIF original, i al final d’aquesta quan identifiquem la paraula reservada .end imprimim el codi VHDL resultant fent una crida a les funcions de la classe TPrinter_1ctx [Printer_1ctx.cpp]. L’an àlisi del fitxer BLIF es fa seguint el model del punt 5.3.2 que veurem a continuació. En aquest moment, ja tenim un fitxer traduït i tancat, el nom.vhd. Al mateix temps guardarem la informació de l’entitat d’aquest fitxer VHDL per a utilitzar -la posteriorment en la traducció dels fitxers particionats com s’ha explicat anteriorment al llarg de l’informe. En aquest punt del programa inicia la lectura dels dos fitxers particionats seguint el mateix model de la lectura anterior i que descriurem a continuació. Al final de la lectura d’aquests dos fitxers, farem una crida a les funcions de la classe TPrinter [Printer.cpp] que s’encarregaran de:

• Multiplexar tots dos fitxers

• Crear elements DLUTs i DBUFFs apart dels DFFs existents

• Crear els elements de rutatge RUT_IN i RUT_OUT necessaris per als senyals multiplexats que en resulten dels procediments anteriors.

• i finalment imprimir el fitxer VHDL de dos contexts.

Tot això té lloc a les funcions del Printer.cpp

5.3.2 Anàlisi del BLIF en memòria.

El procediment descrit a continuació és el que se segueix per a analitzar el contingut dels fitxers BLIF un cop aquests han estat passats a memòria, això té lloc per a cada fitxer per separat. Sabem que el pas previ a l’anàlisi és el de llegir el fitxer en qüestió i passar el seu contingut en un array d’AnsiStrings per a cada línia de codi BLIF; un cop tenim això

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

56

fet anirem analitzant aquests arrays d’AnsiStrings un darrera l’altre seguint l’ordre en que apareixen al fitxer original BLIF.

D’aquesta manera, quan trobarem .model ens crearem un objecte Entity de la classe TEntity [Entity.cpp] i hi guardarem el nom del fitxer. Aquest objecte es crea un únic cop per fitxer i es va emplenant a mesura que van apareixent nous elements que hi pertanyen; és el cas de .inputs, .outputs i .clock, tots tres models pertanyen al mateix objecte Entity és per aquest motiu que quan ens els trobem no crearem cap objecte nou, sinó que emplenarem els camps de l’ Entity corresponents. Els camps d’aquest objecte són : Inputs, Outputs, Model i Clock.

Quan trobarem .names crearem un objecte de la classe TLut [Lut.cpp] que conté els camps nom, EntSor, array. El nom de l’objecte Lut serà l’últim element de la línia on trobem .names, la resta de noms i el mateix nom en últim lloc s’afegiran a EntSor i formaran les entrades i sortida de la LUT. Array és el contingut de la LUT que anirem emplenant a mesura que anirem llegint les línies següents a .names.

Per tal de saber que els números en binari que trobem al llarg del codi BLIF pertanyen a una LUT o a una altra tenim una variable índex que ens ho indicarà. Aquesta variable és LutIndex[] i la controlem cada cop que creem un nou objecte de tipus TLut. D’aquesta manera quan trobem un número binari que correspon al contingut d’una LUT cridem a l’objecte Lut que indica aquest índex.

Si trobem .latch o .buff crearem un objecte del tipus TBuff i els dos noms que segueixen aquesta paraula clau seran l’input i l’output del model. Aquests són els dos camps de que consta la classe TBuff.

Una cosa similar passa quan en el codi BLIF trobem .dbuff. En aquest cas es tracta d’un element no estàndard d’aquest llenguatge que ha estat adaptat per a la simulació de circuits particionats. La classe associada a aquests objectes és TDbuff i conté els mateixos camps que l’anterior emplenats d e la mateixa forma.

Quan llegim .end sabem que la lectura del fitxer BLIF ha acabat i no continuarem llegint. En aquest moment tornem el control al Tabinterface.cpp que comprovarà la iteració de lectura de fitxers en curs per saber si s’ha de fer una crida a les funcions de Traductor _1ctx.cpp, Traductor.cpp o si s’ha de fer una altra lectura abans.

Un cop tots dos fitxers VHDL han estat escrits, passarem tot el contingut dels memos, on tenim totes les informacions del procés de traducció, en dos fitxers. El primer memo corresponent a la traducció del fitxer original d’un context l’escriurem en un fitxer de tipus nom.inf; el segon memo relatiu a la traducció dels fitxers particionats l’escriurem en un fitxer de tipus nom_2ctx.inf. En aquest punt, el programa restarà a l’espera per si volem fer una altra traducció o volem finalitzar-lo totalment. En cas de voler fer una nova traducció haurem d’introduir el nou nom del fitxer BLIF a traduir en la casella “NOM DEL FITXER BLIF” de la solapa “Fitxers 1ctx” i préme r el botó Executar Traductor com hem fet anteriorment, si el que volem és finalitzar l’execució del programa farem un click a sobre de la X situada a la cantonada superior dreta de la pantalla del traductor. El programa està dissenyat per a poder fer vàries traduccions de diferents fitxers sense haver de tornar a executar-lo cada cop. Cada cop que modifiquem el paràmetre d’entrada i executem el software, els memos s’esborren per a mostrar la nova informació i es creen els nous fitxers nom.inf i nom_2ctx.inf.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

57

Figura 5-12. Flux del software Traductor

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

58

5.4 Fitxers que componen el projecte.

En aquest capítol veurem quins són i com es comporten els diferents fitxers *.cpp de que consta el projecte Traductor_2ctx.bpr emfatitzant sobre les rutines de més rellevància per tal de comprendre el com i el perquè d’aquestes rutines.

5.4.1 Tabinterface.cpp

És el fitxer de major jerarquia i que s’encarrega d’analitzar si el programa rep paràmetre d’entrada o no, de generar els altres fitxers a partir d’aquest i d’executar el Traductor.

Aquest fitxer es compost de 5 funcions:

5.4.1.1 TPagesDlg::TPagesDlg(TComponent* AOwner)

És el constructor de la Classe i després d’inicialitzar la variable que controla el nombre d'iteracions d'execució de la lectura de fitxers BLIF, comprova que se li hagi passat un paràmetre al programa. Si és així, aquesta mateixa funció utilitza el paràmetre i comença l’execució del programa.

5.4.1.2 TPagesDlg::~TPagesDlg(void)

És el destructor de la classe, i no fa res perquè el cos del programa s’encarr ega d’alliberar la memòria utilitzada. Aquesta és la funció habitual d’un destructor.

5.4.1.3 TPagesDlg::Button1Click(TObject *Sender)

Aquesta funció s’executa cada cop que premem el botó Executar Traductor de la interfície gràfica del programa. Fa la crida a les dues funcions encarregades de generar els altres fitxers i executar el traductor.

5.4.1.4 TPagesDlg::ArrangeParam(void)

Partint del nom del fitxer BLIF original, anomenem els altres fitxers amb que treballarem. La variable Edit4->Text és un AnsiString que conté el nom del fitxer original BLIF, ja sigui perquè l’usuari l’ha introduït per teclat o pel pas de paràmetres. La funció analitza aquesta variable i n’identifica el nom i l’extensió, generant a partir d’aquesta informació els noms dels dos fitxers particionats a llegir i els noms dels fitxers VHDL finals. Recordem que la nomenclatura per a saber el nom dels fitxers particionats és la mateixa que la utilitzada en el software de Partició Temporal del Dr. Enric Cantó.

5.4.1.5 TPagesDlg::ExeSoftware(void)

El primer que fem és crear-nos un objecte de la classe Traductor que ens permetrà accedir a les seves funcions. Carreguem els noms dels fitxers amb que treballarem en unes

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

59

variables per poder-hi treballar amb més comoditat, fitxer[n] són els noms dels BLIFs i sortida[n] els dels fitxers VHDL. Com que podem traduir diversos fitxers originals BLIF durant la mateixa execució del programa, per a que les informacions dels memos no es confonguin, cada cop que executem el traductor netegem els memos.

Farem tres lectures i anàlisi dels fitxers, un per a cada fitxer BLIF d’entrada. Al finalitzar la primera passada imprimirem el fitxer nom.vhd i al finalitzar l’última imprimirem el fitxer nom_2ctx.vhd. En acabar passem tot el contingut dels memos a fitxers de noms iguals que les sortides però amb extensió *.inf.

5.4.2 Traductor.cpp

Les funcions d’aquest fitxer són les encarregades d’analitzar i gestionar el contingut dels fitxers BLIF.

5.4.2.1 TTraductor::TTraductor()

És el constructor de la classe i s’encarrega d’inicialitzar tots els índexs i zones de memòria que utilitzarem durant l’execució del programa. S’executa per a cadascuna de les diferents traduccions, si n’hi hagués.

5.4.2.2 TTraductor::~TTraductor()

És el destructor i s’encarrega d’alliberar tota la memòria utilitzada durant el programa, un cop aquest ha acabat una traducció.

5.4.2.3 void TTraductor::OpenFile(char *fitxer)

Obre un fitxer, el nom del qual rep per paràmetre. En el nostre cas sempre serà un fitxer BLIF.

5.4.2.4 void TTraductor::CloseFile(void)

Tanca un fitxer. És l’equivalent a l’anterior funció per tancar fitxers.

5.4.2.5 void TTraductor::LeerFichero()

Un cop tenim el fitxer BLIF obert, llegim línia a línia i guardem tot el seu contingut en un AnsiString. Aquest AnsiString l’afegim després a una llista que analitzarem posteriorment.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

60

5.4.2.6 void TTraductor::Parse(void)

Un cop tenim el contingut del fitxer BLIF passat a llista d’ AnsiStrings (un per a cada línia) el que farem és agafar cadascuna de les línies i passar-les en forma de cadenes de caràcters en una altra funció.

5.4.2.7 void TTraductor::Parse(char *linea)

Aquesta és la funció que agafa aquestes cadenes de caràcters corresponents a cadascuna de les línies del fitxer BLIF i separa les diferents paraules introduint-les en un array d’AnsiStrings que utilitzarem posteriorment per a identificar paraules clau.

5.4.2.8 AnsiString TTraductor::CogePalabra(char **p_linea)

Per tal de separar la cadena de caràcters que compon cadascuna de les línies el que hem fet és recórrer aquesta cadena fins trobar un espai en blanc, al trobar-lo hi hem posat un ‘\0’ per a indicar qu e la cadena acaba allí i la retornem. Al mateix temps la variable que apuntava al començament de la cadena original la fem apuntar al caràcter que segueix a aquest ‘\0’ que hem introduït i repetim el procés fins que aquesta variable apunti a NULL indicant final de línia.

5.4.2.9 void TTraductor::Parse(AnsiString palabra[])

Un cop tenim les paraules d’una línia de codi BLIF passades a AnsiStrings i aquests ordenats per ordre d’aparició, podem identificar les paraules clau del llenguatge BLIF per a saber què fer en funció de cada paraula clau. Així si trobem .names ho tractarem com una LUT, si trobem .buff ho tractarem com un DFF, etc.

Aquesta funció s’encarrega fer justament això: en funció de la primera paraula clau de cada línia direcciona el flux del programa cap a un lloc o cap a l’altre.

5.4.2.10 int TTraductor::PalabraClave(AnsiString palabra[])

Per tal de que la funció anterior sàpiga quina és la paraula clau amb què comença la línia analitzada en cada moment, aquesta funció retorna un índex diferent per a cada paraula clau que hi ha en primera posició.

5.4.2.11 void TTraductor::ParseNames(AnsiString palabra[])

S’executa cada cop que s’identifica la paraula . names com a paraula clau en el codi

BLIF. Quan passa això creem un element de la classe TLut que anomenem Lut, omplim els seus camps amb la informació continguda en les paraules que segueixen a la paraula clau .names, i l’afegim a la llista de LUTs que hem creat per a poder tractar tots aquests elements al final de la lectura del fitxer BLIF. Com hem comentat durant l’infor me, tenim

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

61

una variable que ens indicarà l’última LUT que s’ha creat per a poder -hi incloure el seu contingut en el moment en que aquest aparegui.

5.4.2.12 void TTraductor::ParseBuff(AnsiString palabra[])

És el cas anterior relatiu als Flip Flops. S’executarà cada cop que trobem en el codi

BLIF la paraula clau .buff. Omplirem els seus camps i l’afegirem a la llista de DFFs per poder-los tractar posteriorment.

5.4.2.13 void TTraductor::ParseDbuff(AnsiString palabra[])

És el cas anterior relatiu als Flip Flops de doble context. S’executarà cada cop que trobem en el codi BLIF la paraula clau .dbuff. Omplirem els seus camps i l’afegirem a la llista de BDFFs per poder-los tractar posteriorment.

5.4.2.14 void TTraductor::ParseEnd()

Quan llegim .end el programa retorna el control al fitxer “Tabinterface.cpp” però hem decidit posar la possibilitat de poder realitzar alguna operació quan llegim el final del fitxer BLIF per a futures ampliacions. En el nostre cas no fem res, és una funció buida.

5.4.2.15 void TTraductor::ParseBin(AnsiString palabra[])

En el cas de que la primera paraula d’una línia no correspongui amb cap de les paraules clau de que disposa el BLIF, aquesta funció s’encarrega d’analitzar de què es tracta. Sabem que pot ser una d’aquestes tres opcions:

1. Sigui la continuació d'una llista d'entrades i/o sortides

2. Es tracti del contingut d'una LUT

3. Siguin comentaris o elements no codificats en BLIF

Si llegim ‘\’ voldrà dir que és el primer cas, si llegim ‘0’,’1’ o ‘ -‘ voldrà dir que és el segon, i en qualsevol altre cas suposarem que es tracta de comentaris.

5.4.2.16 void TTraductor::ParseEnd_1ctx(AnsiString nom)

Aquesta funció és cridada pel fitxer de major jerarquia un cop la lectura del fitxer BLIF original ha finalitzat. Creem un nou fitxer d’extensió VHD i fem la crida a la funció encarregada d’im primir aquest fitxer VHDL traducció del fitxer BLIF original. Per a això, juntament amb el nom del fitxer a imprimir, li passem tota la informació generada pel processat de la lectura del fitxer: llista de LUTs, llista de DFFs, continguts de l’Entitat i llista de senyals generats.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

62

5.4.2.17 void TTraductor::ParseEnd(AnsiString nom)

Aquesta funció és similar a l’anterior amb la diferència de que en aquest cas es tracta d’imprimir la traducció dels fitxers particionats. Per aquest motiu la informació que se li ha de passar a la funció encarregada d’escriure el fitxer final VHDL és més àmplia que en el cas anterior ja que es tracta d’informació de dos fitxers.

5.4.3 Entity.cpp

Aquest fitxer conté la classe utilitzada per a definir l’entitat del fitxer VHDL.

5.4.3.1 TEntity::TEntity()

Constructor de la classe, demanem memòria per a les entrades, sortides, nom del model i rellotge del sistema.

5.4.3.2 TEntity::~TEntity()

Destructor de la classe. Està buit, la memòria l’alliberarem un cop haguem imprès el fitxer.

5.4.3.3 void TEntity::OmplirEntitat(AnsiString palabra[],TStringList *Noms[])

Aquesta funció és cridada des del “Traductor.cpp”. S’executa cada cop que trobem una d’aquestes paraules clau en el codi BLIF: .model, .inputs, .outputs, .clock. El que fem és en funció de quina és la paraula per la que s’ha fet la crida a aquesta funció direccionem el flux cap a un lloc o un altre.

5.4.3.4 int TEntity::PalabraClave(AnsiString palabra[])

És la mateixa funció que hem explicat en l’ apartat 5.4.2.10.

5.4.3.5 void TEntity::ParseModel(AnsiString palabra[],TStringList *Noms[])

S’executa en trobar . model al codi BLIF. Dóna el nom a l’entitat VHDL.

5.4.3.6 void TEntity::ParseInputs(AnsiString palabra[],TStringList *Noms[])

S’executa en trobar .inputs al codi BLIF. Afegeix els noms d’entrades del circuit a una llista.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

63

5.4.3.7 void TEntity::ParseOutputs(AnsiString palabra[],TStringList *Noms[])

S’executa en trobar . outputs al codi BLIF. Afegeix els noms de les sortides del circuit a una llista.

5.4.3.8 void TEntity::ParseClock(AnsiString palabra[],TStringList *Noms[])

S’executa en trobar . clock al codi BLIF. Assigna el nom al rellotge del sistema.

5.4.3.9 AnsiString TEntity::TestNom(AnsiString palabra,TStringList *Noms[])

Com hem explicat amb més profunditat en l’ apartat 5.1.1 d’aquesta memòria, els noms acceptats pel BLIF no sempre corresponen amb els que treballa el VHDL. És per aquest motiu que hem creat aquesta funció per a assegurar-nos no solament de que els noms VHDL són adequats sinó també per controlar els possibles canvis de nom que puguin experimentar els noms originals. Aquest control inclou la possibilitat de que dos senyals BLIF diferents no puguin arribar a tenir un mateix nom al codi VHDL, cosa que faria que el codi final no fos el correcte.

Veurem aquesta mateixa funció en els fitxers Lut.cpp, Buff.cpp i DBuff.cpp.

5.4.4 Lut.cpp

Aquest fitxer conté la classe utilitzada per a tractar les LUTs que van sortint al llarg del codi BLIF.

5.4.4.1 TLut::TLut()

És el constructor de la classe, inicialitzem el contingut de la LUT i les seves entrades i sortides en cas de que no s’arribin a utilitzar.

5.4.4.2 TLut::~TLut()

Destructor de la classe, no utilitzat.

5.4.4.3 void TLut::OmplirLut(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[])

Aquesta funció pot ser cridada o bé quan es crea una LUT o bé quan s’hi introdueixen els valors del seu contingut.

En un primer moment, mirem quantes entrades té aquesta LUT i assignem el camp "nom" de l'objecte. Començant pel darrera, omplim primer la sortida de la LUT i després les seves entrades (de dreta a esquerra) de menys a més pes. Per a LUTs de menys de 4

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

64

entrades, les lliures tindran el valor de 'nil'. Cada cop que utilitzarem un senyal comprovarem que no sigui un senyal ja declarat o senyal primari.

5.4.4.4 int TLut::ContaParaules(AnsiString cadena[])

Conta les paraules que segueixen a .names. El que és el mateix, el nombre d’entrades que té aquesta LUT.

5.4.4.5 void TLut::ContingutLut(AnsiString palabra[])

Aquesta funció és cridada des del ParseBin del fitxer “Traductor.cpp” quan identifica un número en binari durant el codi BLIF. Aquest número és dintre d’un AnsiString pel que l’haurem de convertir a cadena de caràcters per poder -hi treballar amb comoditat. Les LUTs amb que treballem són com a molt de 4 entrades, pel que comprovarem que aquestes no siguin més grans. Si efectivament el nombre d’entrades és el correcte, passem aquesta cadena de caràcters d’’1’s , ‘0’s i ‘ -‘s a la funció Arrange.

5.4.4.6 void TLut::Arrange (char* nom)

En aquesta funció tractem el problema de les entrades "don't care" que es representen per '-'. Un número en binari que contingui aquest caràcter no podrà ser convertit a decimal, el que fem és generar a partir d'un binari amb "don't care's" tants numeros binaris com facin falta per codificar-lo correctament. D'aquesta forma, una entrada com 10-- es convertirà en 1000,1001,10010 i 10011.

A mesura que anem generant els diferents números binaris que podem codificar, els passen a la funció BintoDec que retornarà el seu valor decimal. Aquest valor l’utilitzarem com a índex per a adreçar-nos al contingut de la nostra LUT i posar-hi un ‘1’.

5.4.4.7 int TLut::BintoDec (char* nom)

Funció que converteix un número binari "pur" en decimal entenent per "pur" l'existència de només '1' i '0' sense el valor '-'. És un simple convertidor de binari a decimal.

5.4.4.8 AnsiString TLut::TestNom(AnsiString palabra,TStringList *Noms[])

És la mateixa funció que hem explicat en l’ apartat 5.4.3.9.

5.4.5 Buff.cpp

Aquest fitxer conté la classe utilitzada per a tractar els Flip Flops tipus D que van sortint al llarg del codi BLIF.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

65

5.4.5.1 TBuff::TBuff()

Constructor de la classe on s’inicialitzen l’entrada i la sortida del DFF

5.4.5.2 TBuff::~TBuff()

Destructor de la classe, no utilitzat.

5.4.5.3 void TBuff::OmplirBuff(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[])

En aquesta funció assignem l’entrada i la sortida del DFF, que corresponen a l a segona i tercera paraula de la llista. Sempre tenim en compte que els noms utilitzats siguin correctes.

5.4.5.4 AnsiString TBuff::TestNom(AnsiString palabra,TStringList *Noms[])

És la mateixa funció que hem explicat en l’ apartat 5.4.3.9.

5.4.6 DBuff.cpp

És el mateix model que hem vist en el punt anterior però amb un nom de classe diferent per a crear DFFs de doble context. No explicarem les seves funcions perquè són exactament les mateixes, hem decidit crear dos models diferents per a mostrar clarament que els DFFs de doble context no són el mateix que els DFFs normals i per a que en possibles ampliacions d’aquest software s’hi pugui treballar de forma diferenciada i separada.

5.4.7 Rut_in.cpp

És el recurs de rutatge d’entrada del que hem parlat en l’apartat 4.5 . Consta de dues funcions: contructor i destructor; i de les tres variables involucrades en el rutatge: entrada del primer context, entrada del segon context i sortida multiplexada.

5.4.7.1 TRut_in::TRut_in()

Constructor de la classe, inicialitzem aquestes variables a “ not_used” per si hagués alguna entrada que es multiplexa amb cap altra, en aquest cas ho farà amb “ not_used”.

5.4.7.2 TRut_in::~TRut_in()

Destructor de la classe, no utilitzat.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

66

5.4.8 Rut_out.cpp

És el model anàleg al vist en el punt anterior, en aquest cas de rutatge de sortida. Les inicialitzacions són les mateixes amb la diferència de que aquí tenim una única entrada i dues sortides. Només consta de constructor i destructor.

5.4.9 Printer_1ctx.cpp

Aquest és el fitxer encarregat de realitzar la traducció del fitxer BLIF original utilitzant tota la informació emmagatzemada per les funcions anteriorment explicades. La funció de major jerarquia d’aquest fitxer és PrintFile que és cridada des de ParseEnd_1ctx del Traductor.cpp cridat al mateix temps per tabinterface.cpp en veure que el fitxer BLIF original ja ha estat llegit i analitzat.

5.4.9.1 TPrinter_1ctx::TPrinter_1ctx()

Constructor, no utilitzat.

5.4.9.2 TPrinter_1ctx::~TPrinter_1ctx()

Destructor, no utilitzat.

5.4.9.3 void TPrinter_1ctx::PrintFile(FILE *Fout,TEntity Entity,TList *ListBuff,TList *ListLut,TStringList *Signals)

Funció de major jerarquia, des d’aquí es fa la crida per imprimir l’Entitat, l’Arquitectura i el cos del programa VHDL. Quan parlarem d’imprimir ens referirem al fet d’escriure el fitxer final VHDL.

5.4.9.4 void TPrinter_1ctx::PrintEntity(TEntity Entity,FILE *Fout)

Primer incloem les llibreries necessàries per als nostres dissenys i tot seguit imprimim l’entitat: rellotge i entrades de tipus IN STD_LOGIC i sortides de tipus OUT STD_LOGIC. S’ha tingut en compte durant l’escriptura de le s entrades i sortides el fet de que el nombre de noms se sobrepassi en 8 per línia. Recordem que les sortides de l’entitat són el nom de les sortides primàries del BLIF però amb els caràcters “OUT_” al davant tal i com hem explicat en l’ apartat 5.1.6

5.4.9.5 void TPrinter_1ctx::PrintArchitecture(TEntity Entity,FILE *Fout,TStringList *Signals)

Imprimim la declaració d’arquitectura i hi incloem els components que utilitzarem. Tot seguit imprimim els senyals que al BLIF són de sortida primàris, però que tal i com hem explicat en l’ apartat 5.1.6 utilitzarem com a senyals auxiliars. Al darrera, els altres

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

67

senyals auxiliars i les constants del nostres programa. Les constants que emmagatzemen el contingut de les LUTs hem decidit imprimir-les en la funció PrintBody.

5.4.9.6 void TPrinter_1ctx::PrintBody(FILE *Fout,TEntity Entity,TList *ListBuff,TList *ListLut)

El primer que fem és imprimir els continguts de les LUTs, aquests són en forma de constants. Un cop ho tenim imprès comencem a escriure el cos del programa dintre de l’arq uitectura.

Recorrem la llista d’objectes de la classe TBuff i un a un els anem imprimint, en acabar fem el mateix amb les LUTs imprimint la llista d’objectes de la classe TLut. Un cop això ha estat fet assignem a les sortides primàries de la nostra entitat els valors dels senyals de sortida auxiliars que ens hem creat anteriorment per tal de poder utilitzar els senyals de sortida de l’entitat en mode OUT. Veure apartat 5.1.6 d’aquest informe.

Ja per últim escrivim el final de l’arquitectura.

5.4.10 Pinter.cpp

Aquest és el fitxer encarregat de realitzar la traducció dels fitxer BLIF pariticionats utilitzant tota la informació emmagatzemada per les funcions anteriorment explicades. La funció de major jerarquia d’aquest fitxer és PrintFile que és cridada des de ParseEnd_1ctx del Traductor.cpp cridat al mateix temps per tabinterface.cpp en veure que els dos fitxers BLIF ja han estat llegits i analitzats. És en aquest fitxer on s’aplica la multiplexació de senyals i elements, ja que la informació de que disposem són els conjunts de LUTs, BUFFs i DBUFFs de cada fitxer particionat per separat. Per aquest motiu, el primer que farem és crear-nos unes noves llistes de LUTs, BUFFs i DBUFFs multiplexats, a més dels seus corresponents senyals i elements de rutatge. Un cop tindrem això, procedirem com en el cas anterior Printer_1ctx.cpp.

5.4.10.1 TPrinter::TPrinter()

Constructor de la classe. Demanem memòria per als elements de dos contexts que utilitzarem: senyals de dos contexts, senyals de rut_in i rut_out, llista de LUTs, llista de BUFFs, llista de DBUFFs i llistes de Rut_in i Rut_out.

5.4.10.2 TPrinter::~TPrinter()

Destructor de la classe, alliberem tota la memòria utilitzada.

5.4.10.3 void TPrinter::PrintFile(FILE *Fout,TEntity Entity[],TList *ListBuff[],TList *ListDbuff[],TList *ListLut[],TStringList *Signals)

És la funció de major jerarquia, primerament fa una crida a les funcions encarregades de generar els elements multiplexats i seguidament procedeix a escriure el fitxer nom_2ctx.vhd.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

68

5.4.10.4 void TPrinter::CreateLuts_2ctx(TList *ListLut[],TStringList *Signals_2tx)

És la funció encarregada de crear les LUTs de dos contexts a partir de la informació dels dos fitxers nom_0.bli i nom_1.bli i aparellar i multiplexar les diferents entrades i sortides de les LUTs.

El primer que fem és comprovar que el nombre de LUTs en un context és el mateix que en l’altre perquè sinó no podríem aparellar els senyals. Si el nombre no coincideix creem tantes LUTs com sigui necessari per a que tota LUT d’un context sempre tingui una parella a l’altre context. Recordem que aqu estes noves LUTs estan dissenyades de manera que al crear-se ja porten els valors per defecte d’entrades i sortides adequats per a la multiplexació.

Una vegada tenim el mateix nombre de LUTs a un context que a l’altre, cridem a la funció que s’encarregarà d’aparellar -les i crear els nous senyals que se’n derivin. Aquesta funció és OmplirLut_2ctx.

5.4.10.5 void TPrinter::OmplirLut_2ctx(TLut *Lut,TList *ListLut[],TStringList *Signals_2ctx,int i)

Al associar LUTs només manipulem entrades i sortides ja que els continguts són els mateixos que en les LUTs originals. El primer que fem és aparellar les entrades i les sortides de cada LUT de cada context com hem explicat en l’ apartat 5.1.4. generant d’aquesta forma nous senyals que s’afegiran a la llista de senyals multiple xats. Cadascun d’aquests senyals tindrà un rutatge de sortida o entrada en funció de la seva naturalesa com també hem explicat en l’ apartat 5.1.4. Per tant, per a cada senyal multiplexat s’ha generat un element de rutatge que en aquesta mateixa funció serà omplert amb els valors necessaris. Cada vegada que creem un nou element de rutatge, l’afegim a una llista per poder llistar-los tots en ordre al final.

5.4.10.6 void TPrinter::CreateBuffs_2ctx(TList *ListBuff[],TStringList *Signals_2tx)

És el mateix procediment que hem utilitzat en l’apartat 5.4.10.4 amb la diferència de que els elements amb que treballem són els FFs. Primer comprovem que hi hagi el mateix nombre de FFs a tots dos contexts, i posteriorment fem la crida a la funció OmplirBuff_2ctx per a que els aparelli i en generi els corresponents senyals multiplexats amb els seus rutatges.

5.4.10.7 void TPrinter::OmplirBuff_2ctx(TBuff *Buff,TList *ListBuff[],TStringList *Signals_2ctx,int i)

És el mateix procediment que hem utilitzat en l’apartat 5.4.10.5 , però més simple ja que en aquest cas només disposem d’una entrada i una sortida. És important tenir en compte que a l’hora d’escriure les sortides multiplexades, l’ordre d’aquestes s’intercanvia pels motius vistos en l’ apartat 5.1.4. Pel que fa als rutatges, és la mateixa situació que hem vist anteriorment.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

69

5.4.10.8 void TPrinter::CreateDbuffs_2ctx(TList *ListDbuff[],TStringList *Signals_2tx)

Procediment idéntic al vist en l’apartat 5.4.10.6 amb la diferència de que aquí es tracta d’elements DFFs de dos contexts. Funcionalment é s exactament el mateix.

5.4.10.9 void TPrinter::OmplirDbuff_2ctx(TDbuff *Dbuff,TList *ListDbuff[],TStringList *Signals_2ctx,int i)

Procediment idéntic al vist en l’apartat 5.4.10.7 amb la diferència de que com aquí es tracta d’elements DFFs de dos contexts les sor tides no canvien l’ordre quan es multiplexen. Funcionalment és exactament el mateix.

5.4.10.10 void TPrinter::CleanEntity(TEntity Entity[],TStringList *Signals)

Aquesta funció allibera la memòria utilitzada quan hem creat les variables Entity, ja que hi hem accedit durant tot el programa en diverses ocasions i per aquest motiu no ho podíem posar al destructor.

5.4.10.11 void TPrinter::PrintEntity(TEntity Entity[],FILE *Fout)

Primer incloem les llibreries necessàries per als nostres dissenys i tot seguit imprimim l’entitat: s enyal de context, rellotge i entrades de tipus IN STD_LOGIC i sortides de tipus OUT STD_LOGIC. S’ha tingut en compte durant l’escriptura de les entrades i sortides el fet de que el nombre de noms se sobrepassi en 8 per línia. Recordem que les sortides de l’entitat són el nom de les sortides primàries del BLIF però amb els caràcters “OUT_” al davant tal i com hem explicat en l’ apartat 5.1.6

5.4.10.12 void TPrinter::PrintArchitecture(TEntity Entity[],FILE *Fout,TStringList *Signals)

Imprimim la declaració d’arquitectu ra i hi incloem els components que utilitzarem. Tot seguit imprimim les senyals que al BLIF són de sortida primàries, però que tal i com hem explicat en l’ apartat 5.1.6 utilitzarem com a senyals auxiliars. Al darrera, els altres senyals auxiliars, els senyals multiplexats i les constants del nostres programa. Les constants que emmagatzemen el contingut de les LUTs hem decidit imprimir-les en la funció PrintBody

5.4.10.13 void TPrinter::PrintBody(FILE *Fout,TEntity Entity[],TList *ListBuff[],TList *ListDbuff[],TList *ListLut[])

El primer que fem és imprimir els continguts de les LUTs, aquests són en forma de constants. Aquestes constants són exactament les mateixes que hem vist en la traducció del fitxer BLIF original. Un cop ho tenim imprès comencem a escriure el cos del programa dintre de l’arquitectura.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

70

Recorrem la llista d’objectes de la classe TBuff i un a un els anem imprimint, tot seguit fem el mateix amb els elements de la classe TDbuff i en acabar procedim de la mateixa forma amb les LUTs imprimint la llista d’objectes de la classe TLut.

Un cop tenim tots els elements impresos amb els seus senyals, haurem d’imprimir les instanciacions de rutatge, com que ho tenim tot guardat en llistes només haurem d’imprimir tots i cadascun dels elements de les dues llistes Rut_In i Rut_Out.

Per acabar de la mateixa forma que hem fet en la traducció del fitxer original d’un context, assignem a les sortides primàries de la nostra entitat els valors dels senyals de sortida auxiliars que ens hem creat anteriorment per tal de poder utilitzar els senyals de sortida de l’entitat en mode OUT. Veure apartat 5.1.6 d’aquest informe.

Ja per últim escrivim el final de l’arquitectura.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

71

6 Gràfiques i resultats experimentals.

En l’apartat 4 -3-2 d’aquest informe hem après a interpretar les g ràfiques de sortida d’una LUT de doble context, aquesta informació ens serà molt útil per a poder comprendre les gràfiques que veurem a continuació. En aquest capítol veurem uns quants exemples de traducció BLIF a VHDL tant dels fitxers originals com dels corresponents particionats, alhora que podrem comprovar en les gràfiques de les diferents simulacions que el seu comportament és exactament el que s’esperava. Per tal de fer més entenedores les gràfiques hem considerat els retards de tots els elements inexistents i hem doblat la freqüència de rellotge en les simulacions de lògica reconfigurable per tal d’obtenir les mateixes gràfiques de sortida en ambdues simulacions en un mateix temps d’execució.

6.1 Exemple adder

Es tracta del mateix exemple que hem vist en l’apartat 3.3 d’aquest informe. Al ser el primer dels exemples que veurem en aquest capítol hem decidit fer-lo el més entenedor possible i hem introduït tots els esquemes dels circuits per tal de veure clarament com funciona la partició i com s’implementa la multiplexació de senyals.

6.1.1 adder.bli

A la figura 6-1 veiem l’esquema d’un sumador de dos bits a i b (entrades primàries) que genera dues sortides primàries add i Cout, l’una és el resultat de la suma i l’altra és el bit de carry, Aquest bit de carry és utilitzat en la següent iteració per a la següent suma mitjançant un DFF. Les dues funcions lògiques que generen les sortides add i Cout han estat implementades amb dues LUTs.

La línia de punts que podem veure en la figura mostra com s’implementarà la bipartició, veiem que la sortida add es generarà en el segon context mentre que el Cout ho farà al primer.

LUT1

DFFFF1

LUT2

Cin

ab add

Cout

Cin

CinC1

C2

Figura 6.1 adder

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

72

El codi és el següent:

.model adder

.inputs a b

.outputs add Cout

.clock clk .latch Cout Cin re clk 0 .names Cin a b add 001 1 010 1 100 1 111 1 .names Cin a b Cout 011 1 101 1 110 1 111 1 .end

6.1.2 adder.vhd

Aquest codi BLIF traduït a VHDL pel software Traductor_2ctx genera el codi que veiem a continuació. Observem que com ja hem explicat anteriorment, les sortides primàries del BLIF actúen com a senyals intermitjos durant el codi VHDL generant-ne uns altres OUT_add i OUT_Cout als que s’hi assignaran aquests valors com podem veure en les últimes línies del codi VHDL.

library ieee; use ieee.std_logic_1164.all; entity adder is port( clk,a,b : in STD_LOGIC; OUT_add,OUT_Cout : out STD_LOGIC); end adder; architecture blif2vhdl of adder is component LUT generic (Delay:Time; Table_0:STD_LOGIC_VECTOR (0 to 15)); port (in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC); end component; component DFF generic (delay : time); port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; signal add,Cout : STD_LOGIC :='U'; signal Cin : STD_LOGIC :='U'; constant nil: STD_LOGIC:='0'; constant none: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant Delay:time:=0 ns; constant Delay_Lut:time:=0 ns; constant Delay_Buff:time:=0 ns; constant LUT_add : STD_LOGIC_VECTOR(0 TO 15):="0110100100000000"; constant LUT_Cout : STD_LOGIC_VECTOR(0 TO 15):="0001011100000000";

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

73

BEGIN DFF_Cin : DFF generic map (Delay_Buff) port map(clk,Cout,Cin); LUT_aadd : LUT generic map (Delay_Lut,LUT_add) port map(nil,Cin,a,b,add); LUT_aCout : LUT generic map (Delay_Lut,LUT_Cout) port map(nil,Cin,a,b,Cout); OUT_add<=add; OUT_Cout<=Cout; END blif2vhdl;

6.1.3 adder_0.bli

Aquest és el primer fitxer generat per l’algoritme de bipartició temporal, si mirem la Figura 6-1 veurem que els senyals a, b i Cin s’utilitzen en ambdós contexts i a més a més el valor de Cout és utilitzat també en el següent context. És per aquests motius que necessitarem a part d’una LUT quatre Flip Flops per a comunicar aquests senyals al contexts següent.

LUT1

FF1

D Q

FF4

FF3

D Q

FF2

D Q

D Q

ab

Cin

Cout *Cout

*Cin

*a

*b

clk

Figura 6.2 adder context 0

El codi generat pel software de bipartició temporal és el següent:

.model Context#0

.inputs Cin a b

.outputs Cout *Cout *Cin *a *b

.clock clk

.names Cin a b Cout

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

74

011 1 101 1 110 1 111 1 .buff Cout *Cout RE clk 0 .buff Cin *Cin RE clk 0 .buff a *a RE clk 0 .buff b *b RE clk 0 .end

6.1.4 adder_1.bli

A la Figura 6-3 veiem la configuració de la FPGA durant el context 1. Observem que la cel· la LUT és compartida a l’igual que també ho són les cel· les DFFs encara que en aquest context només s’utilitza el primer.

LUT1 FF1

D Q

FF4

FF3

D Q

FF2

D Q

D Q

add Cin*a*b

*Cin

*Cout

clk

Figura 6.3 adder context 1

De la mateixa manera que abans el codi generat és el que segueix:

.model Context#1

.inputs *Cout *Cin *a *b

.outputs Cin add

.clock clk

.latch *Cout Cin re clk 0 .names *Cin *a *b add 001 1 010 1 100 1 111 1 .end

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

75

6.1.5 adder_2ctx.vhd

Un cop tenim els dos fitxers BLIF particionats, el nostre software els analitzarà per a crear una configuració com la que veiem a la Figura 6-4 on podem apreciar com s’han anat aparellant els senyals en funció de l’ordre de la seva aparició i de l’element al que pertanyen. Per tenir una idea més clara de com es multiplexen els senyals hem mostrat els senyals multiplexats més significatius amb els seus corresponents valors individuals en l’apartat 6 -1-7 d’aquest informe.

clk

FF1

D Q

FF4

FF3

D Q

FF2

D Q

D Q

Cin_*Cout

Cout_*Cout

Cin_notused notused_*Cin

a_notused notused_*a

b_notused notused_*b

0

1

0

1

Cin

*Cout

0

1

0

1

notused

*Cin

0

1

0

1

notused

*a

0

1

0

1

notused

*b

0

1

0

1

0

1

0

1

0

1

0

1

0

1

0

1

0

1

0

1

0

1

0

1

0

1

0

1

LUT1

0

1

0

1

Cout_add

nil_nil

Cin_*Cin

a_*a

b_*b

Cout0

1

0

1 add

notused

notused

notused

a

b

nil

*b

nil

*Cin

Cin

*a

b

a

Cout

*Cout

Cin

a

Figura 6.4 adder multiplexat

Aquest és el codi generat en VHDL pel nostre Software Traductor, observem com els recursos de rutatge es corresponen amb els multiplexors i demultiplexors del circuit:

library ieee; use ieee.std_logic_1164.all; entity adder is port( ctx,clk,a,b : in STD_LOGIC;

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

76

OUT_add,OUT_Cout : out STD_LOGIC); end adder; architecture blif2vhdl of adder is component DLUT generic ( Delay:Time; Table_0:STD_LOGIC_VECTOR (0 to 15); Table_1:STD_LOGIC_VECTOR (0 to 15)); port (ctx,in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC); end component; component DFF generic (delay : time); port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; component BDFF generic (delay : time); port ( clk, ctx, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; component RUT_IN generic (delay : time); port (ctx :in STD_LOGIC; in_ctx_0,in_ctx_1 : in STD_LOGIC; output :out STD_LOGIC ); end component; component RUT_OUT generic (delay : time); port (ctx :in STD_LOGIC; out_ctx_0,out_ctx_1 : out STD_LOGIC; input : in STD_LOGIC ); end component; signal add,Cout : STD_LOGIC :='U'; signal Cin,BuffCout,BuffCin,Buffa,Buffb : STD_LOGIC :='U'; signal nil_nil,Cin_BuffCin,a_Buffa,b_Buffb,Cout_add,Cout_BuffCout, Cin_BuffCout,Cin_notused : STD_LOGIC :='U'; signal notused_BuffCin,a_notused,notused_Buffa,b_notused, notused_Buffb : STD_LOGIC :='U'; constant nil: STD_LOGIC:='0'; constant none: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant Delay:time:=0 ns; constant Delay_Lut:time:=0 ns; constant Delay_Buff:time:=0 ns; constant Delay_Dbuff:time:=0 ns; constant Delay_In:time:=0 ns; constant Delay_Out:time:=0 ns; signal notused: STD_LOGIC :='U'; constant LUT_notused: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant LUT_Cout :STD_LOGIC_VECTOR(0 TO 15):= "0001011100000000"; constant LUT_add : STD_LOGIC_VECTOR(0 TO 15):="0110100100000000";

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

77

BEGIN DFF_Cin_BuffCout : DFF generic map (Delay_Buff) port map(clk,Cout_BuffCout,Cin_BuffCout); DFF_notused_BuffCin : DFF generic map (Delay_Buff) port map(clk,Cin_notused,notused_BuffCin); DFF_notused_Buffa : DFF generic map (Delay_Buff) port map(clk,a_notused,notused_Buffa); DFF_notused_Buffb : DFF generic map (Delay_Buff) port map(clk,b_notused,notused_Buffb); DLUT_Cout_add : DLUT generic map (Delay_Lut,LUT_Cout,LUT_add) port map(ctx,nil_nil,Cin_BuffCin,a_Buffa,b_Buffb,Cout_add); RUT_IN_nil_nil : RUT_IN generic map (Delay_In) port map (ctx,nil,nil,nil_nil); RUT_IN_Cin_BuffCin : RUT_IN generic map (Delay_In) port map (ctx,Cin,BuffCin,Cin_BuffCin); RUT_IN_a_Buffa : RUT_IN generic map (Delay_In) port map (ctx,a,Buffa,a_Buffa); RUT_IN_b_Buffb : RUT_IN generic map (Delay_In) port map (ctx,b,Buffb,b_Buffb); RUT_IN_Cout_BuffCout : RUT_IN generic map (Delay_In) port map (ctx,Cout,BuffCout,Cout_BuffCout); RUT_IN_Cin_notused : RUT_IN generic map (Delay_In) port map (ctx,Cin,notused,Cin_notused); RUT_IN_a_notused : RUT_IN generic map (Delay_In) port map (ctx,a,notused,a_notused); RUT_IN_b_notused : RUT_IN generic map (Delay_In) port map (ctx,b,notused,b_notused); RUT_OUT_Cout_add : RUT_OUT generic map (Delay_Out) port map (ctx,Cout,add,Cout_add); RUT_OUT_Cin_BuffCout : RUT_OUT generic map (Delay_Out) port map (ctx,Cin,BuffCout,Cin_BuffCout); RUT_OUT_notused_BuffCin : RUT_OUT generic map (Delay_Out) port map (ctx,notused,BuffCin,notused_BuffCin); RUT_OUT_notused_Buffa : RUT_OUT generic map (Delay_Out) port map (ctx,notused,Buffa,notused_Buffa); RUT_OUT_notused_Buffb : RUT_OUT generic map (Delay_Out) port map (ctx,notused,Buffb,notused_Buffb); OUT_add<=add; OUT_Cout<=Cout; END blif2vhdl;

6.1.6 Gràfiques d’ adder.vhd

Com hem comentat anteriorment, després de la bipartició temporal la sortida add i la Cout no es generen en el mateix context. És per aquest motiu que hem decidit posar dues gràfiques per a il· lustrar la simulació. En aquesta primera gràfica veurem els temps en que el senyal OUT_add és assertat a ‘1’ i es manté fins un canvi de valor.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

78

Figura 6.5 gràfica adder (1)

En aquesta segona gràfica ens centrarem amb el senyal OUT_Cout. No hem mostrat el senyal Cin en aquestes dues gràfiques per a simplificar però si analitzem detingudament les ones veurem que el sumador de dos bits funciona correctament.

Figura 6.6 gràfica adder (2)

6.1.7 Gràfiques d’ adder_2ctx.vhd

L’objectiu d’aquestes gràfiques és el de mostrar que la simulació corresponent al codi generat pel programa traductor tant per a circuits de lògica no reconfigurable com per als que si que ho són, es correspon totalment. Hem de tenir en compte però la teoria de bipartició explicada anteriorment per tal de poder avaluar aquestes formes d’ona.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

79

Recordem de la Figura 6-1 que quan la bipartició s’implementa es genera una situació de canvi de context a cada flanc ascendent de rellotge, junt amb això veiem que en aquest circuit en particular la nova configuració genera en el context 0 la sortida OUT_Cout i en el context 1 la sortida OUT_add. Com que aquestes simulacions intenten apropar-se al màxim al model real i el model real multiplexa els senyals, sabrem que un senyal que només és actiu en un context determinat tindrà un valor indefinit durant el context on no és utilitzat.

En aquesta primera gràfica, igual com hem fet abans, ens centrarem en el senyal OUT_add. Observem per tant, com el seu valor només està definit quan ens trobem en el context 1 i la resta del temps té un valor indeterminat. D’altra ba nda podem apreciar com els temps des de que el senyal pren el valor ‘1’ fins que pren el valor ‘0’ són els mateixos que en la Figura 6-5

És important remarcar que la freqüència del rellotge ha estat doblada però les entrades canvien cada dos cicles de rellotge per tal de poder veure més clarament de forma visual la correspondència amb el seu circuit original.

Figura 6.7 gràfica adder dos contexts (1)

A la Figura 6-8 veiem com el senyal OUT_Cout només existeix en el context 1 i la resta del temps té un valor indefinit. A l’igual que en la gràfica anterior, podem observar que es correspon totalment amb la gràfica vista en la Figura 6-6.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

80

Figura 6.8 gràfica adder dos contexts (2)

En aquesta gràfica de la Figura 6-9 hem afegit als anteriors alguns dels senyals més significatius per tal de comprendre com funciona la multiplexació de senyals en FPGA’s de lògica reconfigurable multicontext. Hem comentat que OUT_Cout es genera en el context 0 i l’OUT_add al context 1, dóna la casualitat de que aquests dos senyals estan multiplexats entre ells per tant és relativament fàcil veure el seu funcionament. Pel fet d’estar multiplexats s’ha creat un nou senyal anomenat Cout_add (recordem que Cout i OUT_Cout tenen sempre el mateix valor i que de fet utilitzem Cout i add durant tot el programa). Aquest senyal Cout_add és un senyal generat per la LUT de doble context i el valor d’aquest senyal s’aplica a Cout o a add en funció del context on ens trobem. Se li aplica, doncs, un Rut_Out. El mateix passa amb Cin_BuffCout amb la diferència de que en aquest cas el senyal és generat a la sortida d’un DFF.

Figura 6.9 gràfica adder dos contexts (3)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

81

6.2 Exemple comptador

Es tracta d’un comptador ascendent de 4 bits. Compta de 0 a 15 i quan arriba a 15 torna a començar. Està dissenyat de manera que quan Vcc=’1’ compta i quan Vcc=’0’ s’atura fins que es torni a posar a ‘1’.

Com en l’exemple anterior hem explicat amb més detall en què consiteix la multiplexació de senyals i com es duu a terme, en aquest exemple ens limitarem a mostrar un esquema del circuit original i analitzarem les seves gràfiques generades pel codi VHDL traduït del BLIF pel Software Traductor. A l’igual que en l’exemple anterior la línia de punts indica com s’h a implementat la bipartició.

DFFFF1

DFFFF1

DFFFF1

DFFFF1

Q0

Q1

Q2

Q3

LUTVcc

LUT

LUT

LUT

LUT

LUT

XOR

XOR

XOR

XOR

AND

AND

D0

D1

D2

D3

A

B

C2

C1

Figura 6.10 Esquema del comptador

6.2.1 comptador.bli

L’esquema de la Figura 6-10 es descriu en llenguatge BLIF mitjançant aquest codi:

.model comptador .inputs Vcc .outputs Q0 Q1 Q2 Q3 .clock clk .latch D0 Q0 re clk 0 .latch D1 Q1 re clk 0 .latch D2 Q2 re clk 0 .latch D3 Q3 re clk 0 .names Q0 Vcc D0

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

82

10 1 01 1 .names Q1 Q0 D1 10 1 01 1 .names Q2 A D2 10 1 01 1 .names Q3 B D3 10 1 01 1 .names Q1 Q0 A 11 1 .names Q2 Q1 Q0 B 111 1 .end

6.2.2 comptador.vhd

Es tracta d’un circuit principalment seqüencial, aquest és el codi VHDL corresponent.

library ieee; use ieee.std_logic_1164.all; entity comptador is port( clk,Vcc : in STD_LOGIC; OUT_Q0,OUT_Q1,OUT_Q2,OUT_Q3 : out STD_LOGIC); end comptador; architecture blif2vhdl of comptador is component LUT generic (Delay:Time; Table_0:STD_LOGIC_VECTOR (0 to

15)); port (in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC); end component; component DFF generic (delay : time); port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; signal Q0,Q1,Q2,Q3 : STD_LOGIC :='U'; signal D0,D1,D2,D3,A,B : STD_LOGIC :='U'; constant nil: STD_LOGIC:='0'; constant none: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant Delay:time:=0 ns; constant Delay_Lut:time:=0 ns; constant Delay_Buff:time:=0 ns; constant LUT_D0 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_D1 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_D2 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_D3 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_A : STD_LOGIC_VECTOR(0 TO 15):="0001000000000000"; constant LUT_B : STD_LOGIC_VECTOR(0 TO 15):="0000000100000000";

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

83

BEGIN DFF_Q0 : DFF generic map (Delay_Buff) port map(clk,D0,Q0); DFF_Q1 : DFF generic map (Delay_Buff) port map(clk,D1,Q1); DFF_Q2 : DFF generic map (Delay_Buff) port map(clk,D2,Q2); DFF_Q3 : DFF generic map (Delay_Buff) port map(clk,D3,Q3); LUT_aD0 : LUT generic map (Delay_Lut,LUT_D0) port map(nil,nil,Q0,Vcc,D0); LUT_aD1 : LUT generic map (Delay_Lut,LUT_D1) port map(nil,nil,Q1,Q0,D1); LUT_aD2 : LUT generic map (Delay_Lut,LUT_D2) port map(nil,nil,Q2,A,D2); LUT_aD3 : LUT generic map (Delay_Lut,LUT_D3) port map(nil,nil,Q3,B,D3); LUT_aA : LUT generic map (Delay_Lut,LUT_A) port map(nil,nil,Q1,Q0,A); LUT_aB : LUT generic map (Delay_Lut,LUT_B) port map(nil,Q2,Q1,Q0,B); OUT_Q0<=Q0; OUT_Q1<=Q1; OUT_Q2<=Q2; OUT_Q3<=Q3; END blif2vhdl;

6.2.3 comptador_0.bli

Codi BLIF del primer context del fitxer particionat, una LUT i cinc DFFs:

.model Context#0 .inputs Q0 Vcc Q1 Q2 Q3 .outputs *D0 *Q1 *Q2 *Q3 *Q0 .clock clk .names Q0 Vcc D0 10 1 01 1 .buff D0 *D0 RE clk 0 .buff Q1 *Q1 RE clk 0 .buff Q2 *Q2 RE clk 0 .buff Q3 *Q3 RE clk 0 .buff Q0 *Q0 RE clk 0 .end

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

84

6.2.4 comptador_1.bli

Codi BLIF del segon context del fitxer particionat, cinc LUTs i quatre DFFs, observem que en el context anterior els DFFs fan la funció de comunicació de senyals del primer al segon context. Això passa perquè les sortides primàries del circuit estan mapejades totes al context 0 (primer context) i són necessaris els seus valors en el context 1 també. En el cas del context 1 són DFFs originals utilitzats per a les funcions seqüencials que caracteritzen aquest circuit.

.model Context#1

.inputs *Q1 *Q0 *Q2 *Q3 *D0

.outputs Q1 Q2 Q3 Q0

.clock clk

.latch D1 Q1 re clk 0

.latch D2 Q2 re clk 0

.latch D3 Q3 re clk 0 .names *Q1 *Q0 D1 10 1 01 1 .names *Q2 A D2 10 1 01 1 .names *Q3 B D3 10 1 01 1 .names *Q1 *Q0 A 11 1 .names *Q2 *Q1 *Q0 B 111 1 .latch *D0 Q0 re clk 0 .end

6.2.5 comptador_2ctx.vhd

El codi VHDL generat pel Software és el següent:

library ieee; use ieee.std_logic_1164.all; entity comptador is port( ctx,clk,Vcc : in STD_LOGIC; OUT_Q0,OUT_Q1,OUT_Q2,OUT_Q3 : out STD_LOGIC); end comptador; architecture blif2vhdl of comptador is component DLUT generic ( Delay:Time; Table_0:STD_LOGIC_VECTOR (0 to 15); Table_1:STD_LOGIC_VECTOR (0 to 15)); port (ctx,in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC); end component;

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

85

component DFF generic (delay : time); port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; component BDFF generic (delay : time); port ( clk, ctx, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; component RUT_IN generic (delay : time); port (ctx :in STD_LOGIC; in_ctx_0,in_ctx_1 : in STD_LOGIC; output :out STD_LOGIC ); end component; component RUT_OUT generic (delay : time); port (ctx :in STD_LOGIC; out_ctx_0,out_ctx_1 : out STD_LOGIC; input : in STD_LOGIC ); end component; signal Q0,Q1,Q2,Q3 : STD_LOGIC :='U'; signal D0,D1,D2,D3,A,B,BuffD0,BuffQ1 : STD_LOGIC :='U'; signal BuffQ2,BuffQ3,BuffQ0 : STD_LOGIC :='U'; signal

nil_nil,Q0_BuffQ1,Vcc_BuffQ0,D0_D1,nil_BuffQ2,nil_A,notused_D2,nil_BuffQ3 : STD_LOGIC :='U';

signal nil_B,notused_D3,nil_BuffQ1,nil_BuffQ0,notused_A,notused_B,Q1_BuffD0 : STD_LOGIC :='U';

signal Q1_D2,Q2_BuffQ1,Q2_D3,Q3_BuffQ2,Q3_BuffD0,Q0_BuffQ3,Q0_notused : STD_LOGIC :='U';

signal notused_BuffQ0 : STD_LOGIC :='U'; constant nil: STD_LOGIC:='0'; constant none: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant Delay:time:=0 ns; constant Delay_Lut:time:=0 ns; constant Delay_Buff:time:=0 ns; constant Delay_Dbuff:time:=0 ns; constant Delay_In:time:=0 ns; constant Delay_Out:time:=0 ns; signal notused: STD_LOGIC :='U'; constant LUT_notused: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant LUT_D0 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_D1 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_D2 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_D3 : STD_LOGIC_VECTOR(0 TO 15):="0110000000000000"; constant LUT_A : STD_LOGIC_VECTOR(0 TO 15):="0001000000000000"; constant LUT_B : STD_LOGIC_VECTOR(0 TO 15):="0000000100000000";

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

86

BEGIN DFF_Q1_BuffD0 : DFF generic map (Delay_Buff) port map(clk,D0_D1,Q1_BuffD0); DFF_Q2_BuffQ1 : DFF generic map (Delay_Buff) port map(clk,Q1_D2,Q2_BuffQ1); DFF_Q3_BuffQ2 : DFF generic map (Delay_Buff) port map(clk,Q2_D3,Q3_BuffQ2); DFF_Q0_BuffQ3 : DFF generic map (Delay_Buff) port map(clk,Q3_BuffD0,Q0_BuffQ3); DFF_notused_BuffQ0 : DFF generic map (Delay_Buff) port map(clk,Q0_notused,notused_BuffQ0); DLUT_D0_D1 : DLUT generic map (Delay_Lut,LUT_D0,LUT_D1) port map(ctx,nil_nil,nil_nil,Q0_BuffQ1,Vcc_BuffQ0,D0_D1); DLUT_notused_D2 : DLUT generic map (Delay_Lut,LUT_notused,LUT_D2) port map(ctx,nil_nil,nil_nil,nil_BuffQ2,nil_A,notused_D2); DLUT_notused_D3 : DLUT generic map (Delay_Lut,LUT_notused,LUT_D3) port map(ctx,nil_nil,nil_nil,nil_BuffQ3,nil_B,notused_D3); DLUT_notused_A : DLUT generic map (Delay_Lut,LUT_notused,LUT_A) port map(ctx,nil_nil,nil_nil,nil_BuffQ1,nil_BuffQ0,notused_A); DLUT_notused_B : DLUT generic map (Delay_Lut,LUT_notused,LUT_B) port map(ctx,nil_nil,nil_BuffQ2,nil_BuffQ1,nil_BuffQ0,notused_B); RUT_IN_nil_nil : RUT_IN generic map (Delay_In) port map (ctx,nil,nil,nil_nil); RUT_IN_Q0_BuffQ1 : RUT_IN generic map (Delay_In) port map (ctx,Q0,BuffQ1,Q0_BuffQ1); RUT_IN_Vcc_BuffQ0 : RUT_IN generic map (Delay_In) port map (ctx,Vcc,BuffQ0,Vcc_BuffQ0); RUT_IN_nil_BuffQ2 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffQ2,nil_BuffQ2); RUT_IN_nil_A : RUT_IN generic map (Delay_In) port map (ctx,nil,A,nil_A); RUT_IN_nil_BuffQ3 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffQ3,nil_BuffQ3); RUT_IN_nil_B : RUT_IN generic map (Delay_In) port map (ctx,nil,B,nil_B); RUT_IN_nil_BuffQ1 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffQ1,nil_BuffQ1); RUT_IN_nil_BuffQ0 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffQ0,nil_BuffQ0); RUT_IN_Q1_D2 : RUT_IN generic map (Delay_In) port map (ctx,Q1,D2,Q1_D2); RUT_IN_Q2_D3 : RUT_IN generic map (Delay_In) port map (ctx,Q2,D3,Q2_D3); RUT_IN_Q3_BuffD0 : RUT_IN generic map (Delay_In) port map (ctx,Q3,BuffD0,Q3_BuffD0); RUT_IN_Q0_notused : RUT_IN generic map (Delay_In) port map (ctx,Q0,notused,Q0_notused); RUT_OUT_D0_D1 : RUT_OUT generic map (Delay_Out) port map (ctx,D0,D1,D0_D1); RUT_OUT_notused_D2 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,D2,notused_D2); RUT_OUT_notused_D3 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,D3,notused_D3); RUT_OUT_notused_A : RUT_OUT generic map (Delay_Out)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

87

port map (ctx,notused,A,notused_A); RUT_OUT_notused_B : RUT_OUT generic map (Delay_Out) port map (ctx,notused,B,notused_B); RUT_OUT_Q1_BuffD0 : RUT_OUT generic map (Delay_Out) port map (ctx,Q1,BuffD0,Q1_BuffD0); RUT_OUT_Q2_BuffQ1 : RUT_OUT generic map (Delay_Out) port map (ctx,Q2,BuffQ1,Q2_BuffQ1); RUT_OUT_Q3_BuffQ2 : RUT_OUT generic map (Delay_Out) port map (ctx,Q3,BuffQ2,Q3_BuffQ2); RUT_OUT_Q0_BuffQ3 : RUT_OUT generic map (Delay_Out) port map (ctx,Q0,BuffQ3,Q0_BuffQ3); RUT_OUT_notused_BuffQ0 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,BuffQ0,notused_BuffQ0); OUT_Q0<=Q0; OUT_Q1<=Q1; OUT_Q2<=Q2; OUT_Q3<=Q3; END blif2vhdl;

6.2.6 Gràfica de comptador.vhd

Com es pot veure en la Figura 6-11 es tracta d’un comp tador de 4 bits. És un circuit molt bàsic però entenedor per a veure que la simulació en lògica reconfigurable multi-context es correspon amb el circuit original.

Figura 6.11 gràfica comptador

6.2.7 Gràfica de comptador_2ctx.vhd

Com podem observar en la Figura 6-12, les 4 sortides del circuit estan mapejades al context 0. Això fa molt més fàcil el poder interpretar la gràfica i comparar-la amb l’anterior. Si ens fixem amb el senyal OUT_Q3 veurem que està 8 cicles a ‘0’ i després 8 cicles a ‘1’ ( quan és acti u en el seu context, és clar). Si en acabar parem atenció al senyal

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

88

OUT_Q2 veurem que n’està la meitat. OUT_Q1 estarà dos períodes a ‘1’ i en acabar dos a ‘0’. Ja per acabar veiem que OUT_Q0 corresponent al bit de menys pes del comptador canvia el seu valor a cada context en què és actiu.

Figura 6.12 gràfica comptador 2 contexts

6.3 Exemple S27_n

Hem escollit aquest exemple del que desconeixem la seva funcionalitat perquè als seus fitxers particionats trobem FFs de doble context. No coneixem què fa el circuit però sabem que si el Software Traductor està ben implementat podrem interpretar les gràfiques de totes dues simulacions i concloure que es corresponen. De fet, aquest circuit té una única sortida que veurem que és mapejada en el context 1. Això ens fa pensar a priori que la gràfica de sortida del circuit particionat i multiplexat serà com la del circuit VHDL original però desplaçada un context respecte de les seves entrades ja que aquestes tenen lloc en el context 0. Això significa sabent que el període del rellotge és de 50ns i que un canvi de context té lloc a cada flanc de pujada del rellotge que efectivament el desfasament entre gràfiques serà de 50ns.

6.3.1 s27_n.bli .model s27 .inputs G0 G1 G2 G3 .outputs G17 .clock clk .latch [3018] G5 re clk 0 .latch [3021] G6 re clk 0 .latch [3023] G7 re clk 0 .names G5 G9 G17 1- 1 -1 1 .names G0 G5 G9 [3018] 11- 1 1-1 1 .names G5 G9 [3021]

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

89

00 1 .names G1 G2 G7 [3023] 10- 1 -01 1 .names G0 G1 G6 G7 G15 0-1- 1 -0-0 1 .names G0 G3 G6 G15 G9 ---0 1 10-- 1 -00- 1 .end

6.3.2 s27_n.vhd library ieee; use ieee.std_logic_1164.all; entity s27 is port( clk,G0,G1,G2,G3 : in STD_LOGIC; OUT_G17 : out STD_LOGIC); end s27; architecture blif2vhdl of s27 is component LUT generic (Delay:Time; Table_0:STD_LOGIC_VECTOR (0 to

15)); port (in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC); end component; component DFF generic (delay : time); port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; signal G17 : STD_LOGIC :='U'; signal k3018,G5,k3021,G6,k3023,G7,G9,G15 : STD_LOGIC :='U'; constant nil: STD_LOGIC:='0'; constant none: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant Delay:time:=0 ns; constant Delay_Lut:time:=0 ns; constant Delay_Buff:time:=0 ns; constant LUT_G17 : STD_LOGIC_VECTOR(0 TO 15):="0111000000000000"; constant LUT_k3018 : STD_LOGIC_VECTOR(0 TO

15):="0000011100000000"; constant LUT_k3021 : STD_LOGIC_VECTOR(0 TO

15):="1000000000000000"; constant LUT_k3023 : STD_LOGIC_VECTOR(0 TO

15):="0100110000000000"; constant LUT_G15 : STD_LOGIC_VECTOR(0 TO 15):="1011001110100000"; constant LUT_G9 : STD_LOGIC_VECTOR(0 TO 15):="1110101011111010"; BEGIN DFF_G5 : DFF generic map (Delay_Buff)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

90

port map(clk,k3018,G5); DFF_G6 : DFF generic map (Delay_Buff) port map(clk,k3021,G6); DFF_G7 : DFF generic map (Delay_Buff) port map(clk,k3023,G7); LUT_aG17 : LUT generic map (Delay_Lut,LUT_G17) port map(nil,nil,G5,G9,G17); LUT_ak3018 : LUT generic map (Delay_Lut,LUT_k3018) port map(nil,G0,G5,G9,k3018); LUT_ak3021 : LUT generic map (Delay_Lut,LUT_k3021) port map(nil,nil,G5,G9,k3021); LUT_ak3023 : LUT generic map (Delay_Lut,LUT_k3023) port map(nil,G1,G2,G7,k3023); LUT_aG15 : LUT generic map (Delay_Lut,LUT_G15) port map(G0,G1,G6,G7,G15); LUT_aG9 : LUT generic map (Delay_Lut,LUT_G9) port map(G0,G3,G6,G15,G9); OUT_G17<=G17; END blif2vhdl;

6.3.3 s27_n_0.bli .model Context#0 .inputs G1 G2 G7 G0 G6 G3 .outputs *[3023] *G15 *G6 *G0 *G3 .clock clk .names G1 G2 G7 [3023] 10- 1 -01 1 .names G0 G1 G6 G7 G15 0-1- 1 -0-0 1 .buff [3023] *[3023] RE clk 0 .buff G15 *G15 RE clk 0 .buff G6 *G6 RE clk 0 .buff G0 *G0 RE clk 0 .buff G3 *G3 RE clk 0 .end

6.3.4 s27_n_1.bli .model Context#1 .inputs *[3023] *G0 *G3 *G6 *G15 .outputs G6 G7 G17 .clock clk .dbuff [3018] G5 RE clk 0 .latch [3021] G6 re clk 0 .latch *[3023] G7 re clk 0

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

91

.names G5 G9 G17 1- 1 -1 1 .names *G0 G5 G9 [3018] 11- 1 1-1 1 .names G5 G9 [3021] 00 1 .names *G0 *G3 *G6 *G15 G9 ---0 1 10-- 1 -00- 1 .end

6.3.5 s27_n_2ctx.vhd library ieee; use ieee.std_logic_1164.all; entity s27 is port( ctx,clk,G0,G1,G2,G3 : in STD_LOGIC; OUT_G17 : out STD_LOGIC); end s27; architecture blif2vhdl of s27 is component DLUT generic ( Delay:Time; Table_0:STD_LOGIC_VECTOR (0 to 15); Table_1:STD_LOGIC_VECTOR (0 to 15)); port (ctx,in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC); end component; component DFF generic (delay : time); port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; component BDFF generic (delay : time); port ( clk, ctx, entrada : in STD_LOGIC; s:out STD_LOGIC); end component; component RUT_IN generic (delay : time); port (ctx :in STD_LOGIC; in_ctx_0,in_ctx_1 : in STD_LOGIC; output :out STD_LOGIC ); end component; component RUT_OUT generic (delay : time); port (ctx :in STD_LOGIC; out_ctx_0,out_ctx_1 : out STD_LOGIC; input : in STD_LOGIC ); end component; signal G17 : STD_LOGIC :='U'; signal k3018,G5,k3021,G6,k3023,G7,G9,G15 : STD_LOGIC :='U';

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

92

signal BuffW3023,BuffG15,BuffG6,BuffG0,BuffG3 : STD_LOGIC :='U'; signal nil_nil,G1_nil,G2_G5,G7_G9,k3023_G17,G0_nil,G1_BuffG0,G6_G5 :

STD_LOGIC :='U'; signal

G15_k3018,nil_G5,nil_G9,notused_k3021,nil_BuffG0,nil_BuffG3,nil_BuffG6 : STD_LOGIC :='U';

signal nil_BuffG15,notused_G9,k3023_k3021,G6_BuffW3023,G15_BuffW3023,G7_BuffG15,G6_notused : STD_LOGIC :='U';

signal notused_BuffG6,G0_notused,notused_BuffG0,G3_notused,notused_BuffG3,notused_k3018,notused_G5 : STD_LOGIC :='U';

constant nil: STD_LOGIC:='0'; constant none: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant Delay:time:=0 ns; constant Delay_Lut:time:=0 ns; constant Delay_Buff:time:=0 ns; constant Delay_Dbuff:time:=0 ns; constant Delay_In:time:=0 ns; constant Delay_Out:time:=0 ns; signal notused: STD_LOGIC :='U'; constant LUT_notused: STD_LOGIC_VECTOR(0 to 15):="UUUUUUUUUUUUUUUU"; constant LUT_k3023 : STD_LOGIC_VECTOR(0 TO

15):="0100110000000000"; constant LUT_G15 : STD_LOGIC_VECTOR(0 TO 15):="1011001110100000"; constant LUT_G17 : STD_LOGIC_VECTOR(0 TO 15):="0111000000000000"; constant LUT_k3018 : STD_LOGIC_VECTOR(0 TO

15):="0000011100000000"; constant LUT_k3021 : STD_LOGIC_VECTOR(0 TO

15):="1000000000000000"; constant LUT_G9 : STD_LOGIC_VECTOR(0 TO 15):="1110101011111010"; BEGIN DFF_G6_BuffW3023 : DFF generic map (Delay_Buff) port map(clk,k3023_k3021,G6_BuffW3023); DFF_G7_BuffG15 : DFF generic map (Delay_Buff) port map(clk,G15_BuffW3023,G7_BuffG15); DFF_notused_BuffG6 : DFF generic map (Delay_Buff) port map(clk,G6_notused,notused_BuffG6); DFF_notused_BuffG0 : DFF generic map (Delay_Buff) port map(clk,G0_notused,notused_BuffG0); DFF_notused_BuffG3 : DFF generic map (Delay_Buff) port map(clk,G3_notused,notused_BuffG3); BDFF_notused_G5 : BDFF generic map (Delay_Dbuff) port map(clk,ctx,notused_k3018,notused_G5); DLUT_k3023_G17 : DLUT generic map (Delay_Lut,LUT_k3023,LUT_G17) port map(ctx,nil_nil,G1_nil,G2_G5,G7_G9,k3023_G17); DLUT_G15_k3018 : DLUT generic map (Delay_Lut,LUT_G15,LUT_k3018) port map(ctx,G0_nil,G1_BuffG0,G6_G5,G7_G9,G15_k3018); DLUT_notused_k3021 : DLUT generic map

(Delay_Lut,LUT_notused,LUT_k3021) port map(ctx,nil_nil,nil_nil,nil_G5,nil_G9,notused_k3021); DLUT_notused_G9 : DLUT generic map (Delay_Lut,LUT_notused,LUT_G9) port

map(ctx,nil_BuffG0,nil_BuffG3,nil_BuffG6,nil_BuffG15,notused_G9); RUT_IN_nil_nil : RUT_IN generic map (Delay_In)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

93

port map (ctx,nil,nil,nil_nil); RUT_IN_G1_nil : RUT_IN generic map (Delay_In) port map (ctx,G1,nil,G1_nil); RUT_IN_G2_G5 : RUT_IN generic map (Delay_In) port map (ctx,G2,G5,G2_G5); RUT_IN_G7_G9 : RUT_IN generic map (Delay_In) port map (ctx,G7,G9,G7_G9); RUT_IN_G0_nil : RUT_IN generic map (Delay_In) port map (ctx,G0,nil,G0_nil); RUT_IN_G1_BuffG0 : RUT_IN generic map (Delay_In) port map (ctx,G1,BuffG0,G1_BuffG0); RUT_IN_G6_G5 : RUT_IN generic map (Delay_In) port map (ctx,G6,G5,G6_G5); RUT_IN_nil_G5 : RUT_IN generic map (Delay_In) port map (ctx,nil,G5,nil_G5); RUT_IN_nil_G9 : RUT_IN generic map (Delay_In) port map (ctx,nil,G9,nil_G9); RUT_IN_nil_BuffG0 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffG0,nil_BuffG0); RUT_IN_nil_BuffG3 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffG3,nil_BuffG3); RUT_IN_nil_BuffG6 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffG6,nil_BuffG6); RUT_IN_nil_BuffG15 : RUT_IN generic map (Delay_In) port map (ctx,nil,BuffG15,nil_BuffG15); RUT_IN_k3023_k3021 : RUT_IN generic map (Delay_In) port map (ctx,k3023,k3021,k3023_k3021); RUT_IN_G15_BuffW3023 : RUT_IN generic map (Delay_In) port map (ctx,G15,BuffW3023,G15_BuffW3023); RUT_IN_G6_notused : RUT_IN generic map (Delay_In) port map (ctx,G6,notused,G6_notused); RUT_IN_G0_notused : RUT_IN generic map (Delay_In) port map (ctx,G0,notused,G0_notused); RUT_IN_G3_notused : RUT_IN generic map (Delay_In) port map (ctx,G3,notused,G3_notused); RUT_IN_notused_k3018 : RUT_IN generic map (Delay_In) port map (ctx,notused,k3018,notused_k3018); RUT_OUT_k3023_G17 : RUT_OUT generic map (Delay_Out) port map (ctx,k3023,G17,k3023_G17); RUT_OUT_G15_k3018 : RUT_OUT generic map (Delay_Out) port map (ctx,G15,k3018,G15_k3018); RUT_OUT_notused_k3021 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,k3021,notused_k3021); RUT_OUT_notused_G9 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,G9,notused_G9); RUT_OUT_G6_BuffW3023 : RUT_OUT generic map (Delay_Out) port map (ctx,G6,BuffW3023,G6_BuffW3023); RUT_OUT_G7_BuffG15 : RUT_OUT generic map (Delay_Out) port map (ctx,G7,BuffG15,G7_BuffG15); RUT_OUT_notused_BuffG6 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,BuffG6,notused_BuffG6); RUT_OUT_notused_BuffG0 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,BuffG0,notused_BuffG0); RUT_OUT_notused_BuffG3 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,BuffG3,notused_BuffG3); RUT_OUT_notused_G5 : RUT_OUT generic map (Delay_Out) port map (ctx,notused,G5,notused_G5);

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

94

OUT_G17<=G17; END blif2vhdl;

6.3.6 Gràfica de s27_n.vhd

Observem en el seu comportament que després de 200ns en que totes les entrades valen ‘0’, la sortida roman a ‘0 durant 1400ns i després canvia a ‘1’ durant 1800ns.

Figura 6.13 gràfica s27

6.3.7 Gràfica de s27_n_2ctx.vhd

Comprovem i justifiquem el raonament fet a priori. S’observa que e l comportament és idèntic al de la Figura 6-13 amb un retard de 50ns com havíem suposat.

Figura 6.14 gràfica s27 (2 contexts)

6.4 Exemple S5378_n

Es tracta d’un circuit del que també desconeixem el seu funcionament, l’hem escollit perquè podríem considerar que és un circuit gran i així demostrem que el software traductor funciona bé no només amb circuits de poques entrades i sortides sinó també amb

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

95

altres com aquest on tenim 35 entrades, 45 sortides, 1098 senyals intermitjos no multiplexats, 1986 senyals intermitjos multiplexats, 330 LUTs, 296 DFFs, 73 BDFFs, 1324 recursos de rutatge d’entrada i 699 recursos de rutatge de sortida.

Degut a la mida del fitxer hem decidit no incloure els diferents netlists en l’informe i per tant només mostrarem dues gràfiques en la mateixa línia dels exemples anteriors. La Figura 6-15 correspon a la simulació del fitxer original, mentre que la Figura 6-16 és relativa al circuit particionat i multiplexat.

6.4.1 Gràfica de s5378_n.vhd

Els senyals representats han estat escollits aleatòriament amb l’única precaució de que siguin senyals significatius en la seva simulació dels fitxers particionats multiplexats.

Podem observar per exemple en aquesta gràfica que el senyal k3437 és l’entrada d’un DFF del que n2510gat n’és la sortida. El mateix passa amb n3067gat i n3066gat que són entrades de DFFs on les sortides són n160gat i n337gat respectivament. La resta de senyals són sortides combinacionals de LUTs.

Figura 6.15 gràfica s5378 (1 context)

6.4.2 Gràfica de s5378_n_2ctx.vhd

En aquesta simulació hem intentat reflectir tots els possibles tipus de senyals generats per tal de veure per una banda que es corresponen amb la simulació anterior, i per l’altra que el fitxer VHDL final s’ha generat de forma adequada.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

96

D’aquesta manera podem veure que els senyals n3117gat, n3120gat i n3107gat són combinacionals i generats al context 0; els senyals n3118gat i n3121gat són combinacionals i generats al context 1; n3067gat és entrada primària al context 0 i entrada a un BDFF la sortida del qual és n160gat que es llegeix també en el context 0 però del següent Macro-cicle. El mateix passa amb n3066gat que també és entrada al context 0 d’un BDFF de sortida n337gat. El senyal k3437 és actiu en el context 1 essent l’ent rada d’un DFF que té la seva sortida al context 0, el nom d’aquesta sortida és n2510gat. Finalment podem veure un altre DFF que té la seva entrada al context 0 amb nom n290gat i la seva sortida al context 1 anomenada buffn290gat.

Figura 6.16 gràfica s5378 (2 contexts)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

97

7 Conclusions i futures millores.

Els dispositius lògics FPGAs reconfigurables dinàmicament (DRFPGAs) tenen com a característica la possibilitat de canviar la funcionalitat d’una porció dels seus blocs lògics i recursos de rutatge, mentre la resta del dispositiu executa una altra tasca computacional. Les FPGAs multi-context permeten una reconfiguració dinàmica molt ràpida, degut a que els nous bits de configuració es troben emmagatzemats en una memòria interna.

Gràcies a l’algoritme de bipartició temporal que serveix de base a aquest projecte, es podrà aprofitar l’arquitectura de les FPGAs Multi -context per tal d’implementar dissenys de major grandària que la capacitat dels recursos hardware del dispositiu.

Aquest projecte ha demostrat que el software de bipartició temporal de fitxers BLIF realitzat pel Dr. Enric Cantó genera fitxers que són simulables i que aquestes simulacions corresponen a les simulacions del fitxer original abans de la partició. Això, però, és només un dels passos que s’han de seguir per a poder implementar circuits particionats sobre dispositius FPGAs reconfigurables dinàmicament.

La situació en que ens trobem és la següent: Disposem d’un software que particiona fitxers BLIF segons la teoria de bipartició temporal. Disposem també a partir d’ara d’un altre software que tradueix aquests netlists de BLIF a VHDL per a poder realitzar simulacions d’aquests fitxers. La realitat, però, és que el llenguatge de descripció hardware utilitzat més universalment és el VHDL i això fa que necessitem un traductor d’algun tipus de netlist VHDL a BLIF per tal de poder-li aplicar aquest algoritme de bipartició temporal. Un cop aquest codi VHDL hagi passat a BLIF i s’hagi particionat, se’l torna a traduir al VHDL mitjançant aquest projecte, se’l simula i finalment se l’hauria de sintetitzar i aplicar un algoritme de “Placement and Routing” específic per a FPGAs multi-context per a poder gravar l’FPGA en acabar. El problema amb que ens trobem és que per una banda aquest sintetitzador i algoritme de “ Placement and Routing” específics per a aquest tipus de dispositius no existeixen, i per altra banda no és possible trobar en el mercat avui en dia FPGAs multi-context. Aquests dispositius van ser comercialitzats durant un temps, però degut a la manca de totes aquestes eines de que parlem no van ser acceptats pels compradors. En la Figura 7-1 veiem en línia contínua els elements ja existents i amb línia de punts els que encara resten per dissenyar. Observem en aquesta figura que hi ha dos branques, la branca esquerra reflexa el procés que es duu a terme per a programar FPGAs no reconfigurables dinàmicament, mentre que la branca dreta mostra els passos a seguir per a poder programar una FPGA multi-context.

Per a la realització d’aquest projecte hem treballat amb llenguatges de descripció hardware com són el BLIF i el VHDL, ens hem hagut de familiaritzar amb el simulador de VHDL anomenat Veribest i hem après a programar en el llenguatge de programació C++. Les principals dificultats amb que ens hem trobat, a part del fet de no conèixer cap dels llenguatges abans esmentats, han estat per una banda la teoria de bipartició temporal de la qual en desconeixia la seva existència i per altra banda a l’hora de dissenyar els models VHDL que utilitzaríem al llarg de totes les simulacions, aquests models havien de ser tant semblants a la realitat com fos possible i a la fi podem dir que el seu comportament en simulació és molt proper al real. Per a fer això, hem tingut en compte al llarg de tot el procés l’estructura física de l’FPGA Multi -context. Un dels altres problemes amb que ens hem trobat ha estat a l’hora d’unir els dos fitxers particionats i dissenyar un algoritme per poder multiplexar-los de manera que el seu comportament continués sent fidel al dispositiu real.

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

98

En definitiva, un projecte molt interessant i ple de continguts educatius que m’han fet treballar amb ganes, convicció i amb la certesa de que al darrera hi haurà una continuïtat tal i com hem explicat en aquest mateix capítol de conclusions per tal de fer de la programació d’FPGAs Multi -context una realitat més accessible a tots els qui treballen amb el llenguatge VHDL.

VHDL

SimuladorTraductor de VHDL a BLIF

Sintetitzador Soft. Bipartició

Place & RouteFPGA

FPGA

Traductor deBLIF-VHDL

Llibreries síntesi Tecnologia Fabricant

FPGAs

Sintetitzador

Place & RouteFPGA

Multi-context

FPGA Multi-context

Llibreries síntesi Tecnologia FabricantFPGAs Multi-contextSimulador

Figura 7.1 Cicle de disseny amb VHDL

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

99

8 Bibliografia.

[1] Enrique Cantó, Juan Manuel Moreno, Nicolau Cañellas, Joan Cabestany Algoritmo de

Bipartición Temporal de Bajo Nivel para FPGAs Multi-Contexto. Departament

d’Enginyeria Elèctrica, Electrònica i Automàtica (DEEEA), Universitat Rovira i Virgili

(URV).

[2] Enrique F. Cantó Navarro. Juliol 2001. Temporal Bipartitioning Techniques For Multi-Context FPGAS. Universitat Politècnica de Catalunya.

[3] http://cas.et.tudelft.nl/education/et4054/sis/blif/blif.html Berkeley Logic Interchange

Format (BLIF ) University of California, Berkeley (Tutorial de BLIF)

[4] http://www.eda.org/vi/comp.lang.vhdl/FAQ1.html#0.1 (Tutorial VHDL)

[5] http://instruct1.cit.cornell.edu/courses/ee475/tutorial/VHDLman.pdf (Tutorial VHDL)

[6] Carlos López Barrio, Rafael Burriel Lluna, Fernando Aldana Mayor. 1998. VHDL lenguaje estándar de diseño electrónico. Madrid. Mc Graw-Hill cop.

[7] VeriBest VHDL Tutorial. (Tutorial del software de simulació VeriBest VHDL)

[8] https://arco.inf-cr.uclm.es/docs/tutorial-veribest (Tutorial de Veribest.)

[9] http://c.conclase.net/curso/indice.html (Tutorial de C++)

[10] http://www.intap.net/~drw/cpp/ (Tutorial de C++)

[11] http://www.techiwarehouse.com/C/C++_Tutorial.html (Tutorial de C++)

[12] http://www.intap.net/~drw/cpp/ (Tutorial de C++)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

100

9 Annex: Codi del Software

9.1 Tabinterface.cpp //--------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "tabinterface.h" //--------------------------------------------------------------------- #pragma resource "*.dfm" TPagesDlg *PagesDlg; //--------------------------------------------------------------------- __fastcall TPagesDlg::TPagesDlg(TComponent* AOwner) : TForm(AOwner) { // Netegem els memos PagesDlg->Memo1->Clear(); PagesDlg->Memo2->Clear(); // Inicialitzem la variable que controla el nombre d'iteracions // d'execució de la lectura de fitxers BLIF PagesDlg->multi=0; if(ParamCount()==1) // Si el programa rep paràmetre d'entrada // l'utilitzem { try { Edit4->Text=ParamStr(1); ArrangeParam(); ExeSoftware(); } catch (int codigo) { if (PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("S'HA PRODUÏT UN ERROR CRITIC!!"); else PagesDlg->Memo2->Lines->Add("S'HA PRODUÏT UN ERROR CRITIC!!"); } } } //--------------------------------------------------------------------- __fastcall TPagesDlg::~TPagesDlg(void) { } //--------------------------------------------------------------------------- void __fastcall TPagesDlg::Button1Click(TObject *Sender) { try { ArrangeParam(); ExeSoftware(); } catch(int codigo)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

101

{ if (PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("S'HA PRODUÏT UN ERROR CRITIC!!"); else PagesDlg->Memo2->Lines->Add("S'HA PRODUÏT UN ERROR CRITIC!!"); } } //--------------------------------------------------------------------- void __fastcall TPagesDlg::ExeSoftware(void) { Traductor= new TTraductor; AnsiString fitxer[3]; AnsiString sortida[2]; fitxer[0]=Edit4->Text; // Fitxer BLIF original fitxer[1]=Edit1->Text; // Fitxer BLIF partició 0 fitxer[2]=Edit2->Text; // Fitxer BLIF partició 1 sortida[0] = Edit5->Text; // Fitxer VHDL 1 ctx sortida[1] = Edit3->Text; // Fitxer VHDL 2 ctx // Netegem els memos PagesDlg->Memo1->Clear(); PagesDlg->Memo2->Clear(); for (PagesDlg->multi=0;PagesDlg->multi<=2;PagesDlg->multi++) { //Obrim fitxer BLIF Traductor->OpenFile(fitxer[PagesDlg->multi].c_str()); // El passem a memòria Traductor->LeerFichero(); // Tanquem el fitxer BLIF Traductor->CloseFile(); // Analitzem el seu contingut Traductor->Parse(); if (PagesDlg->multi==0) // Si és el primer imprimim la traducció // del fitxer original Traductor->ParseEnd_1ctx(sortida[0]); } Traductor->ParseEnd(sortida[1]); // Imprimim el fitxer VHDL 2ctx // Passem tot el contingut dels memos a fitxers PagesDlg->Memo1->Lines->SaveToFile(ChangeFileExt(Edit5->Text, ".INF")); PagesDlg->Memo2->Lines->SaveToFile(ChangeFileExt(Edit3->Text, ".INF")); delete Traductor; } //--------------------------------------------------------------------- void __fastcall TPagesDlg::ArrangeParam(void) { // Partint del nom del fitxer BLIF original, anomenem els altres // fitxers amb que treballarem. char *nom2; nom2= new char[65]; nom2=Edit4->Text.c_str(); AnsiString nom,nom1,nom3,nom4; int i=0; while (nom2[i]!='.') i++; nom2[i]='\0';

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

102

nom=(AnsiString)nom2; nom1=(AnsiString)nom2; nom3=(AnsiString)nom2; nom4=(AnsiString)nom2; Edit5->Text=(AnsiString)nom+=(".vhd"); nom=(AnsiString)nom1; Edit1->Text=(AnsiString)nom+=("_0.bli"); nom=(AnsiString)nom3; Edit2->Text=(AnsiString)nom+=("_1.bli"); nom=(AnsiString)nom4; Edit3->Text=(AnsiString)nom+=("_2ctx.vhd"); }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

103

9.2 Traductor.cpp

#include "traductor.h" #include "tabinterface.h" //--------------------------------------------------------------------------- TTraductor::TTraductor() { // Inicialitzacions LutIndex[0]=-1; LutIndex[1]=-1; LutIndex[2]=-1; Lineas[0]= new TStringList; Lineas[1]= new TStringList; Lineas[2]= new TStringList; Signals= new TStringList; Noms[0]= new TStringList; Noms[1]= new TStringList; ListLut[0] = new TList; ListLut[1] = new TList; ListLut[2] = new TList; ListBuff[0] = new TList; ListBuff[1] = new TList; ListBuff[2] = new TList; ListDbuff[0] = new TList; ListDbuff[1] = new TList; ListDbuff[2] = new TList; } //--------------------------------------------------------------------------- TTraductor::~TTraductor() { // Netegem la memòria utilitzada //CleanBuff for (int i = 0; i < ListBuff[0]->Count; i++) delete ((TBuff*)ListBuff[0]->Items[i]); for (int i = 0; i < ListBuff[1]->Count; i++) delete ((TBuff*)ListBuff[1]->Items[i]); for (int i = 0; i < ListBuff[2]->Count; i++) delete ((TBuff*)ListBuff[2]->Items[i]); //CleanDbuff for (int i = 0; i < ListDbuff[0]->Count; i++) delete ((TDbuff*)ListDbuff[0]->Items[i]); for (int i = 0; i < ListDbuff[1]->Count; i++) delete ((TDbuff*)ListDbuff[1]->Items[i]); for (int i = 0; i < ListDbuff[2]->Count; i++) delete ((TDbuff*)ListDbuff[2]->Items[i]); //CleanLut for (int i = 0; i < ListLut[0]->Count; i++) delete ((TLut*)ListLut[0]->Items[i]); for (int i = 0; i < ListLut[1]->Count; i++) delete ((TLut*)ListLut[1]->Items[i]); for (int i = 0; i < ListLut[2]->Count; i++)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

104

delete ((TLut*)ListLut[2]->Items[i]); delete Signals; delete Noms[0]; delete Noms[1]; delete Lineas[0]; delete Lineas[1]; delete Lineas[2]; delete ListLut[0]; delete ListLut[1]; delete ListLut[2]; delete ListBuff[0]; delete ListBuff[1]; delete ListBuff[2]; delete ListDbuff[0]; delete ListDbuff[1]; delete ListDbuff[2]; } //--------------------------------------------------------------------------- void TTraductor::OpenFile(char *fitxer) { // Obrim el fitxer BLIF Handler=fopen(fitxer,"r+t"); if (Handler!=NULL) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("Fitxer BLIF obert satisfactoriament"); else PagesDlg->Memo2->Lines->Add("Fitxer BLIF obert satisfactoriament"); } else { if(PagesDlg->multi==0) { PagesDlg->Memo1->Lines->Add("El fitxer BLIF no s'ha pogut obrir"); throw 1; } else { PagesDlg->Memo2->Lines->Add("El fitxer BLIF no s'ha pogut obrir"); throw 1; } } } //--------------------------------------------------------------------------- void TTraductor::CloseFile(void) { // Tanquem el fitxer BLIF if (!fclose(Handler)) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("Fitxer BLIF tancat satisfactoriament"); else

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

105

PagesDlg->Memo2->Lines->Add("Fitxer BLIF tancat satisfactoriament"); } else { if(PagesDlg->multi==0) { PagesDlg->Memo1->Lines->Add("El fitxer BLIF no s'ha pogut tancar"); throw 2; } else { PagesDlg->Memo2->Lines->Add("El fitxer BLIF no s'ha pogut tancar"); throw 2; } } } //--------------------------------------------------------------------------- void TTraductor::LeerFichero() { // Recorrem linia a linea el fitxer i ho gardem en una TStringList #define MAX_LINE 1024 char buffer[MAX_LINE+1]; while (fgets(buffer,MAX_LINE,Handler)!=NULL) { AnsiString linea = buffer; Lineas[PagesDlg->multi]->Add(linea); } } //--------------------------------------------------------------------------- void TTraductor::Parse(void) {//Si fem la traducció dels fitxers particionats //buidem les llistes de senyals anteriors. if (PagesDlg->multi==1) { delete Noms[0]; delete Noms[1]; Noms[0]=new TStringList; Noms[1]=new TStringList; } // Agafem cadascuna de les lines(component de TStringList) i les passem a // cadena de caràcters en una altra funció. int LineaParse; for (LineaParse=0; LineaParse<Lineas[PagesDlg->multi]->Count; LineaParse++) { Parse(Lineas[PagesDlg->multi]->Strings[LineaParse].c_str());

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

106

} } //--------------------------------------------------------------------------- void TTraductor::Parse(char *linea) { //Recorrem una cadena de caràcters i omplim un vector d'AnsiStrings //amb els continguts de la cadena AnsiString palabra[MAX_PALABRAS]; char *p_palabra=linea; int j=0; while(p_palabra!=NULL) { palabra[j++]=CogePalabra(&p_palabra); if(j==MAX_PALABRAS) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("S'ha sobrepassat el nombre de paraules per línia."); else PagesDlg->Memo2->Lines->Add("S'ha sobrepassat el nombre de paraules per línia."); throw 3; } } palabra[j]=""; //Passem la cadena d'AnsiStrings sencera per a analitzar Parse(palabra); } //--------------------------------------------------------------------------- AnsiString TTraductor::CogePalabra(char **p_linea) { //Separa una cadena de caràcters en AnsiStrings int j=0; char *linea=*p_linea; char car=*(linea+j); while((car==' ' || car=='\0' || car=='\t')) //Treu els espais en blanc car=*(++linea); while(!(car==' ' || car=='\n' || car=='\0' || car=='\t')) car=*(linea+j++); *(linea+j-1)='\0'; AnsiString palabra=linea; if(car=='\n') *p_linea=NULL; else *p_linea=linea+j; return palabra; } //--------------------------------------------------------------------------- void TTraductor::Parse(AnsiString palabra[]) { switch(PalabraClave(palabra))

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

107

{ case 0: case 1: case 2: case 3: Entity[PagesDlg->multi].OmplirEntitat(palabra,Noms);break; case 4: ParseNames(palabra); break; case 5: ParseBuff(palabra); break; case 6: ParseDbuff(palabra); break; case 7: ParseEnd(); break; default:ParseBin(palabra); break; } } //--------------------------------------------------------------------------- int TTraductor::PalabraClave(AnsiString palabra[]) { //Retorna index en funció de paraula clau que serà la primera de la línia. // (= Primer element de l'array d'AnsiStrings) if(palabra[0]==".model") return 0; else if(palabra[0]==".inputs") return 1; else if(palabra[0]==".outputs") return 2; else if(palabra[0]==".clock") return 3; else if(palabra[0]==".names") return 4; else if(palabra[0]==".latch") return 5; else if(palabra[0]==".buff") return 5; else if(palabra[0]==".dbuff") return 6; else if(palabra[0]==".end") return 7; else return -1; } //--------------------------------------------------------------------------- void TTraductor::ParseNames(AnsiString palabra[]) { //Creem un element LUT, l'omplim i l'afegim a la llista TLut *Lut= new TLut; Lut->OmplirLut(palabra,Signals,Entity[0],Noms); ListLut[PagesDlg->multi]->Add(Lut); //Indiquem al 'parsebin' a quina LUT correspoenen els valors LutIndex[PagesDlg->multi]++; } //--------------------------------------------------------------------------- void TTraductor::ParseBuff(AnsiString palabra[]) {

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

108

//Creem un element FF, l'omplim i l'afegim a la llista TBuff *Buff=new TBuff; Buff->OmplirBuff(palabra,Signals,Entity[0],Noms); ListBuff[PagesDlg->multi]->Add(Buff); }//--------------------------------------------------------------------------- void TTraductor::ParseDbuff(AnsiString palabra[]) { //Creem un element DFF, l'omplim i l'afegim a la llista TDbuff *Dbuff=new TDbuff; Dbuff->OmplirDbuff(palabra,Signals,Entity[0],Noms); ListDbuff[PagesDlg->multi]->Add(Dbuff); } //--------------------------------------------------------------------------- void TTraductor::ParseEnd() { // No fem res i el programa retornarà el control al fitxer "tabinterface.cpp" } //--------------------------------------------------------------------------- void TTraductor::ParseEnd(AnsiString nom) { //Fem la crida a imprimir al fitxer destí i li passem tots els elements // que hem anat omplint fins arribar al final del codi BLIF int i; FILE *Fout=fopen(nom.c_str(),"w+t"); if (Fout!=NULL) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("Fitxer VHDL obert satisfactoriament"); else PagesDlg->Memo2->Lines->Add("Fitxer VHDL obert satisfactoriament"); } else { if(PagesDlg->multi==0) { PagesDlg->Memo1->Lines->Add("El fitxer VHDL no s'ha pogut obrir"); throw -9; } else { PagesDlg->Memo2->Lines->Add("El fitxer VHDL no s'ha pogut obrir"); throw -9; } } // Imprimim el fitxer Printer.PrintFile(Fout,Entity,ListBuff,ListDbuff,ListLut,Signals); if (!fclose(Fout))

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

109

{ if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("Fitxer VHDL tancat satisfactoriament"); else PagesDlg->Memo2->Lines->Add("Fitxer VHDL tancat satisfactoriament"); } else { if(PagesDlg->multi==0) { PagesDlg->Memo1->Lines->Add("El fitxer VHDL no s'ha pogut tancar"); throw -7; } else { PagesDlg->Memo2->Lines->Add("El fitxer VHDL no s'ha pogut tancar"); throw -7; } } }//--------------------------------------------------------------------------- void TTraductor::ParseEnd_1ctx(AnsiString nom) { //Fem la crida a imprimir al fitxer destí d'un context int i=0; FILE *Fout=fopen(nom.c_str(),"w+t"); if (Fout!=NULL) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("Fitxer VHDL obert satisfactoriament"); else PagesDlg->Memo2->Lines->Add("Fitxer VHDL obert satisfactoriament"); } else { if(PagesDlg->multi==0) { PagesDlg->Memo1->Lines->Add("El fitxer VHDL no s'ha pogut obrir"); throw -9; } else { PagesDlg->Memo2->Lines->Add("El fitxer VHDL no s'ha pogut obrir"); throw -9; } } //Imprimim el fitxer VHDL Printer_1ctx.PrintFile(Fout,Entity[0],ListBuff[0],ListLut[i],Signals); if (!fclose(Fout)) {

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

110

if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add("Fitxer VHDL tancat satisfactoriament"); else PagesDlg->Memo2->Lines->Add("Fitxer VHDL tancat satisfactoriament"); } else { if(PagesDlg->multi==0) { PagesDlg->Memo1->Lines->Add("El fitxer VHDL no s'ha pogut tancar"); throw -7; } else { PagesDlg->Memo2->Lines->Add("El fitxer VHDL no s'ha pogut tancar"); throw -7; } } } //--------------------------------------------------------------------------- void TTraductor::ParseBin(AnsiString palabra[]) { /* Quan una línia no conté cap paraula clau al començament pot ser que: 1. Sigui la continuació d'una llista d'entrades i/o sortides 2. Es tracti del contingut d'una LUT 3. Siguin comentaris o elements no codificats en BLIF */ if ( Entity->chivato>0) { if (Entity->chivato==1) //Les entrades ocupen més d'una línia Entity->ParseInputs(palabra,Noms); else {if (Entity->chivato==2) //Les sortides ocupen més d'una línia Entity->ParseOutputs(palabra,Noms); } } else { //Comprovem que sigui 1,0,- //si ho és ho enviem a la Lut que li correspongui char *aux=palabra[0].c_str(); if ((*aux=='1')||(*aux=='0')||(*aux=='-')) ((TLut*)ListLut[PagesDlg->multi]->Items[LutIndex[PagesDlg->multi]])->ContingutLut(palabra); // En qualsevol altre cas entendrem que és un comentari i no el tindrem en compte // ja que totes les possibles paraules claus han estat analitzades. } }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

111

9.3 Entity.cpp

#include "Entity.h" #include "tabinterface.h" #include "traductor.h" //--------------------------------------------------------------------------- TEntity::TEntity() { Inputs = new TStringList; Outputs = new TStringList; Model = new TStringList; Clock = new TStringList; chivato=0; } //--------------------------------------------------------------------------- TEntity::~TEntity() { } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void TEntity::OmplirEntitat(AnsiString palabra[],TStringList *Noms[]) { if (PagesDlg->multi==0) { // Llegim el contingut de l'entitat només al fitxer BLIF original switch(PalabraClave(palabra)) { case 0: ParseModel(palabra,Noms); break; case 1: ParseInputs(palabra,Noms); break; case 2: ParseOutputs(palabra,Noms); break; case 3: ParseClock(palabra,Noms); break; default: throw -10; } } } //--------------------------------------------------------------------------- int TEntity::PalabraClave(AnsiString palabra[]) { if(palabra[0]==".model") return 0; else if(palabra[0]==".inputs") return 1; else if(palabra[0]==".outputs") return 2; else if(palabra[0]==".clock") return 3; else if(palabra[0]==".names") return 4; else if(palabra[0]==".latch") return 5; else if(palabra[0]==".buff") return 6;

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

112

else if(palabra[0]==".end") return 7; else return -1; } //--------------------------------------------------------------------------- void TEntity::ParseModel(AnsiString palabra[],TStringList *Noms[]) { Model->Add(TestNom(palabra[1],Noms)); } //--------------------------------------------------------------------------- void TEntity::ParseInputs(AnsiString palabra[],TStringList *Noms[]) { int i=0; if (chivato==1) i--; while (palabra[++i]!="") { if (palabra[i]!="\\") { Inputs->Add(TestNom(palabra[i],Noms)); chivato=0; } else chivato=1; // Les entrades ocupen més d'una línia } } //--------------------------------------------------------------------------- void TEntity::ParseOutputs(AnsiString palabra[],TStringList *Noms[]) { int i=0; if (chivato==2) i--; while (palabra[++i]!="") { if (palabra[i]!="\\") { Outputs->Add(TestNom(palabra[i],Noms)); chivato=0; } else chivato=2;// Les sortides ocupen més d'una línia } //--------------------------------------------------------------------------- void TEntity::ParseClock(AnsiString palabra[],TStringList *Noms[]) { int i=0; while (palabra[++i]!="") Clock->Add(TestNom(palabra[i],Noms)); } //---------------------------------------------------------------------------

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

113

AnsiString TEntity::TestNom(AnsiString palabra,TStringList *Noms[]) { // EL VHDL no accepta segons quins caràcters, aquí ho comprovem char *nom=palabra.c_str(); char *actual; actual= new char [25]; int modif=0,j,i=0; j=0; // comprovem que el primer caràcter estigui entre a-z o A-Z /***********************************************************/ if (!(((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if (nom[i]=='*') { actual[0]='B'; actual[1]='u'; actual[2]='f'; actual[3]='f'; j=3; } else { //Si comença per número li assignem una lletra 1=A, 2=B, ... if ( ((int)nom[i]>=48)&& ( (int)nom[i]<=57) ) actual[i+j]= ((int)nom[i])+17; else if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+43; else actual[i+j]='k'; } modif++; } else actual[i+j]=nom[i]; // Fi del primer caràcter /**************************************************************/ while (nom[++i]!='\0') { //comprovem que no hi hagi caracters no acceptats a l'interior de la paraula if (!(((48<=(int)nom[i])&&((int)nom[i]<=57))||(nom[i]=='_')||((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+32; else if ( ((int)nom[i]>=58)&& ( (int)nom[i]<=64) ) actual[i+j]= ((int)nom[i])+22; else if ((int)nom[i]=='[') actual[i+j]='W'; else if ((int)nom[i]=='(') actual[i+j]='X'; else if ((int)nom[i]=='{') actual[i+j]='Y'; else if ((int)nom[i]==92) actual[i+j]='Z'; else { actual[i+j]='_'; modif++;

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

114

} } else actual[i+j]=nom[i]; } if (actual[i+j-1]=='_') actual[i+j-1]='\0'; else actual[i+j]='\0'; // Fins ara tenim nom=nom original i actual=canvi proposat // Anem a assegurar que no posem el mateix nom a dos senyals diferents if ( Noms[0]->IndexOf((AnsiString)nom)<0 ) { Noms[0]->Add((AnsiString)nom); //Comprovem el nom proposat if (Noms[1]->IndexOf((AnsiString)actual)!=-1) { while ((Noms[1]->IndexOf((AnsiString)actual))>=0 ) //Anem modificant fins que no existeixi { actual[i+j]='a'; actual[i+j+1]='\0'; j++; modif++; } Noms[1]->Add((AnsiString)actual); } else Noms[1]->Add((AnsiString)actual); if (modif) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); else PagesDlg->Memo2->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); } } return (AnsiString)actual; }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

115

9.4 Lut.cpp

#include "LUT.h" #include "traductor.cpp" //--------------------------------------------------------------------------- TLut::TLut() { // Look Up Table inicialitzada a 0's array[0]=0; array[1]=0; array[2]=0; array[3]=0; array[4]=0; array[5]=0; array[6]=0; array[7]=0; array[8]=0; array[9]=0; array[10]=0; array[11]=0; array[12]=0; array[13]=0; array[14]=0; array[15]=0; //Entrades inicialitzades a 'nil' EntSor[0]="nil"; EntSor[1]="nil"; EntSor[2]="nil"; EntSor[3]="nil"; //Sortida inicialitzada a 'notused' EntSor[4]="notused"; nom="notused"; } //--------------------------------------------------------------------------- TLut::~TLut() { } //--------------------------------------------------------------------------- void TLut::OmplirLut(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[]) { int i,num; //Mirem quantes entrades té aquesta LUT num=ContaParaules(palabra); // Assignem el camp "nom" de l'objecte. nom=TestNom(palabra[num-1],Noms); for (i=4,num=num-1;num>0;num--,i--)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

116

{ // Començant pel darrera, omplim primer la sortida de la LUT // i després les seves entrades (de dreta a esquerra) // (= de menys a més pes) // Per a LUTs de menys de 4 entrades les lliures tindran el valor de 'nil' EntSor[i]=TestNom(palabra[num],Noms); //Comprovem que siguen senyals ja declarades o senyals primàries if ((Signals->IndexOf(EntSor[i])<0) && (Entity.Inputs->IndexOf(EntSor[i])<0)&& (Entity.Outputs->IndexOf(EntSor[i])<0)) Signals->Add(EntSor[i]); } } //--------------------------------------------------------------------------- int TLut::ContaParaules(AnsiString cadena[]) { // Ens indicarà quantes entrades té aquesta LUT int i=0; while (cadena[i++]!=""); return --i; } //--------------------------------------------------------------------------- void TLut::ContingutLut(AnsiString palabra[]) { // Omplim el contingut de la LUT amb els valors binaris que s'extreuen // del codi BLIF int index; char *name; // Això ho farem tants cops com línies de números "binaris" trobem // després de la declaració d'una LUT name=palabra[0].c_str(); if (strlen(name)>MAX_INT) // Check it has a max lengh of 4bits { // Comprovem que les LUTs no siguin més grans de 4 entrades // aquest és el tamany màxim de les LUTs amb que treballem if(PagesDlg->multi==0) { PagesDlg->Memo1->Lines->Add("S'ha trobat una LUT amb més de 4 entrades"); throw 16; } else { PagesDlg->Memo2->Lines->Add("S'ha trobat una LUT amb més de 4 entrades"); throw 16; } } else Arrange(name); // Comprovem que continguin només 1s i 0s

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

117

} //--------------------------------------------------------------------------- int TLut::BintoDec (char* nom) { // Funció que converteix un número binari "pur" en decimal // entenent per "pur" l'existència de només '1' i '0' // sense el valor '-' int dec = 0; int pow = 1; int length = strlen(nom); // longitud de l'array strrev(nom); // invertim l'array for (int i = 0; i <= length-1; i++) { if (nom[i] == '1') dec += pow; pow <<= 1; // multipiquem per dos } // fi del bucle return dec; } void TLut::Arrange (char* nom) { // En aquesta funció tractem el problema de les entrades "don't care" // que es representen per '-'. // Un número en binari que contingui aquest caràcter no podrà ser convertit // el que fem és crear, a partir d'un binari amb "don't care's" a tants numeros // binaris com facin falta per codificar-lo correctament. // // D'aquesta forma, una entrada com 10-- es convertirà en 1000,1001,10010 i 10011 // char string[MAX_INT+1]; int i=0; int length = strlen(nom); // longitud de l'array for (i=0;i<length;i++) { if ((nom[i]=='1') || (nom[i]=='0')); else { strcpy(string, nom); string[i]='0'; Arrange (string); strcpy(string, nom); string[i]='1'; Arrange (string); } }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

118

array[BintoDec(nom)]=1; } //--------------------------------------------------------------------------- AnsiString TLut::TestNom(AnsiString palabra,TStringList *Noms[]) { // EL VHDL no accepta segons quins caràcters, aquí ho comprovem char *nom=palabra.c_str(); char *actual; actual= new char [25]; int modif=0,j,i=0; j=0; // comprovem que el primer caràcter estigui entre a-z o A-Z /***********************************************************/ if (!(((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if (nom[i]=='*') { actual[0]='B'; actual[1]='u'; actual[2]='f'; actual[3]='f'; j=3; } else { //Si comença per número li assignem una lletra 1=A, 2=B, ... if ( ((int)nom[i]>=48)&& ( (int)nom[i]<=57) ) actual[i+j]= ((int)nom[i])+17; else if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+43; else actual[i+j]='k'; } modif++; } else actual[i+j]=nom[i]; // Fi del primer caràcter /**************************************************************/ while (nom[++i]!='\0') { //comprovem que no hi hagi caracters no acceptats a l'interior de la paraula if (!(((48<=(int)nom[i])&&((int)nom[i]<=57))||(nom[i]=='_')||((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+32; else if ( ((int)nom[i]>=58)&& ( (int)nom[i]<=64) ) actual[i+j]= ((int)nom[i])+22; else if ((int)nom[i]=='[') actual[i+j]='W'; else if ((int)nom[i]=='(') actual[i+j]='X'; else if ((int)nom[i]=='{') actual[i+j]='Y'; else if ((int)nom[i]==92)

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

119

actual[i+j]='Z'; else { actual[i+j]='_'; modif++; } } else actual[i+j]=nom[i]; } if (actual[i+j-1]=='_') actual[i+j-1]='\0'; else actual[i+j]='\0'; // Fins ara tenim nom=nom original i actual=canvi proposat // Anem a assegurar que no posem el mateix nom a dos senyals diferents if ( Noms[0]->IndexOf((AnsiString)nom)<0 ) { Noms[0]->Add((AnsiString)nom); //Comprovem el nom proposat if (Noms[1]->IndexOf((AnsiString)actual)!=-1) { while ((Noms[1]->IndexOf((AnsiString)actual))>=0 ) //Anem modificant fins que no existeixi { actual[i+j]='a'; actual[i+j+1]='\0'; j++; modif++; } Noms[1]->Add((AnsiString)actual); } else Noms[1]->Add((AnsiString)actual); if (modif) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); else PagesDlg->Memo2->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); } } return (AnsiString)actual; }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

120

9.5 Buff.cpp

#include "Buff.h" #include "traductor.cpp" //--------------------------------------------------------------------------- TBuff::TBuff() { Input="notused"; Output="notused"; } //--------------------------------------------------------------------------- TBuff::~TBuff() { } //--------------------------------------------------------------------------- void TBuff::OmplirBuff(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[]) { Input=TestNom(palabra[1],Noms); Output=TestNom(palabra[2],Noms); //Comprovem que siguen senyals ja declarats o senyals primàris if ((Signals->IndexOf(Input)<0) && (Entity.Inputs->IndexOf(Input)<0)&& (Entity.Outputs->IndexOf(Input)<0)) Signals->Add(Input); if ((Signals->IndexOf(Output)<0) && (Entity.Inputs->IndexOf(Output)<0)&& (Entity.Outputs->IndexOf(Output)<0)) Signals->Add(Output); } //--------------------------------------------------------------------------- AnsiString TBuff::TestNom(AnsiString palabra,TStringList *Noms[]) { // EL VHDL no accepta segons quins caràcters, aquí ho comprovem char *nom=palabra.c_str(); char *actual; actual= new char [25]; int modif=0,j,i=0; j=0; // comprovem que el primer caràcter estigui entre a-z o A-Z /***********************************************************/ if (!(((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if (nom[i]=='*') { actual[0]='B'; actual[1]='u';

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

121

actual[2]='f'; actual[3]='f'; j=3; } else { //Si comença per número li assignem una lletra 0=A, 1=B, ... if ( ((int)nom[i]>=48)&& ( (int)nom[i]<=57) ) actual[i+j]= ((int)nom[i])+17; // Als altres possibles caràcters els hi assignem una altra lletra else if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+43; else actual[i+j]='k'; } modif++; } else actual[i+j]=nom[i]; // Fi del primer caràcter /**************************************************************/ while (nom[++i]!='\0') { //comprovem que no hi hagi caracters no acceptats a l'interior de la paraula if (!(((48<=(int)nom[i])&&((int)nom[i]<=57))||(nom[i]=='_')||((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+32; else if ( ((int)nom[i]>=58)&& ( (int)nom[i]<=64) ) actual[i+j]= ((int)nom[i])+22; else if ((int)nom[i]=='[') actual[i+j]='W'; else if ((int)nom[i]=='(') actual[i+j]='X'; else if ((int)nom[i]=='{') actual[i+j]='Y'; else if ((int)nom[i]==92) actual[i+j]='Z'; else { actual[i+j]='_'; modif++; } } else actual[i+j]=nom[i]; } if (actual[i+j-1]=='_') actual[i+j-1]='\0'; else actual[i+j]='\0'; // Fins ara tenim nom=nom original i actual=canvi proposat // Anem a assegurar que no posem el mateix nom a dos senyals diferents if ( Noms[0]->IndexOf((AnsiString)nom)<0 ) { Noms[0]->Add((AnsiString)nom); //Comprovem el nom proposat

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

122

if (Noms[1]->IndexOf((AnsiString)actual)!=-1) { while ((Noms[1]->IndexOf((AnsiString)actual))>=0 ) //Anem modificant fins que no existeixi { actual[i+j]='a'; actual[i+j+1]='\0'; j++; modif++; } Noms[1]->Add((AnsiString)actual); } else Noms[1]->Add((AnsiString)actual); if (modif) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); else PagesDlg->Memo2->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); } } return (AnsiString)actual; }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

123

9.6 Dbuff.cpp

#include "Dbuff.h" #include "traductor.cpp" //--------------------------------------------------------------------------- TDbuff::TDbuff() { Input="notused"; Output="notused"; } //--------------------------------------------------------------------------- TDbuff::~TDbuff() { } //--------------------------------------------------------------------------- void TDbuff::OmplirDbuff(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[]) { Input=TestNom(palabra[1],Noms); Output=TestNom(palabra[2],Noms); //Comprovem que siguen senyals ja declarats o senyals primàris if ((Signals->IndexOf(Input)<0) && (Entity.Inputs->IndexOf(Input)<0)&& (Entity.Outputs->IndexOf(Input)<0)) Signals->Add(Input); if ((Signals->IndexOf(Output)<0) && (Entity.Inputs->IndexOf(Output)<0)&& (Entity.Outputs->IndexOf(Output)<0)) Signals->Add(Output); } //--------------------------------------------------------------------------- AnsiString TDbuff::TestNom(AnsiString palabra,TStringList *Noms[]) { // EL VHDL no accepta segons quins caràcters, aquí ho comprovem char *nom=palabra.c_str(); char *actual; actual= new char [25]; int modif=0,j,i=0; j=0; // comprovem que el primer caràcter estigui entre a-z o A-Z /***********************************************************/ if (!(((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if (nom[i]=='*') { actual[0]='B'; actual[1]='u';

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

124

actual[2]='f'; actual[3]='f'; j=3; } else { //Si comença per número li assignem una lletra 1=A, 2=B, ... if ( ((int)nom[i]>=48)&& ( (int)nom[i]<=57) ) actual[i+j]= ((int)nom[i])+17; else if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+43; else actual[i+j]='k'; } modif++; } else actual[i+j]=nom[i]; // Fi del primer caràcter /**************************************************************/ while (nom[++i]!='\0') { //comprovem que no hi hagi caracters no acceptats a l'interior de la paraula if (!(((48<=(int)nom[i])&&((int)nom[i]<=57))||(nom[i]=='_')||((65<=(int)nom[i])&&((int)nom[i]<=90))||((97<=(int)nom[i])&&((int)nom[i]<=122)))) { if ( ((int)nom[i]>=33)&& ( (int)nom[i]<=47) ) actual[i+j]= ((int)nom[i])+32; else if ( ((int)nom[i]>=58)&& ( (int)nom[i]<=64) ) actual[i+j]= ((int)nom[i])+22; else if ((int)nom[i]=='[') actual[i+j]='W'; else if ((int)nom[i]=='(') actual[i+j]='X'; else if ((int)nom[i]=='{') actual[i+j]='Y'; else if ((int)nom[i]==92) actual[i+j]='Z'; else { actual[i+j]='_'; modif++; } } else actual[i+j]=nom[i]; } if (actual[i+j-1]=='_') actual[i+j-1]='\0'; else actual[i+j]='\0'; // Fins ara tenim nom=nom original i actual=canvi proposat // Anem a assegurar que no posem el mateix nom a dos senyals diferents if ( Noms[0]->IndexOf((AnsiString)nom)<0 ) { Noms[0]->Add((AnsiString)nom); //Comprovem el nom proposat if (Noms[1]->IndexOf((AnsiString)actual)!=-1) {

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

125

while ((Noms[1]->IndexOf((AnsiString)actual))>=0 ) //Anem modificant fins que no existeixi { actual[i+j]='a'; actual[i+j+1]='\0'; j++; modif++; } Noms[1]->Add((AnsiString)actual); } else Noms[1]->Add((AnsiString)actual); if (modif) { if(PagesDlg->multi==0) PagesDlg->Memo1->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); else PagesDlg->Memo2->Lines->Add((AnsiString)nom+" ha canviat per : "+(AnsiString)actual); } } return (AnsiString)actual; }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

126

9.7 Rut_In.cpp

#include "Rut_in.h" #include "traductor.cpp" //--------------------------------------------------------------------------- TRut_in::TRut_in() { Input[0]="notused"; Input[1]="notused"; Output="notused_notused"; } //--------------------------------------------------------------------------- TRut_in::~TRut_in() { } //---------------------------------------------------------------------------

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

127

9.8 Rut_Out.cpp

#include "Rut_out.h" #include "traductor.cpp" //--------------------------------------------------------------------------- TRut_out::TRut_out() { Input="notused_notused"; Output[0]="notused"; Output[1]="notused"; } //--------------------------------------------------------------------------- TRut_out::~TRut_out() { } //---------------------------------------------------------------------------

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

128

9.9 Printer_1ctx.cpp

#include "Printer_1ctx.h" #include "tabinterface.h" #include <math.h> //--------------------------------------------------------------------------- TPrinter_1ctx::TPrinter_1ctx() { } //--------------------------------------------------------------------------- TPrinter_1ctx::~TPrinter_1ctx() { } //--------------------------------------------------------------------------- void TPrinter_1ctx::PrintFile(FILE *Fout,TEntity Entity,TList *ListBuff,TList *ListLut,TStringList *Signals) { PrintEntity(Entity,Fout); PrintArchitecture(Entity,Fout,Signals); PrintBody(Fout,Entity,ListBuff,ListLut); } //--------------------------------------------------------------------------- void TPrinter_1ctx::PrintEntity(TEntity Entity,FILE *Fout) { //Imprimim la capçalera de l'entitat fprintf (Fout,"library ieee;\nuse ieee.std_logic_1164.all;\n\n"); fprintf (Fout,"entity %s is port(\n\t",Entity.Model->Strings[0].c_str()); //Clock if (Entity.Clock->Count>0) fprintf (Fout,"%s,",Entity.Clock->Strings[0].c_str()); else PagesDlg->Memo1->Lines->Add("No hi ha senyal de rellotge."); //Entrades int i; div_t x; for (i=0;i<Entity.Inputs->Count;i++) { x=div(i,7); fprintf(Fout,"%s",Entity.Inputs->Strings[i].c_str()); if (i<Entity.Inputs->Count-1) { if ((i!=0)&&(x.rem==0)) fprintf (Fout,"\t: in STD_LOGIC;\n\t"); else

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

129

fprintf(Fout,","); } else { fprintf (Fout,"\t: in STD_LOGIC;\n\n\t"); } } //Sortides for (i=0;i<Entity.Outputs->Count;i++) { AnsiString nom="OUT_"; x=div(i,7); fprintf(Fout,"%s",nom+=Entity.Outputs->Strings[i].c_str()); nom=""; if (i<Entity.Outputs->Count-1) { if ((i!=0)&&(x.rem==0)) fprintf (Fout,"\t: out STD_LOGIC;\n\t"); else fprintf(Fout,","); } else { fprintf (Fout,"\t: out STD_LOGIC);\n\t"); } } fprintf(Fout,"\n"); fprintf (Fout,"end %s;\n\n",Entity.Model->Strings[0]); //Mostrem informació pel Memo. PagesDlg->Memo1->Lines->Add("Nombre d'entrades: "+(AnsiString)Entity.Inputs->Count); PagesDlg->Memo1->Lines->Add("Nombre de sortides: "+(AnsiString)Entity.Outputs->Count); } //--------------------------------------------------------------------------- void TPrinter_1ctx::PrintArchitecture(TEntity Entity,FILE *Fout,TStringList *Signals) { //Imprimim l'arquitectura fprintf(Fout,"architecture blif2vhdl of %s is\n\n",Entity.Model->Strings[0]); //Components fprintf(Fout,"component LUT generic (Delay:Time; Table_0:STD_LOGIC_VECTOR (0 to 15));\n\t"); fprintf(Fout,"port (in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC);\n"); fprintf(Fout,"end component;\n\n"); fprintf(Fout,"component DFF generic (delay : time);\n\t"); fprintf(Fout,"port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC);\n");

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

130

fprintf(Fout,"end component;\n\n"); //Imprimim senyals auxiliars de sortida primàries fprintf(Fout,"signal "); int i; div_t x; for (i=0;i<Entity.Outputs->Count;i++) { x=div(i,7); fprintf(Fout,"%s",Entity.Outputs->Strings[i].c_str()); if (i<Entity.Outputs->Count-1) { if ((i!=0)&&(x.rem==0)) { fprintf(Fout," : STD_LOGIC :='U';\n"); fprintf(Fout,"signal "); } else fprintf(Fout,","); } else { fprintf(Fout," : STD_LOGIC :='U';\n"); } } //Imprimim senyals no primàries fprintf(Fout,"signal "); for (i=0;i<Signals->Count;i++) { x=div(i,7); fprintf(Fout,"%s",Signals->Strings[i].c_str()); if (i<Signals->Count-1) { if ((i!=0)&&(x.rem==0)) { fprintf(Fout," : STD_LOGIC :='U';\n"); fprintf(Fout,"signal "); } else fprintf(Fout,","); } else { fprintf(Fout," : STD_LOGIC :='U';\n"); } } fprintf(Fout,"\n"); //Constants fprintf(Fout,"constant nil: STD_LOGIC:='0';\n"); fprintf(Fout,"constant none: STD_LOGIC_VECTOR(0 to 15):=\"UUUUUUUUUUUUUUUU\";\n"); fprintf(Fout,"constant Delay:time:=0 ns;\n"); fprintf(Fout,"constant Delay_Lut:time:=0 ns;\n"); fprintf(Fout,"constant Delay_Buff:time:=0 ns;\n");

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

131

//EL CONTINGUTS DE LES LOOK UP TABLES EL TENIM AL BODY!!!! //AIXÍ NO CAL PASSAR TLUT PER PARÀMETRES!! // Infomació sobre senyals al Memo PagesDlg->Memo1->Lines->Add("Nombre de senyals intermitjos: "+(AnsiString)(Signals->Count+Entity.Outputs->Count)); } //--------------------------------------------------------------------------- void TPrinter_1ctx::PrintBody(FILE *Fout,TEntity Entity,TList *ListBuff,TList *ListLut) { int index; //Continguts Look up tables for (int i = 0; i < ListLut->Count; i++) { fprintf(Fout,"\nconstant LUT_%s :\tSTD_LOGIC_VECTOR(0 TO 15):=\"",((TLut*)ListLut->Items[i])->nom); for (index=0;index<pow(2,MAX_INT);index++) fprintf(Fout,"%d",((TLut*)ListLut->Items[i])->array[index]); fprintf(Fout,"\";"); } //Body del programa fprintf(Fout,"\n\n\nBEGIN \n"); //Flip Flops for (int i = 0; i < ListBuff->Count; i++) { fprintf(Fout,"\nDFF_%s : DFF generic map (Delay_Buff)\n\t",((TBuff*)ListBuff->Items[i])->Output); fprintf(Fout,"port map(%s,%s,%s);",Entity.Clock->Strings[0],((TBuff*)ListBuff->Items[i])->Input,((TBuff*)ListBuff->Items[i])->Output); } //LUT's fprintf(Fout,"\n"); int i; for (i = 0; i < ListLut->Count; i++) { fprintf(Fout,"\nLUT_a%s : LUT generic map (Delay_Lut,LUT_%s)\n\t",((TLut*)ListLut->Items[i])->nom,((TLut*)ListLut->Items[i])->nom); fprintf(Fout,"port map("); int j; for (j=0;j<5;j++) { fprintf(Fout,"%s",((TLut*)ListLut->Items[i])->EntSor[j]); if (j<4) fprintf(Fout,","); } fprintf(Fout,");\n");

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

132

} fprintf(Fout, "\n\n"); // Assignem les senyals de sortida auxiliars a les senyals de sortida primàries. for (i=0;i<Entity.Outputs->Count;i++) { AnsiString nom="OUT_"; fprintf(Fout,"\n%s",nom+=Entity.Outputs->Strings[i].c_str()); nom=""; fprintf(Fout,"<=%s;",Entity.Outputs->Strings[i].c_str()); } fprintf(Fout,"\n"); fprintf(Fout,"\n\n\nEND blif2vhdl;"); fprintf(Fout,"\n\n\n --Fitxer generat automàticament amb Tradutor BLIF a VHDL fet per Josep Cid.\n\n\n\n\n"); // Informació al Memo PagesDlg->Memo1->Lines->Add("Nombre de LUT's: "+(AnsiString)ListLut->Count); PagesDlg->Memo1->Lines->Add("Nombre de Flip Flop's: "+(AnsiString)ListBuff->Count); }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

133

9.10 Printer.cpp

#include "Printer.h" #include "tabinterface.h" #include <math.h> //--------------------------------------------------------------------------- TPrinter::TPrinter() { Signals_2ctx= new TStringList; Signals_rut_in= new TStringList; Signals_rut_out= new TStringList; ListLut_2ctx = new TList; ListBuff_2ctx = new TList; ListDbuff_2ctx = new TList; ListRut_in = new TList; ListRut_out = new TList; } //--------------------------------------------------------------------------- TPrinter::~TPrinter() { //CleanBuff_2ctx for (int i = 0; i < ListBuff_2ctx->Count; i++) delete ((TBuff*)ListBuff_2ctx->Items[i]); //CleanDbuff for (int i = 0; i < ListDbuff_2ctx->Count; i++) delete ((TDbuff*)ListDbuff_2ctx->Items[i]); //CleanLut for (int i = 0; i < ListLut_2ctx->Count; i++) delete ((TLut*)ListLut_2ctx->Items[i]); //CleanRut_in for (int i = 0; i < ListRut_in->Count; i++) delete ((TRut_in*)ListRut_in->Items[i]); //CleanRut_out for (int i = 0; i < ListRut_out->Count; i++) delete ((TRut_out*)ListRut_out->Items[i]); delete ListLut_2ctx; delete ListBuff_2ctx; delete ListDbuff_2ctx; delete Signals_2ctx; delete Signals_rut_in; delete Signals_rut_out; delete ListRut_in; delete ListRut_out; } //---------------------------------------------------------------------------

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

134

void TPrinter::PrintFile(FILE *Fout,TEntity Entity[],TList *ListBuff[],TList *ListDbuff[],TList *ListLut[],TStringList *Signals) { CreateLuts_2ctx(ListLut,Signals_2ctx); //Creem les DLUTS CreateBuffs_2ctx(ListBuff,Signals_2ctx); //Creem els Buff's de comunicació CreateDbuffs_2ctx(ListDbuff,Signals_2ctx); //Creem els Dbuffs PrintEntity(Entity,Fout); //Imprimim entitat PrintArchitecture(Entity,Fout,Signals); //Imprimim arquitectura PrintBody(Fout,Entity,ListBuff,ListDbuff,ListLut); //Imprimim cos del programa VHDL CleanEntity(Entity,Signals); //Alliberem memòria de l'entitat } //--------------------------------------------------------------------------- void TPrinter::PrintEntity(TEntity Entity[],FILE *Fout) { //Imprimim la capçalera de l'entitat fprintf (Fout,"library ieee;\nuse ieee.std_logic_1164.all;\n\n"); fprintf (Fout,"entity %s is port(\n\t",Entity[0].Model->Strings[0].c_str()); fprintf (Fout,"ctx,"); //Clock if (Entity[0].Clock->Count>0) fprintf (Fout,"%s,",Entity[0].Clock->Strings[0].c_str()); else PagesDlg->Memo2->Lines->Add("No hi ha senyal de rellotge."); //Entrades int i; div_t x; for (i=0;i<Entity[0].Inputs->Count;i++) { x=div(i,7); fprintf(Fout,"%s",Entity[0].Inputs->Strings[i].c_str()); if (i<Entity[0].Inputs->Count-1) { if ((i!=0)&&(x.rem==0)) fprintf (Fout,"\t: in STD_LOGIC;\n\t"); else fprintf(Fout,","); } else { fprintf (Fout,"\t: in STD_LOGIC;\n\n\t"); } } //Sortides for (i=0;i<Entity[0].Outputs->Count;i++) { AnsiString nom="OUT_"; x=div(i,7);

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

135

fprintf(Fout,"%s",nom+=Entity[0].Outputs->Strings[i].c_str()); nom=""; if (i<Entity[0].Outputs->Count-1) { if ((i!=0)&&(x.rem==0)) fprintf (Fout,"\t: out STD_LOGIC;\n\t"); else fprintf(Fout,","); } else { fprintf (Fout,"\t: out STD_LOGIC);\n\t"); } } fprintf(Fout,"\n"); fprintf (Fout,"end %s;\n\n",Entity[0].Model->Strings[0]); //Mostrem informació pel Memo. PagesDlg->Memo2->Lines->Add("Nombre d'entrades: "+(AnsiString)(Entity[0].Inputs->Count)); PagesDlg->Memo2->Lines->Add("Nombre de sortides: "+(AnsiString)(Entity[0].Outputs->Count)); } //--------------------------------------------------------------------------- void TPrinter::PrintArchitecture(TEntity Entity[],FILE *Fout,TStringList *Signals) { //Imprimim l'arquitectura fprintf(Fout,"architecture blif2vhdl of %s is\n\n",Entity[0].Model->Strings[0]); //Components fprintf(Fout,"component DLUT generic (\n"); fprintf(Fout,"\tDelay:Time;\n"); fprintf(Fout,"\tTable_0:STD_LOGIC_VECTOR (0 to 15);\n"); fprintf(Fout,"\tTable_1:STD_LOGIC_VECTOR (0 to 15));\n"); fprintf(Fout,"port (ctx,in_3, in_2, in_1, in_0 : in STD_LOGIC; S:out STD_LOGIC);\n"); fprintf(Fout,"end component;\n\n"); fprintf(Fout,"component DFF generic (delay : time);\n\t"); fprintf(Fout,"port (clk, entrada : in STD_LOGIC; s:out STD_LOGIC);\n"); fprintf(Fout,"end component;\n\n"); fprintf(Fout,"component BDFF generic (delay : time);\n\t"); fprintf(Fout,"port (\n \t clk, ctx, entrada : in STD_LOGIC; s:out STD_LOGIC);\n"); fprintf(Fout,"end component;\n\n"); fprintf(Fout,"component RUT_IN generic (delay : time);\n\t"); fprintf(Fout,"port (ctx\t:in STD_LOGIC;\n"); fprintf(Fout,"\t in_ctx_0,in_ctx_1\t: in STD_LOGIC;\n"); fprintf(Fout,"\t output\t:out STD_LOGIC\n\t);\n");

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

136

fprintf(Fout,"end component;\n\n"); fprintf(Fout,"component RUT_OUT generic (delay : time);\n\t"); fprintf(Fout,"port (ctx\t:in STD_LOGIC;\n"); fprintf(Fout,"\t out_ctx_0,out_ctx_1\t: out STD_LOGIC;\n"); fprintf(Fout,"\t input\t: in STD_LOGIC\n\t);\n"); fprintf(Fout,"end component;\n\n"); //Imprimim senyals auxiliars de sortides primàries fprintf(Fout,"signal "); int i; div_t x; for (i=0;i<Entity[0].Outputs->Count;i++) { x=div(i,7); fprintf(Fout,"%s",Entity[0].Outputs->Strings[i].c_str()); if (i<Entity[0].Outputs->Count-1) { if ((i!=0)&&(x.rem==0)) { fprintf(Fout," : STD_LOGIC :='U';\n"); fprintf(Fout,"signal "); } else fprintf(Fout,","); } else { fprintf(Fout," : STD_LOGIC :='U';\n"); } } //Imprimim senyals no primàries fprintf(Fout,"signal "); for (i=0;i<Signals->Count;i++) { x=div(i,7); fprintf(Fout,"%s",Signals->Strings[i].c_str()); if (i<Signals->Count-1) { if ((i!=0)&&(x.rem==0)) { fprintf(Fout," : STD_LOGIC :='U';\n"); fprintf(Fout,"signal "); } else fprintf(Fout,","); } else { fprintf(Fout," : STD_LOGIC :='U';\n"); }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

137

} fprintf(Fout,"\n"); //Imprimim senyals no primàries multiplexades fprintf(Fout,"signal "); for (i=0;i<Signals_2ctx->Count;i++) { x=div(i,7); fprintf(Fout,"%s",Signals_2ctx->Strings[i].c_str()); if (i<Signals_2ctx->Count-1) { if ((i!=0)&&(x.rem==0)) { fprintf(Fout," : STD_LOGIC :='U';\n"); fprintf(Fout,"signal "); } else fprintf(Fout,","); } else { fprintf(Fout," : STD_LOGIC :='U';\n"); } } //Constants fprintf(Fout,"\nconstant nil: STD_LOGIC:='0';\n"); fprintf(Fout,"constant none: STD_LOGIC_VECTOR(0 to 15):=\"UUUUUUUUUUUUUUUU\";\n"); fprintf(Fout,"constant Delay:time:=0 ns;\n"); fprintf(Fout,"constant Delay_Lut:time:=0 ns;\n"); fprintf(Fout,"constant Delay_Buff:time:=0 ns;\n"); fprintf(Fout,"constant Delay_Dbuff:time:=0 ns;\n"); fprintf(Fout,"constant Delay_In:time:=0 ns;\n"); fprintf(Fout,"constant Delay_Out:time:=0 ns;\n"); fprintf(Fout,"signal notused:\tSTD_LOGIC :='U';\n"); //EL CONTINGUTS DE LES LOOK UP TABLES EL TENIM AL BODY!!!! //AIXÍ NO CAL PASSAR TLUT PER PARÀMETRES!! // Infomació sobre senyals al Memo PagesDlg->Memo2->Lines->Add("Nombre de senyals intermitjos no multiplexats: "+(AnsiString)(Signals->Count+Entity[0].Outputs->Count)); PagesDlg->Memo2->Lines->Add("Nombre de senyals intermitjos multiplexats: "+(AnsiString)Signals_2ctx->Count); } //---------------------------------------------------------------------------

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

138

void TPrinter::PrintBody(FILE *Fout,TEntity Entity[],TList *ListBuff[],TList *ListDbuff[],TList *ListLut[]) { int index; int ctx; //Continguts Look up tables fprintf(Fout,"constant LUT_notused: STD_LOGIC_VECTOR(0 to 15):=\"UUUUUUUUUUUUUUUU\";\n"); for (ctx=1;ctx<3;ctx++) { for (int i = 0; i < n_luts_2ctx[ctx-1]; i++) { fprintf(Fout,"\nconstant LUT_%s :\tSTD_LOGIC_VECTOR(0 TO 15):=\"",((TLut*)ListLut[ctx]->Items[i])->nom); for (index=0;index<pow(2,MAX_INT);index++) fprintf(Fout,"%d",((TLut*)ListLut[ctx]->Items[i])->array[index]); fprintf(Fout,"\";"); } } //Body del programa fprintf(Fout,"\n\n\nBEGIN \n"); //Flip Flops comunicació for (int i = 0; i < ListBuff_2ctx->Count; i++) { fprintf(Fout,"\nDFF_%s : DFF generic map (Delay_Buff)\n\t",((TBuff*)ListBuff_2ctx->Items[i])->Output); fprintf(Fout,"port map(%s,%s,%s);",Entity[0].Clock->Strings[0],((TBuff*)ListBuff_2ctx->Items[i])->Input,((TBuff*)ListBuff_2ctx->Items[i])->Output); } //Flip Flops doble contexte for (int i = 0; i < ListDbuff_2ctx->Count; i++) { fprintf(Fout,"\nBDFF_%s : BDFF generic map (Delay_Dbuff)\n\t",((TDbuff*)ListDbuff_2ctx->Items[i])->Output); fprintf(Fout,"port map(%s,ctx,%s,%s);",Entity[0].Clock->Strings[0],((TDbuff*)ListDbuff_2ctx->Items[i])->Input,((TDbuff*)ListDbuff_2ctx->Items[i])->Output); } //LUT's fprintf(Fout,"\n"); for (int i = 0; i < ListLut_2ctx->Count; i++) { fprintf(Fout,"\nDLUT_%s : DLUT generic map (Delay_Lut,LUT_%s,LUT_%s)\n\t",((TLut*)ListLut_2ctx->Items[i])->nom,((TLut*)ListLut[1]->Items[i])->nom,((TLut*)ListLut[2]->Items[i])->nom); fprintf(Fout,"port map(ctx,"); int j; for (j=0;j<5;j++) {

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

139

fprintf(Fout,"%s",((TLut*)ListLut_2ctx->Items[i])->EntSor[j]); if (j<4) fprintf(Fout,","); } fprintf(Fout,");"); } fprintf(Fout,"\n"); //Recursos de rutatge IN for (int i = 0; i < ListRut_in->Count; i++) { //Comprovem que no existeixin també com a rut_out. En aquest cas només imprimirem el RUT_OUT if ( (Signals_rut_out->IndexOf( Signals_rut_in->Strings[i] ) ) ==-1) { fprintf(Fout,"\nRUT_IN_%s : RUT_IN generic map (Delay_In)\n\tport map (ctx,",((TRut_in*)ListRut_in->Items[i])->Output); fprintf(Fout,"%s,%s,%s);",((TRut_in*)ListRut_in->Items[i])->Input[0],((TRut_in*)ListRut_in->Items[i])->Input[1],((TRut_in*)ListRut_in->Items[i])->Output); } } fprintf(Fout,"\n"); //Recursos de rutatge OUT int i; for (i = 0; i < ListRut_out->Count; i++) { fprintf(Fout,"\nRUT_OUT_%s : RUT_OUT generic map (Delay_Out)\n\tport map (ctx,",((TRut_out*)ListRut_out->Items[i])->Input); fprintf(Fout,"%s,%s,%s);",((TRut_out*)ListRut_out->Items[i])->Output[0],((TRut_out*)ListRut_out->Items[i])->Output[1],((TRut_out*)ListRut_out->Items[i])->Input); } fprintf(Fout, "\n\n"); // Assignem les senyals de sortida auxiliars a les senyals de sortida primàries. for (i=0;i<Entity[0].Outputs->Count;i++) { AnsiString nom="OUT_"; fprintf(Fout,"\n%s",nom+=Entity[0].Outputs->Strings[i].c_str()); nom=""; fprintf(Fout,"<=%s;",Entity[0].Outputs->Strings[i].c_str()); } fprintf(Fout,"\n\n\nEND blif2vhdl;"); fprintf(Fout,"\n\n\n --Fitxer generat automàticament amb Tradutor BLIF a VHDL fet per Josep Cid.\n\n\n\n\n"); // Informació al Memo PagesDlg->Memo2->Lines->Add("Nombre de LUT's: "+(AnsiString)ListLut_2ctx->Count); PagesDlg->Memo2->Lines->Add("Nombre de Flip Flop's de comunicació: "+(AnsiString)ListBuff_2ctx->Count); PagesDlg->Memo2->Lines->Add("Nombre de Flip Flop's de doble contexte: "+(AnsiString)ListDbuff_2ctx->Count);

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

140

PagesDlg->Memo2->Lines->Add("Nombre de Rut_in: "+(AnsiString)ListRut_in->Count); PagesDlg->Memo2->Lines->Add("Nombre de Rut_out: "+(AnsiString)ListRut_out->Count); } //--------------------------------------------------------------------------- void TPrinter::CreateLuts_2ctx(TList *ListLut[],TStringList *Signals_2tx) { int i,index=0; // Comprovem que tinguem el mateix nombre de LUT's a un contexte i a l'altre // Si no és aixi, els igualem. n_luts_2ctx[0]=0; //Inicialitzem n_luts_2ctx[1]=0; index=((n_luts_2ctx[0]=(ListLut[1]->Count))-(n_luts_2ctx[1]=(ListLut[2]->Count))); if (index!=0) { if (index>0)i=2; else i=1; index=abs(index); while (index>0) { TLut *Lut = new TLut; ListLut[i]->Add(Lut); index--; } } // Creem les Lut's de dos contextes a partir de les anteriors. for (i=0;i<ListLut[1]->Count;i++) { TLut *Lut= new TLut; OmplirLut_2ctx(Lut,ListLut,Signals_2ctx,i); ListLut_2ctx->Add(Lut); } } //--------------------------------------------------------------------------- void TPrinter::CreateBuffs_2ctx(TList *ListBuff[],TStringList *Signals_2tx) { int i,index=0; // Comprovem que tinguem el mateix nombre de Buff's a un contexte i a l'altre // Si no és aixi, els igualem. index=((ListBuff[1]->Count)-(ListBuff[2]->Count)); if (index!=0) { if (index>0)i=2; else i=1; index=abs(index); while (index>0) {

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

141

TBuff *Buff=new TBuff; ListBuff[i]->Add(Buff); index--; } } // Creem els Buff's de dos contextes a partir de les anteriors. for (i=0;i<ListBuff[1]->Count;i++) { TBuff *Buff= new TBuff; OmplirBuff_2ctx(Buff,ListBuff,Signals_2ctx,i); ListBuff_2ctx->Add(Buff); } }//--------------------------------------------------------------------------- void TPrinter::CreateDbuffs_2ctx(TList *ListDbuff[],TStringList *Signals_2tx) { int i,index=0; // Comprovem que tinguem el mateix nombre de Buff's a un contexte i a l'altre // Si no és aixi, els igualem. index=((ListDbuff[1]->Count)-(ListDbuff[2]->Count)); if (index!=0) { if (index>0)i=2; else i=1; index=abs(index); while (index>0) { TDbuff *Dbuff=new TDbuff; ListDbuff[i]->Add(Dbuff); index--; } } // Creem els Dbuff's de dos contextes a partir de les anteriors. for (i=0;i<ListDbuff[1]->Count;i++) { TDbuff *Dbuff= new TDbuff; OmplirDbuff_2ctx(Dbuff,ListDbuff,Signals_2ctx,i); ListDbuff_2ctx->Add(Dbuff); } } //--------------------------------------------------------------------------- void TPrinter::OmplirDbuff_2ctx(TDbuff *Dbuff,TList *ListDbuff[],TStringList *Signals_2ctx,int i) { //Omplim els Dbuff's de dos contextes amb les entrades i sortides multiplexades int j; AnsiString nou_1,nou_2; nou_1=(((TDbuff*)ListDbuff[1]->Items[i])->Input); nou_1+=("_"); nou_1+=(((TDbuff*)ListDbuff[2]->Items[i])->Input);

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

142

Dbuff->Input=nou_1; nou_2=(((TDbuff*)ListDbuff[1]->Items[i])->Output); nou_2+=("_"); nou_2+=(((TDbuff*)ListDbuff[2]->Items[i])->Output); Dbuff->Output=nou_2; //Afegim a la llista de senyals multiplexades, si és que no existeixen ja. if (Signals_2ctx->IndexOf(Dbuff->Input)<0) { Signals_2ctx->Add(Dbuff->Input); } //Recursos de rutatge if (Signals_rut_in->IndexOf(Dbuff->Input)<0) { TRut_in *Rut_in= new TRut_in; Rut_in->Input[0]=(((TDbuff*)ListDbuff[1]->Items[i])->Input); Rut_in->Input[1]=(((TDbuff*)ListDbuff[2]->Items[i])->Input); Rut_in->Output=nou_1; ListRut_in->Add(Rut_in); Signals_rut_in->Add(nou_1); } if (Signals_2ctx->IndexOf(Dbuff->Output)<0) { Signals_2ctx->Add(Dbuff->Output); } //Recursos de rutatge if (Signals_rut_out->IndexOf(Dbuff->Output)<0) { TRut_out *Rut_out= new TRut_out; Rut_out->Output[0]=(((TDbuff*)ListDbuff[1]->Items[i])->Output); Rut_out->Output[1]=(((TDbuff*)ListDbuff[2]->Items[i])->Output); Rut_out->Input=nou_2; ListRut_out->Add(Rut_out); Signals_rut_out->Add(nou_2); } }//--------------------------------------------------------------------------- void TPrinter::OmplirBuff_2ctx(TBuff *Buff,TList *ListBuff[],TStringList *Signals_2ctx,int i) { //Omplim els Buff's de dos contextes amb les entrades i sortides multiplexades int j; AnsiString nou_1,nou_2; nou_1=(((TBuff*)ListBuff[1]->Items[i])->Input); nou_1+=("_");

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

143

nou_1+=(((TBuff*)ListBuff[2]->Items[i])->Input); Buff->Input=nou_1; nou_2=(((TBuff*)ListBuff[2]->Items[i])->Output); nou_2+=("_"); nou_2+=(((TBuff*)ListBuff[1]->Items[i])->Output); Buff->Output=nou_2; //Afegim a la llista de senyals multiplexades, si és que no existeixen ja. if (Signals_2ctx->IndexOf(Buff->Input)<0) { Signals_2ctx->Add(Buff->Input); } //Recursos de rutatge if (Signals_rut_in->IndexOf(Buff->Input)<0) { TRut_in *Rut_in= new TRut_in; Rut_in->Input[0]=(((TBuff*)ListBuff[1]->Items[i])->Input); Rut_in->Input[1]=(((TBuff*)ListBuff[2]->Items[i])->Input); Rut_in->Output=nou_1; ListRut_in->Add(Rut_in); Signals_rut_in->Add(nou_1); } if (Signals_2ctx->IndexOf(Buff->Output)<0) { Signals_2ctx->Add(Buff->Output); } //Recursos de rutatge if (Signals_rut_out->IndexOf(Buff->Output)<0) { TRut_out *Rut_out= new TRut_out; Rut_out->Output[0]=(((TBuff*)ListBuff[2]->Items[i])->Output); Rut_out->Output[1]=(((TBuff*)ListBuff[1]->Items[i])->Output); Rut_out->Input=nou_2; ListRut_out->Add(Rut_out); Signals_rut_out->Add(nou_2); } } //--------------------------------------------------------------------------- void TPrinter::OmplirLut_2ctx(TLut *Lut,TList *ListLut[],TStringList *Signals_2ctx,int i) { //Omplim les LUT's de dos contextes amb les entrades i sortides multiplexades int j; AnsiString nou_1; for (j=0;j<5;j++) { nou_1=(((TLut*)ListLut[1]->Items[i])->EntSor[j]); nou_1+=("_"); nou_1+=(((TLut*)ListLut[2]->Items[i])->EntSor[j]); Lut->EntSor[j]=nou_1;

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

144

//Posem el nom de la LUT if (j==4) Lut->nom=nou_1; //Afegim a la llista de senyals multiplexades, si és que no existeixen ja. if ((Signals_2ctx->IndexOf(Lut->EntSor[j])<0)) { Signals_2ctx->Add(Lut->EntSor[j]); if (j<4) //Omplim recurs de rutatge IN { if ((Signals_rut_in->IndexOf(Lut->EntSor[j])<0)) { TRut_in *Rut_in= new TRut_in; Rut_in->Input[0]=(((TLut*)ListLut[1]->Items[i])->EntSor[j]); Rut_in->Input[1]=(((TLut*)ListLut[2]->Items[i])->EntSor[j]); Rut_in->Output=nou_1; ListRut_in->Add(Rut_in); Signals_rut_in->Add(nou_1); } } if (j==4) //Omplim recurs de rutatge OUT { if ((Signals_rut_in->IndexOf(Lut->EntSor[j])<0)) { TRut_out *Rut_out= new TRut_out; Rut_out->Output[0]=(((TLut*)ListLut[1]->Items[i])->EntSor[j]); Rut_out->Output[1]=(((TLut*)ListLut[2]->Items[i])->EntSor[j]); Rut_out->Input=nou_1; ListRut_out->Add(Rut_out); Signals_rut_out->Add(nou_1); } } } } } //--------------------------------------------------------------------------- void TPrinter::CleanEntity(TEntity Entity[],TStringList *Signals) { // Alliberem la memòria emprada en els objectes Entity. int n=0; for (n=0;n<2;n++) { delete Entity[n].Inputs; delete Entity[n].Outputs; delete Entity[n].Clock; } }

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

145

9.11 Tabinterface.h

//---------------------------------------------------------------------------- #ifndef tabinterfaceH #define tabinterfaceH //---------------------------------------------------------------------------- #include <vcl\ExtCtrls.hpp> #include <vcl\ComCtrls.hpp> #include <vcl\Buttons.hpp> #include <vcl\StdCtrls.hpp> #include <vcl\Controls.hpp> #include <vcl\Forms.hpp> #include <vcl\Graphics.hpp> #include <vcl\Classes.hpp> #include <vcl\SysUtils.hpp> #include <vcl\Windows.hpp> #include <vcl\System.hpp> #include "traductor.h" #include <Dialogs.hpp> //- //---------------------------------------------------------------------------- class TPagesDlg : public TForm { __published: TPanel *Panel1; TPageControl *PageControl1; TTabSheet *TabSheet1; TTabSheet *TabSheet2; TPanel *Panel2; TLabel *Label7; TEdit *Edit4; TEdit *Edit5; TButton *Button1; TPanel *Panel3; TLabel *Label4; TLabel *Label8; TEdit *Edit1; TEdit *Edit2; TButton *Button2; TEdit *Edit3; TPanel *Panel4; TLabel *Label5; TLabel *Label2; TLabel *Label3; TMemo *Memo1; TMemo *Memo2; void __fastcall Button1Click(TObject *Sender); private: TTraductor *Traductor; void __fastcall ArrangeParam(void); void __fastcall ExeSoftware(void); public:

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

146

int multi; virtual __fastcall TPagesDlg(TComponent* AOwner); virtual __fastcall ~TPagesDlg(void); }; //---------------------------------------------------------------------------- extern PACKAGE TPagesDlg *PagesDlg; //---------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

147

9.12 Traductor.h

//--------------------------------------------------------------------------- #ifndef traductorH #define traductorH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "LUT.h" #include "Entity.h" #include "Printer.h" #include "Printer_1ctx.h" #include "Buff.h" #include "Dbuff.h" #include <stdio.h> #include <io.h> #define MAX_PALABRAS 5000 //--------------------------------------------------------------------------- class TTraductor { private: TStrings *Lineas[3]; TList *ListLut[3]; TList *ListBuff[3]; TList *ListDbuff[3]; int LutIndex[3]; TStringList *Signals; FILE *Handler; TPrinter Printer; TPrinter_1ctx Printer_1ctx; TEntity Entity[2]; AnsiString CogePalabra(char**); void Parse(char*); void Parse(AnsiString[]); void ParseNames(AnsiString palabra[]); void ParseBuff(AnsiString palabra[]); void ParseDbuff(AnsiString palabra[]); void ParseBin(AnsiString palabra[]); void ParseEnd(void); int PalabraClave(AnsiString palabra[]); public: TTraductor(); ~TTraductor(); //void OpenFile(char *fitxer="adder2.bli");

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

148

void OpenFile(char *fitxer); void CloseFile(void); void Parse(void); void LeerFichero(); void ParseEnd(AnsiString nom); void ParseEnd_1ctx(AnsiString nom); TStringList *Noms[2]; }; //--------------------------------------------------------------------------- extern TTraductor Traductor; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

149

9.13 Entity.h

//--------------------------------------------------------------------------- #ifndef EntityH #define EntityH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include <io.h> //--------------------------------------------------------------------------- class TEntity { private: int PalabraClave(AnsiString palabra[]); AnsiString TestNom(AnsiString palabra,TStringList *Noms[]); void ParseModel(AnsiString palabra[],TStringList *Noms[]); void ParseClock(AnsiString palabra[],TStringList *Noms[]); public: void ParseInputs(AnsiString palabra[],TStringList *Noms[]); void ParseOutputs(AnsiString palabra[],TStringList *Noms[]); int chivato;//Indicarà inputs o outputs de més d'una linia TStringList *Inputs; TStringList *Outputs; TStringList *Model; TStringList *Clock; TEntity(); ~TEntity(); void OmplirEntitat(AnsiString palabra[]); void OmplirEntitat(AnsiString palabra[],TStringList *Noms[]); }; //--------------------------------------------------------------------------- extern TEntity Entity; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

150

9.14 Lut.h

//--------------------------------------------------------------------------- #ifndef LUTH #define LUTH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include <io.h> #include "Entity.h" #define MAX_INT 4 //--------------------------------------------------------------------------- class TLut { private: int ContaParaules(AnsiString cadena[]); AnsiString TestNom(AnsiString palabra,TStringList *Noms[]); int BintoDec (char* nom); void Arrange (char* nom); public: TLut(); ~TLut(); AnsiString nom; AnsiString EntSor[6]; int array[16]; // Look Up Table void OmplirLut(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[]); void ContingutLut(AnsiString palabra[]); }; //--------------------------------------------------------------------------- extern TLut Lut; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

151

9.15 Buff.h

//--------------------------------------------------------------------------- #ifndef buffH #define buffH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include <io.h> #include "Entity.h" //--------------------------------------------------------------------------- class TBuff { private: AnsiString TestNom(AnsiString palabra,TStringList *Noms[]); public: TBuff(); ~TBuff(); AnsiString Input; AnsiString Output; void OmplirBuff(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[]); }; //--------------------------------------------------------------------------- extern TBuff Buff; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

152

9.16 Dbuff.h

//--------------------------------------------------------------------------- #ifndef DbuffH #define DbuffH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include <io.h> #include "Entity.h" //--------------------------------------------------------------------------- class TDbuff { private: AnsiString TestNom(AnsiString palabra,TStringList *Noms[]); public: TDbuff(); ~TDbuff(); AnsiString Input; AnsiString Output; void OmplirDbuff(AnsiString palabra[],TStringList *Signals,TEntity Entity,TStringList *Noms[]); }; //--------------------------------------------------------------------------- extern TDbuff Dbuff; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

153

9.17 Rut_In.h

//--------------------------------------------------------------------------- #ifndef rut_inH #define rut_inH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include <io.h> //--------------------------------------------------------------------------- class TRut_in { private: public: TRut_in(); ~TRut_in(); AnsiString Input[2]; AnsiString Output; }; //--------------------------------------------------------------------------- extern TRut_in Rut_in; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

154

9.18 Rut_Out.cpp

//--------------------------------------------------------------------------- #ifndef rut_outH #define rut_outH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <stdio.h> #include <io.h> //--------------------------------------------------------------------------- class TRut_out { private: public: TRut_out(); ~TRut_out(); AnsiString Input; AnsiString Output[2]; }; //--------------------------------------------------------------------------- extern TRut_out Rut_out; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

155

9.19 Printer_1ctx.h

//--------------------------------------------------------------------------- #ifndef Printer_1ctxH #define Printer_1ctxH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "Entity.h" //--------------------------------------------------------------------------- class TPrinter_1ctx { private: void PrintEntity(TEntity Entity,FILE *Fout); void PrintArchitecture(TEntity Entity,FILE *Fout,TStringList *Signals); void PrintBody(FILE *Fout,TEntity Entity,TList *ListBuff,TList *ListLut); public: void PrintFile(FILE *Fout,TEntity Entity,TList *ListBuff,TList *ListLut,TStringList *Signals); TPrinter_1ctx(); ~TPrinter_1ctx(); }; //--------------------------------------------------------------------------- extern TPrinter_1ctx Printer_1ctx; //--------------------------------------------------------------------------- #endif

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

156

9.20 Printer.h

//--------------------------------------------------------------------------- #ifndef PrinterH #define PrinterH //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "Entity.h" #include "Lut.h" #include "Buff.h" #include "Dbuff.h" #include "Rut_in.h" #include "Rut_out.h" //--------------------------------------------------------------------------- class TPrinter { private: void PrintEntity(TEntity Entity[],FILE *Fout); void PrintArchitecture(TEntity Entity[],FILE *Fout,TStringList *Signals); void PrintBody(FILE *Fout,TEntity Entity[],TList *ListBuff[],TList *ListDbuff[],TList *ListLut[]); void CleanEntity(TEntity Entity[],TStringList *Signals); void CreateLuts_2ctx(TList *ListLut[],TStringList *Signals_2tx); void CreateBuffs_2ctx(TList *ListBuff[],TStringList *Signals_2tx); void CreateDbuffs_2ctx(TList *ListDbuff[],TStringList *Signals_2tx); void OmplirLut_2ctx(TLut *Lut,TList *ListLut[], TStringList *Signals_2ctx,int i); void OmplirBuff_2ctx(TBuff *Buff,TList *ListBuff[], TStringList *Signals_2ctx,int i); void OmplirDbuff_2ctx(TDbuff *Dbuff,TList *ListDbuff[], TStringList *Signals_2ctx,int i); int n_luts_2ctx[2]; TList *ListRut_in; TList *ListRut_out; TList *ListLut_2ctx; TList *ListBuff_2ctx; TList *ListDbuff_2ctx; TStringList *Signals_2ctx; TStringList *Signals_rut_in; TStringList *Signals_rut_out; public:

Josep Cid Prades Traductor BLIF-VHDL P.F.C.

157

void PrintFile(FILE *Fout,TEntity Entity[],TList *ListBuff[],TList *ListDbuff[],TList *ListLut[],TStringList *Signals); TPrinter(); ~TPrinter(); }; //--------------------------------------------------------------------------- extern TPrinter Printer; //--------------------------------------------------------------------------- #endif