LOGISIM NAAR VERILOG VERTALER
Bachelor eindwerk
Promotor: Prof. Hans Vangheluwe
Auteur:
Naomi Christis
Academiejaar 2010-2011
Begeleider: Bart Meyers
Logisim naar Verilog vertaler Universiteit van Antwerpen Naomi Christis Rolnr 20082199
[email protected] Academiejaar 2010-2011
Contents Dankwoord . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 3
1 Introductie 1.1 Omschrijving project . . . . . . . . . . . . . . . . . . . . . . . 1.2 Benodigdheden . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Werkwijze en gebruikte programmeertechnieken . . . . . . . .
4 4 5 5
2 Vertaler 2.1 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Verschillende iteraties . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Eerste stadium: and, or, not gates & wires . . . . . . 2.2.2 Tweede stadium: tunnels . . . . . . . . . . . . . . . . 2.2.3 Derde stadium: input, output, probe, clock, constante & remaining gates . . . . . . . . . . . . . . . . . . . . 2.2.4 Vierde stadium: plexers, except priorityEncoder . . . 2.2.5 Vijfde stadium: arithmetic . . . . . . . . . . . . . . . 2.2.6 Zesde stadium: priority encoder & bit extender & input & output (led, joystick, . . . ) . . . . . . . . . . . . 2.2.7 Zevende stadium: flipflop . . . . . . . . . . . . . . . . 2.2.8 Achtste stadium: abstractRegister & random . . . . . 2.2.9 Negende stadium: ram, rom & shiftregister . . . . . . 2.2.10 Tiende stadium: pull resistor . . . . . . . . . . . . . . 2.2.11 Elfde stadium: importeren van circuits . . . . . . . . . 2.2.12 Twaalfde stadium: splitter . . . . . . . . . . . . . . .
7 7 8 8 12
21 23 24 24 25 26 27
3 Checks
30
4 Conclusie
33
5 Klassediagrammen 5.1 Annotated Classes . 5.2 Intermediate Classes 5.3 Visitor Classes . . . 5.4 Verilog Classes . . .
. . . .
. . . .
. . . .
. . . .
. . . . 1
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
13 17 19
34 34 37 42 44
Dankwoord Dit werk kon slechts tot stand komen dankzij de steun en hulp van een aantal mensen. Mijn erkentelijkheid gaat uit naar mijn promotor, Professor Hans Vangheluwe, voor het aanreiken van het onderwerp en het geven van richtlijnen. Daarnaast ook een woord van dank aan mijn begeleider, Bart Meyers, voor zijn opmerkingen en zijn begeleiding bij de uitwerking van mijn project. Zonder hen was deze scriptie nooit tot stand gekomen. Verder wil ik mijn collega-studenten bedanken voor hun steun, suggesties en uitleg bij bepaalde kwesties. En natuurlijk wil ik ook nog mijn zus en mijn ouders bedanken voor hun luisterend oor en hun niet aflatende morele steun gedurende het voorbije jaar.
2
Abstract Voor u ligt het werkstuk dat ik heb geschreven in het kader van de ontwikkeling van een Logisim-Verilog-vertaler. Dankzij deze Logisim-Verilog-vertaler wordt het mogelijk om Logisimcircuits om te zetten in Verilogcode. Bovendien wordt het met deze vertaler heel wat eenvoudiger om Logisimcircuits semantisch te testen omdat dit dan kan verlopen via Verilogtestbenches. En, last but not least, dankzij deze vertaler kunnen de structurele / syntactische eigenschappen van een Logisimontwerp makkelijker geverifieerd worden.
3
Chapter 1
Introductie 1.1
Omschrijving project
Logisim en Verilog zijn hardware description languages. Ze maken het mogelijk logische circuits te simuleren. Logisim maakt hiervoor gebruik van een grafische benadering, terwijl Verilog een echte programmeertaal is. Er dient een geschikt testingsysteem ontworpen te worden voor de Logisimcircuits. Bij het tekenen van een Logisimmodel, zorgt de modelomgeving er voor dat er een paar beperkingen zijn (zodat de modellen zinvol zijn). Dit is de syntax directed editing. Deze geeft ondermeer aan dat de uitgang van een link en de ingang van diezelfde link eenzelfde grootte van bit moeten hebben. Maar enkel syntactische checks van Logisim volstaan niet. Het is noodzakelijk dat meerdere beperkingen kunnen gedefinieerd worden. Problem specific tests dienen ingebouwd te worden, zodat bepaalde eigenschappen van het circuit kunnen getoetst worden. Een voorbeeld hiervan is dat wanneer er een memory object aanwezig is dewelke een clock vereist, er wordt nagegaan of deze clock ook effectief voorhanden is. Bijkomend moet er een check worden uitgevoerd of beide elementen effectief transitief geconnecteerd zijn, met andere woorden of de clock verbonden is met het memory object. Een ander voorbeeld van een problem specific test is de controle van de aanwezigheid van bepaalde elementen. Deze elementen hoeven niet allemaal verbonden te zijn. De bedoeling is enkel om bijvoorbeeld te testen hoeveel buffer elementen (die bv allemaal 1 bit groot moeten zijn) er voorhanden zijn. Ook de semantiek van een circuit moet getest kunnen worden. Hiervoor wordt meestal gebruik gemaakt van testbenches. Echter, Logisim werkt enkel op Gate Level, en dit is niet het gepaste niveau van abstractie voor een testbench. Daarom is er behoefte aan de vertaler. De vertaalde
4
Verilogbestanden en hun testbenches kunnen dan de semantische checks voor hun rekening nemen. Onderzoek naar een soortgelijk vertaalprogramma, om daaruit eventueel wat inspiratie op te doen, leverde niets op. Publicaties rond dit onderwerp waren niet terug te vinden.
1.2
Benodigdheden
Alvorens het echte werk kon worden aangevat, diende Python 3.x nog ge¨ınstalleerd en gecompileerd te worden. Dit pakket was namelijk niet ter beschikking in Ubuntu. Verder moest eveneens IVerilog1 , Gtkwave en Logisim 2.6.12 ge¨ınstalleerd worden. Bovendien was het een vereiste om vertrouwd te zijn met Python (een “nieuwe” taal) en moest de aanwezige latente kennis van Verilog en Logisim worden opgefrist.
1.3
Werkwijze en gebruikte programmeertechnieken
Er werd voor geopteerd om, als programmeertechniek, iteratieve ontwikkeling in combinatie met TDD (test driven development) te gebruiken. Bij iteratieve ontwikkeling wordt aan de hand van releases (die na enkele weken klaar moeten zijn) gewerkt. Elke release dient afgewerkt te worden tot op het eind. Pas daarna kan met een volgende release gestart worden. Deze vorm van programmeren bleek voor dit project veel voordeliger te zijn dan bijvoorbeeld het watervalmodel. De iteratieve techniek gaf een beter zicht op de stand van zaken en dankzij TDD konden een aantal fouten vroegtijdig worden opgespoord. Voor het testen werden Unittesten (en de testsuites van Python) gebruikt en regressie testen, dewelke zoveel mogelijk werden geschreven voorafgaand aan de code. Zodoende hingen de testen niet af van de code maar waren ze al opgesteld autonoom van het geschreven werk, en was het vrijwel zeker dat het project foutloos zou werken. Al de testen voldoen aan de vereisten voor een goede testcase: 1 2
http://iVerilog.icarus.com/ http://ozark.hendrix.edu/~burch/Logisim/
5
1. De testen kunnen op zichzelf lopen (zonder dat er input aan gegeven moet worden). 2. De testen bepalen zelf of ze geslaagd zijn of niet. 3. Elke test loopt onafhankelijk van de andere testen. 4. Alle eisen waaraan het programma moet voldoen, zijn getest in een testcase. In totaal werden er voor 65 .circ bestanden testen geschreven.
6
Chapter 2
Vertaler 2.1
Design
Vertrekpunt in de realisatie van de vertaling is de XML-boom (= voorstelling Logisimcircuit). Aan de hand van deze boom wordt er een intermediaire boom geconstrueerd (hiervoor gebruiken we de klasse intermediateBuilder: zie 5.2), dewelke wordt overlopen met een aantal visitors. De eerste visitor, de naming visitor, ziet erop toe dat elke component in een circuit een unieke naam krijgt. Nadat de naming visitor de boom doorlopen heeft, kan de check visitor, die bepaalde eigenschappen nakijkt, nog een keer de intermediaire boom afgaan. In de volgende stap van het vertalingproces doorkruist de translator visitor nogmaals de intermediaire boom en vervaardigt een Verilogboom. Deze laatste wordt dan op zijn beurt doorlopen met een write visitor, waarna de Verilogboom kan worden weggeschreven naar .v-bestanden.
Logical Checks
Logisim File
Reading
Naming & Translating
Logisim Abstract Syntax Tree
Verilog Abstract Syntax Tree
Figure 2.1: De workflow van het project.
7
Writing
Verilog File
2.2 2.2.1
Verschillende iteraties Eerste stadium: and, or, not gates & wires (tot midden februari)
Omschrijving Voor er effectief gestart kan worden, dient onderzocht te worden welke XMLParser kan gebruikt worden en wat de structuur is van de XML-Tree van Logisim. Verder moet er nu ook worden beslist hoe de intermediaire boom wordt opgebouwd. Er dient gekozen te worden tussen: 1. E´en allesomvattende klasse, waarbij de typering van de component in een apart veld wordt bewaard (minpunt: gevaar voor Godklasse) 2. Diverse aparte klassen. Optie twee krijgt de voorkeur omdat hierbij element specifieke methodes of variabelen kunnen gedefinieerd worden. Ook een circuitklasse moest worden voorzien (zie 5.2). Deze kan bijhouden welke elementen er aanwezig zijn en hoe deze met elkaar verbonden zijn (omdat alle onderdelen met elkaar geconnecteerd kunnen zijn, gaat het hier eigenlijk eerder om een intermediaire graaf dan om een tree). Na het aanmaken van de circuitklassen en gateklassen, moet er worden nagegaan hoe de co¨ ordinaten van de poorten kunnen berekend worden. Logisim heeft namelijk geen concept van “connectivity” tussen elementen, maar hanteert het concept van locatie. Logisim bewaart dus enkel de locatie van elementen en wires en geeft de manier waarop de elementen met elkaar verbonden zijn niet weer. Ook bewaart Logisim telkens maar 1 locatie per element. Bij de gates is dit de locatie van de output pin, zodat de input co¨ ordinaten zelf berekend moeten worden. Bij deze calculatie dient rekening gehouden met het aantal inputs, alsook met welke daarvan negated zijn. Ook de facing en de grootte van het componentblokje spelen hier een rol.
8
Figure 2.2: Enkel de co¨ ordinaten waaruit de rode lijn vertrekt, worden bewaard in het XML formaat. En dan start de zoektocht naar hoe de wires gelinkt kunnen worden. Een struikelsteen is dat wanneer een wire een hoek maakt, of onderbroken wordt, dit als een aparte wire wordt opgeslagen. En het pad van de wire blijkt ook zeer moeilijk te volgen (omdat Logisim de co¨ordinaten opslaat aan de hand van hun ligging ipv aan de hand van de afgelegde weg). Bij de zoektocht naar een geschikt algoritme, werd de sourcecode van Logisim geraadpleegd. Echter dit leverde totaal niets op. De Logisim-sourcecode is zeer slecht, om niet te zeggen zo goed als niet, gedocumenteerd. Bijgevolg wordt er voor geopteerd om telkenmale vanuit de output van nodes te vertrekken en van daaruit de wires te verbinden. Het verbinden van de wires is een gigantische opdracht. Opgelet, in voorgaande stappen wordt bij het doorlopen van de XML een intermediaire voorstelling van een component aangemaakt. Bovendien dient de AnnotatedElementFactory de bijpassende annotatedKlasse terug te geven. Er wordt hievoor gebruik gemaakt van een factory omdat deze de relatief uitgebreidde logica, die nodig is voor het aanmaken van anotated elementen, scheidt van de code waarmee de boom wordt opgebouwd. Een volgende stap in het project is de voorstelling van de gates in een Verilogtree. Omdat de Verilogtree een abstract syntax tree is, waarin de te annoteren Verilogcode opgebouwd staat, is er o.a. nood aan de vermelding van een modulenaam, van de parameters die gedefinieerd dienen te worden, enz. Testen Voor elke iteratie wordt steeds op de 3 onderdelen getest. Eerst wordt de test gemaakt voor de intermediaire boom en wordt de implementatie voor deze boom ontworpen. Nadien wordt de test voor de verilogboom en de implementatie ervoor ontwikkeld. Afsluitend wordt er getest of de gegenereerde .v bestanden naar behoren werken. Deze testcyclus wordt bij elke iteratie hernomen.. 9
Wat hier specifiek wordt getest, is: 1. of de wires goed worden verbonden 2. of de co¨ ordinaten van de gates goed worden berekend 3. het aantal inputs 4. de vorm van het pad van de wires 5. de verschillende combinaties van negated inputs 6. de grootte van de componenten Voorbeeld LogisimCircuit:
Het Logisim circuit wordt aan de hand van de IntermediateBuilder (zie 5.2) in een intermediaire boom omgezet: Objecten (vereenvoudigd) <1> Wire -> start = None -> stop = <5> -> direction = None -> name = None <2> Wire -> start = None -> stop = <5> -> direction = None -> name = None <3> Wire -> start = <5> -> stop = <6> -> direction = None -> name = None <4> Wire -> start = <6> -> stop = None -> direction = None -> name = None 10
<5> AndGate -> inputWires = [ <1>, <2> ] -> bits = 1 -> outputWire = [ <3> ] -> name = None <6> NotGate -> inputWires = [ <3> ] -> bits = 1 -> outputWire = [ <4> ] -> name = None <7> Circuit -> connectionList = [ <1>, <2>, <3>, <4> ] -> nodeList = [ <5>,<6> ] -> name = main <8> IntermediateTree -> circuitList = [ <7> ] Op deze boom worden de visitors losgelaten. Er worden onder meer een aantal checks gedraaid. De naming visitor, die op de boom wordt losgelaten, zorgt ervoor dat elke component een unieke naam krijgt. Daarna wordt de translator visitor op de intermediaire boom losgelaten en wordt de Verilog boom vervaardigd. Objecten (vereenvoudigd) <1> Wire -> bits = 1 -> value = "empty" -> name = wire1 <2> Wire -> bits = 1 -> value = "empty" -> name = wire2 <3> Wire -> bits = 1 -> value = None -> name = wire3 <4> Wire -> bits = 1 -> value =None -> name = wire4 <5> AndGate -> inputs = [ <1>, <2> ] -> output = <3> -> name = gate0 <6> NotGate 11
-> -> -> <7> Module -> -> -> -> -> -> ->
inputs = [ <3> ] output = <4> name = gate1 inputList = [ ] outputList = [ ] gateList = [ <5>, <6> ] netList = [ <1>, <2>, <3>, <4> ] parameterList = [ ] statementList = [ ] name = main
De Verilog boom wordt in de laatste stap van het vertalingsproces doorlopen door de write visitor. Deze zorgt ervoor dat de Verilog boom wordt uitgeschreven naar files.
2.2.2
Tweede stadium: tunnels (tot einde februari)
Omschrijving Tunnels zijn een variant van wires. Het verschilpunt tussen beiden is dat de lijn, die een wire voorstelt, bij een tunnel niet expliciet wordt afgebeeld. Het voordeel hiervan is dat bij een grote massa wires, het risico op klittende (onontwarbare) wires vermeden wordt. Bij tunnels wordt, door middel van labels, duidelijk aangegeven welke tunnel met welke andere tunnel verbonden is.
Figure 2.3: De tunnel vertoont hetzelfde gedrag als een wire.
12
Voor het functioneren van het algoritme is het belangrijk om achteraf de tunnels om te zetten in wires. Omdat het op punt stellen van de wires reeds voltooid is, dient er verder niets meer te gebeuren voor deze iteratie. Testen Voornamelijk speciale gevallen: 1. wat gebeurt er wanneer er een tunnel is zonder label 2. wat gebeurt er als er maar 1 tunnel van een bepaald label aanwezig is 3. worden de tunnels ook effectief als wires beschouwd
2.2.3
Derde stadium: input, output, probe, clock, constante & remaining gates (tot einde maart)
Omschrijving Allereerst dient er verder gewerkt te worden aan de gates. Al de remaining gates (uitgezonderd odd en even parity) vereisen immers extra modules. Het is essentieel deze extra modules te ontwerpen aangezien slechts enkele Logisimelementen ook een gepredefinieerde versie hebben in Verilog. Zelfs voor een simpele controlled buffer dient een extra module te worden geschreven. Verilog heeft wel de functie ‘bufif0’ maar deze functie neemt enkel 1 bit wires aan, wat doorgaans ontoereikend is. Wel kan de ‘bufif0, bufif1, notif1’ van Verilog worden gebruikt:
Figure 2.4: De Verilog code voor een controlled inverter, waarvan de in- en outputs bit breedte 2 is. Bij odd en even parity kan gebruik worden gemaakt van de exclusive or van Verilog. Voor de xor en xnor dienen extra modules gedefinieerd te worden, deze modules tellen het aantal hoge signalen op en controleren of de som 13
gelijk is aan 1 of niet. In deze release dienen eveneens reeds de delays in overweging genomen te worden. In de Logisimdocumentatie staat hieromtrent: “Every component has a delay associated with it. More sophisticated components built into Logisim tend to have larger delays, but these delays are somewhat arbitrary and may not reflect reality.” Omdat hieruit duidelijk blijkt dat Logisim niet consistent omgaat met zijn delays, is het aangewezen ze niet te voorzien. Voorbeeld (Voor uitleg zie 2.2.1) LogisimCircuit:
Intermediaire boom: Objecten (vereenvoudigd) <1> Wire -> start = <4> -> stop = <6> -> direction = None -> name = None <2> Wire -> start = <5> -> stop = <6> -> direction = None -> name = None <3> Wire -> start = <6> -> stop = <7> -> direction = None -> name = None <4> ClockBase -> inputWires = None -> bits = 1 -> highDuration = 1 -> lowDuration = 1 -> outputWire = [ <1> ] -> name = None <5> ConstantBase 14
<6>
<7>
<8>
<9>
-> inputWires = None -> bits = 2 -> value = "3" -> outputWire = [ <2> ] -> name = None ControlledInverterGate -> inputWires = [ <2> ] -> controlLine = <1> -> bits = 2 -> outputWire = [ <3> ] -> name = None OutputBase -> inputWire = [ <3> ] -> bits = 2 -> outputWire = None -> name = None Circuit -> connectionList = [ <1>, <2>, <3> ] -> nodeList = [ <4>, <5>, <6>, <7> ] -> name = main IntermediateTree -> circuitList = [ <8> ]
Verilog boom: Objecten (vereenvoudigd) <1> Wire -> bits = 2 -> value = None -> name = wire1 <2> Clock -> highDuration = 1 -> lowDuration = 1 -> name = clock0 <3> Constant -> value = "3" -> bits = 2 -> name = constant0 <4> ControlledBufferGate -> inputs = <3> -> controlLine = <2> -> output = <1> -> name = gate0 <5> OutputRegister -> bits = 2 15
-> connectedWire = <1> -> name = out0 <6> Module -> inputList = [ ] -> outputList = [ <5> ] -> gateList = [ <4>] -> netList = [ <1> ] -> parameterList = [ <2>, <3> ] -> statementList = [ ] -> name = main Verilog file:
Testen De intermediateBuilder tests zijn gelijkaardig aan de testen in het eerste stadium. Nazien: 1. of de controlInput juist wordt gezet (is aparte input, die niet gewoon bij de inputWires wordt gerekend) 16
2. of al de extra waarden (zoals bv de value in de constanteBase) juist worden ingevuld De testen voor de gegenereerde Verilog files zijn uitgebreider. Vermits het zeker moet zijn dat de gemaakte extra modules hun werk naar behoren verrichten. Voor elke extra gedefinieerde module wordt daarom een testbench gemaakt. Daarenboven wordt elke extra module heel grondig nagekeken.
2.2.4
Vierde stadium: plexers, except priorityEncoder (tot begin april)
Het algoritme Tot hiertoe was het niet mogelijk dat de wires konden botsen. Maar omdat het botsen een vereiste is, dienen er een aantal aanpassingen te worden doorgevoerd. Wanneer 2 wires botsen (dus allebei een signaal dragen en in elkaar overlopen), wordt een extra wire aangemaakt vanaf het botspunt. Deze extra wire krijgt de andere twee wires dan als input gevoerd.
Figure 2.5: Colliding wires met hun verschillende output mogelijkheden.
Figure 2.6: Verilog code voor 2 inputs die verbonden zijn via een colliding wire met een output. In deze run wordt geen Priority encoder gemaakt. Deze hoort helemaal niet bij de plexers. De enige overeenkomst tussen een Priority encoder en plexers is dat de Priority encoder een select line heeft. Echter de select line van de Priority encoder is geen input, maar een output. Evenmin “plexed” de Priority encoder iets van een input.
17
Bij de plexers is het belangrijk dat van elke in- of output het nummer wordt bijgehouden Aan de hand van dit nummer dient immers in de selectLine de juist in- of output geselecteerd te worden. Er worden daarom twee nieuwe klassen gemaakt: de numberedInput en de numberedOutput (zie 5.2). Deze nieuwe klassen houden dus het nummer bij, alsook de connectie waarmee de in- of output verbonden is.
Figure 2.7: De bovenste input wire zal het nummer 0 meekrijgen en de onderste het nummer 2. Een volgende stap is het maken van de hulpmodules in Verilog (vermits ook plexers niet vooraf gedefinieerd zijn in Verilog). Dankzij het uitschrijven van deze extra modules wordt de juiste input (multiplexer) of output (demultiplexer en decoder) geselecteerd aan de hand van het nummer dat in de selectLine wordt gelezen. Tijdens deze run dient ook aan refactoring gedaan te worden. Tegelijkertijd wordt er gebruik gemaakt van het factory pattern om de nodige annotated-x terug te geven. Indien er geen factory pattern wordt gebruikt, dient in de code waar we de annotated-x gemaakt, nagekeken te worden wat het type van x is. Deze verantwoordelijkheid is typisch voor een factory. Testen 1. Nakijken of de in- en outputs van de multiplexer, demultiplexer en decoder juist worden gezet (zowel in de VerilogTree als in de intermediateTree). 2. De co¨ ordinaten berekening diepgaand controleren. 3. Bij bitselector verifi¨eren of de groepen juist zijn ingedeeld. 4. Testbenchen schrijven om na te kijken of mijn gedefinieerde extra modules werken zoals het moet. 5. Ook de colliding wires zijn nauwgezet gecontroleerd. 18
Figure 2.8: Een voorbeeld van een module voor een decoder, waarbij de three state op true staat.
2.2.5
Vijfde stadium: arithmetic (tot midden april)
Het algoritme Dit stadium wordt onderverdeeld in de arithmetics die gebruik maken van carry (adder, multiplier, subtractor, divider), en arithmetics die dat niet doen. Vermits arithmetics met een carry allemaal ongeveer dezelfde vorm hebben (2 inputs, carry input, carry output en normale output) worden ze bij elkaar geteld. De implementatie van de extra modules van de carry arithmetics is vrij voor de hand liggend. Wel dient er opgepast te worden voor een floating bit bevattende input, omdat daarbij een parti¨ele operatie moet worden uitgevoerd. De negator bij de niet-carry arithmetics is iets minder eenvoudig. Wanneer er in de input een floating of error bit zit, wordt deze niet gewoon overgeslagen, maar wordt een rare parti¨ele negatie uitgevoerd. Daarom dient er een module gemaakt te worden die dit gedrag nabootst. Ook de bit adder van de niet-carry arithmetics is een doordenker (ook weer voor het geval waarin dat er floating bits kunnen voorkomen). De Logisim documentatie vermeldt hieromtrent: “If any of the input bits are floating or error values, then the output will contain error bits in the output corresponding to
19
the range of possible outputs depending on whether those floating/error values are counted as zeroes or ones.”. Dus lijkt het aangewezen deze parti¨ele operatie uit te voeren door gebruik te maken van 2 sommen. De eerste som telt alle hoge signalen op. De andere som telt alle floating of error signalen op. Nadien worden de 2 sommen opgeteld en wordt de som van de hoge signalen vergeleken met het totaal van beide sommen. Vanaf het moment dat er een bit verschil is, betekent dit dat alle lagere gelegen bits ook onbekend zijn. Testen 1. Opletten dat de extra output wires (bv bij de comparator de less than en the greater than) juist worden gebonden. 2. Extra tests met behulp van testbenches.
20
Figure 2.9: Weergave van de shifter logical left in de extra modules.
2.2.6
Zesde stadium: priority encoder & bit extender & input & output (led, joystick, . . . ) (tot einde april)
Het algoritme Er dient geen TTY en keyboard ontworpen te worden (na overleg met begeleider). Dit zou namelijk niet toepasbaar zijn in Verilog (probleem met in te typen characters). De button wordt als een gewone input beschouwd, net zoals de LED als een gewone output wordt beschouwd. Joystick wordt in Verilog vertaald naar twee inputs (vermits bij de joystick twee signalen worden geproduceerd). De Hex Digit Display en 7-Segment Display worden enkel vertaald tot in de intermediaire tree vermits er geen mogelijkheid is in Verilog om hiervan de 21
output te laten zien.
Figure 2.10: Implementatie van de bit extenders in de extra modules.
Testen = enkel noodzakkelijk tot in de intermediateTree. Daarna worden ze ofwel niet verder vertaald, of worden ze gezien als een gewone input. 1. Extra test voor de JoyStickBase. 2. Controle van de priority encoder en bits extenders + van hun extra modules. 3. Nagaan of de juiste input wires het juiste nummer krijgen opgespeld.
22
Figure 2.11: Een voorbeeld van een priority encoder met 2 inputs.
2.2.7
Zevende stadium: flipflop (tot einde april)
Het algoritme Over het schrijven van hulpmodules voor het maken van de flipflops staan een aantal voorbeelden online. Dit vergemakkelijkt natuurlijk het werk. De beslissing om Pydoc1 te gebruiken, is mede gebaseerd op de research die werd verricht in verband met documentatie. 1
http://effbot.org/zone/pythondoc.html/
23
Testen 1. Voornamelijk nagaan of de wires op de juiste manier binden met de extra in- en outputs. 2. Checken of de trigger van de flipflop correct reageerd op de clock verandering.
2.2.8
Achtste stadium: abstractRegister & random (tot begin meil)
Het algoritme De random is niet volledig overeenkomstig Logisimnormen vervaardigd. In Verilog zijn hier reeds functies voor voorzien, dus volstaat het dat er random elementen worden teruggeven. In Logisim wordt de seed voor de random en de maxValue voor de counter aangeduid als een veldje in de klasse. In Verilog wordt dit opgelost door de component te koppelen aan de daartoe behorende wire (met de juiste waarde) (zie 5.4). Het is wel essentieel een wire te gebruiken omdat anders voor elke mogelijke ingegeven seed of iedere ingevoerde maxValue een andere hulp module moet gemaakt worden in Verilog. Indien er geen wire zou worden gebruikt, ontstaat er een te groot aantal extra modules. Testen Extra modules nakijken. Bij counter opletten wat de “action on overflow” is. Als gevolg van een door mij foutief gemaakte implementatie van “continue counting” bekwam ik hier hetzelfde resultaat als “wrap around”. Ik merkte het verschil pas wanneer de maximum waarde lager lag dan 2bits . De verschillende acties die moeten ondernomen worden bij een overflowed counter, dienen minitieus getest.
2.2.9
Negende stadium: ram, rom & shiftregister (tot begin meil)
Het algoritme Het gebruik van multi-arrays maakt deze iteratie gemakkelijker dan zou verwacht worden. Bij rom dient er wel rekening mee gehouden te worden dat in elke instantie van de module steeds dezelfde roms worden ingeladen. Aangewezen is dus om bij rom geen variabele file names te gebruiken. Wanneer een bepaalde file moet worden ingelezen (voor de rom), dient deze gedefinieerd in het .v bestand van de module zelf. Hierdoor kunnen er nooit verschillende module instanties zijn, met verschillende rom instanties. Bij ram is het wel mogelijk verschillende instantiaties te hebben per module.
24
Om deze reden dient er gewerkt te worden met een parameter die vanuit een andere module kan worden aangepast met “defparam”. Naast het vertalen van de elementen in deze iteratie, is het aangewezen een python scriptje te maken. Wanneer immers de inhoud van een geheugen wordt opgeslagen met Logisim, heeft dit niet het juiste formaat voor het Verilog geheugen element. Het scriptje zal de opgeslagen Logisim inhoud converteren naar een voor Verilog inleesbaar bestand. Testen 1. Aandachtpunt is de data-pin op de ram. Deze is zowel een input als een output is en dient daarom grondig gecontroleerd te worden. 2. Verder de verschillende data interfaces van de ram nakijken. 3. Natuurlijk dient de rom eveneens getest te worden.
2.2.10
Tiende stadium: pull resistor (tot begin mei)
Het algoritme Voor de pull resistor wordt geen aparte component klasse gemaakt. Het betreft hier eerder een eigenschap van een wire. Een pull resistor, die wordt beschouwd als een wire, is makkelijker te implementeren. Een pull resistor zorgt er namelijk voor dat de wire waaraan hij vasthangt naar een bepaalde waarde wordt getrokken. De wires krijgen dus een extra direction veld. Dit direction veld zegt in welke richting de wire zal worden getrokken als er floating bits opzitten. Testen 1. Nagaan of er een pull resistor op de wire zit. 2. Nakijken of het verbinden van de wires correct verloopt. 3. Controleren dat wanneer er 2 pull resistors (met verschillende direction waarde) op dezelfde wire staan, de uitkomst van het pullen gelijk is aan error value.
25
Figure 2.12: De pull resistor werkt op alle wires waarmee deze verbonden is.
2.2.11
Elfde stadium: importeren van circuits (tot midden mei)
Het algoritme Problematisch hierbij is het bepalen van de co¨ordinaten op de ge¨ımporteerde component. Om te beginnen dient er bepaald te worden met welke base de in XML opgeslagen co¨ ordinaten overeenstemmen. Vervolgens moeten, aan de hand van deze co¨ ordinaten, de andere co¨ordinaten worden bepaald. Die andere co¨ ordinaten zijn afhankelijk van: 1. het aantal andere aanwezige bases met dezelfde facing (dit bepaald de size) 2. de ori¨entatie van de bases 3. de or¨ıentatie van het ge¨ımporteerde component Nadien dient er beslist te worden hoe de verwijzing van de pin naar de overeenkomstige base wordt vastgelegd. De drie mogelijkheden hier zijn: 1. Al in de intermediate tree starten met nameresolutie en dus de pins en bases al namen geven, zodat daaruit de verwijzing kan worden gehaald. 2. Een depth first manier. Wanneer een module een andere module includeert, dient eerst de ge¨ıncludeerde module afgemaakt, zodat tijdens het backtracken in de hoofdmodule een verwijzing naar de bases van de ge¨ımporteerde module wordt gegeven. 3. Werken in 2 passes. In de eerste pass worden alle circuits met hun bijhorende in- en output bases gemaakt. In de 2de pass wordt het eigenlijke parsen en binden gedaan. Wanneer een circuit wordt ge¨ımporteerd en geweten is welke pin met welke base moet overeenkomen, 26
kan de juiste verwijzing naar de base erin gezet worden (vermits alle bases toch al aangemaakt zijn). De eerste optie (namen in de intermediate tree al behandelen en aan de hand van de namen de verwijzing doen) is geen aanrader. Dit omdat er in de intermediaire boom eigenlijk een hele weg moet gevolgd worden. Als we aan de hand van strings naar andere componenten gaan verwijzen, is het niet meer mogelijk die lange weg efficient te volgen. De tweede mogelijkheid (depth first) is niet echt evident. Dit is geen logische manier om over een boom te lopen. Keuzemogelijkheid drie, waarbij al in de Verilog tree gebruik gemaakt wordt van de namen is veruit het meest aangewezen. Testen Doorgedreven testing van de juiste berekening van de co¨ordinaten en de grootte van de component. Vervolgens nakijken of de references juist staan. De reference testen in de VerilogTree testen op zijn juistheid (belangrijk). Indien ok testen aan de hand van een testbench.
2.2.12
Twaalfde stadium: splitter (tot einde mei)
Het algoritme Een laatste (lastige) spurt: de splitter. Een splitter kan niet echt als component worden bekeken. Echter het is ook niet mogelijk een splitter als connection te beschouwen. Het lijkt daarom aangewezen om voor de splitter een aparte klasse (zie 5.2) te maken en aldus ook aparte functies te schrijven voor het binden van de wires. De Verilogsplitter (die in een extra module moet worden gedeclareerd) brengt ook heel wat werk mee. Uiteindelijk is deze iteratie voltooid kunnen worden maar, indien ik niet in zo een tijdnood had gezeten, was er waarschijnlijk een andere implementatie uit de bus gekomen. Het belangrijkste is echter dat er een splitter gemaakt is en dat hij naar behoren werkt. Testen 1. Controleren of er onthouden wordt welke bit aan welke wire wordt toegekend (zowel in intermediaire boom, als in de Verilog boom). 2. Nakijken op de mogelijkheid dat de fan-out groter is dan de bit width in. 3. Controleren op de mogelijkheid dat de fan-out kleiner is dan de bit width in. 4. Uitzoeken hoe de “tran” van Verilog werkt.
27
Figure 2.13: Een voorbeeld van de mogelijkheden waaruit kan worden gekozen welke bit aan welke wire wordt toegekend.
Figure 2.14: De splitter met de wire in kleine partjes opgedeeld.
28
Figure 2.15: De splitter met een wire samengesteld uit kleinere delen.
29
Chapter 3
Checks Voor het implementeren van de checks wordt het visitor pattern in combinatie met een iterator gebruikt. Met dit patroon kunnen de handelingen, verricht tijdens het bezoeken van de boom, worden losgekoppeld van de manier waarop de boom bezocht wordt. Indien de boom achteraf op een alternatieve wijze zou worden doorlopen, dient enkel de traverse methode aangepast te worden. De extra visitor zal over de intermediate tree lopen en de extra gewenste checks uitvoeren. De beoogde checks zijn: 1. Nagaan of een (lijst van) elementen aanwezig is in een circuit (de elementen worden gespecifieerd aan de hand van voorwaarden). 2. Kijken of bepaalde elementen transitief geconnecteerd zijn met elkaar (en hoeveel keer het voorkomt dat ze transitief geconnecteerd zijn) De eerste check kan aan de hand van counters worden ge¨ımplementeerd. Bij het doorlopen van de boom wordt dan geteld hoe vaak aan de gespecifieerde condities voldaan wordt. Bij het uitvoeren van de connectiviteitstest (de tweede check) dient rekening gehouden te worden met de directionaliteit van enerzijds de te testen elementen en anderszijds de tussenliggende componenten. Met deze connectiviteitstest kan worden nagegaan: 1. Of er een element van type 1 verbonden is met een element van type 2. 2. Hoe vaak een element van type 1 verbonden is met een element van type 2.
30
Figure 3.1: Test connectivity tussen clock en flipflop, hier is het resultaat ([3], [0, 0, 0]), vermits er 3 flipflops met de clock verbonden zijn, maar geen enkele flipflop met een clock verbonden is
Figure 3.2: Test connectivity tussen not gate en splitter. Resultaat: ([1, 0], [0, 2, 1]), eerste lijst is de splitter lijst met de gevonden counters en de tweede lijst is een voorstelling van de not gates. Met de checks kunnen combinaties gemaakt worden en een hele boel dingen getest worden. Indien er achterhaald moet worden of elke flipflop verbonden is met een clock, kan worden opgevraagd hoeveel keer een clock verbonden is met een flipflop. Vervolgens wordt nagegaan hoeveel flipflops er voor handen zijn. Indien het aantal flipflops groter is dan het aantal verbonden flipflops, blijkt duidelijk dat niet alle flipflops met een clock verbonden kunnen zijn. Testen De independent checks worden getest op de verschillende combinatie mogelijkheden van lijsten en met verschillende attributen. Verifi¨eren van de connectiviteitstesten: 1. Opvragen van counters. 2. Opvragen van bools.
31
3. Nakijken of het zoeken gestaakt wordt nadat de richting geheel verkend is.
32
Chapter 4
Conclusie Persoonlijk ben ik zeer tevreden over het bekomen eindresultaat. Niet alleen kunnen Logisim bestanden nu zonder probleem worden omgezet in Verilog code, maar wat vooral belangrijk is, met het ontwikkelde programma kunnen dynamische en statische testen worden gedraaid op (door anderen) ontworpen circuits. Ik heb mij vrij goed aan de opgestelde planning kunnen houden. Alle taken die mij werden toevertrouwd, heb ik kunnen voltooien en voor alle iteraties werden de nodige testen voorzien. Dankzij deze eindwerk opdracht heb ik enorm veel bijgeleerd over python, patterns, Logisim en Verilog. Het jammerlijk minpunt is het feit dat het door mij gemaakte vertaalprogramma niet echt meer nuttig is. Bij het redigeren van dit verslag (terwijl ik de downloadlinks op de juiste plaats zette) diende ik namelijk vast te stellen dat Logisim recentelijk een nieuwe release heeft uitgewerkt. Normaal gesproken zou dit niet zo een grote ramp zijn geweest. Echter, er is heel veel nieuw materiaal in het programma opgenomen en er zijn heel wat veranderingen doorgevoerd. Bovendien is er ook aan de basiscomponenten overvloedig gesleuteld. Voor een gedeelte van de Logisim aanpassingen is het vertaalprogramma nog bruikbaar (mits diverse modificaties). Een lichtpuntje hier is dat de bestanden, aangemaakt in 2.6.1, “runbaar” zijn in versie 2.7.1. Dit neemt evenwel niet weg dat mijn programma, spijtig genoeg niet gebruikt zal kunnen worden in zijn huidige vorm (zoals ik had gehoopt).
33
Chapter 5
Klassediagrammen 5.1
Annotated Classes
Deze klassen worden gebruikt om de noodzakelijke informatie (voor het parsen en builden van de boom) in op te slaan. Deze informatie wordt echter overbodig wanneer de boom voltooid is. Een voorbeeld van dit soort informatie: de co¨ ordinaten van de componenten. Deze co¨ordinaten zijn nodig om de elementen juist met elkaar te kunnen verbinden, maar zijn overbodig wanneer de elementen effectief verbonden zijn.
34
AnnotatedElement
AnnotatedNode
AnnotatedConnection
AnnotatedTunnel
AnnotatedSplitter
+node +coordinates +facing : string
+connection +coordinatesFrom +coordinatesTo
+splitter +coordinatesFrom +coordinatesTo +facing : string +fanOut : int
AnnotatedStandardCon nection
AnnotatedArithmetic
AnnotatedBitExtender
+inputCoordinate
+inputCoordinate +extraInputCoordinate
AnnotatedDisplay
AnnotatedPriorityEncoder +inputCoordinates +enableInputCoordinate +enableOuputCoordinate +groupOutputCoordinate
AnnotatedGate +nrOfInputs : int +negatedInputIndexes +size : int +inputCoordinates
AnnotatedBase
AnnotatedPlexer
AnnotatedMemory
+connectingCoordinates +clockInputCoordinate +selectCoordinate
AnnotatedImportedCircuit +inputCoordinateTuples +outputCoordinateTuples
AnnotatedArithmetic
AnnotatedDisplay
+inputCoordinate
AnnotatedCarryArithmetic
AnnotatedBitAdder +inputCoordinates +numberOfInputs : int
AnnotatedNegator
-secondInputCoordinate +extraInputCoordinate +extraOutputCoordinate
annotated7SegmentDisplay
AnnotatedLedMatrix
+inputCoordinates
+inputCoordinates
AnnotatedComparator +secondInputCoordinate +greaterOutputCoordinate +lessOutputCoordinate
AnnotatedBitFinder
AnnotatedShifter
+presentOutputCoordinate
+distanceInputCoordinate
AnnotatedHexDigitDisplay +pointInputCoordinate
AnnotatedPlexer
AnnotatedBase
AnnotatedGate
+connectingCoordinates +selectCoordinate
+nrOfInputs : int +negatedInputIndexes +size : int +inputCoordinates AnnotatedInputBase
AnnotatedInputPlexer
AnnotatedOutputBase
AnnotatedSelector
AnnotatedStandardGate
AnnotatedJoystickBase +secondOutputCoordinate
AnnotatedOutputPlexer
AnnotatedControllerGate
+hasInput : bool
+controlCoordinate +controlSide
AnnotatedMemory -inputCoordinate +clockInputCoordinate +resetInputCoordinate
AnnotatedFlipFlop +enableInputCoordinate +setInputCoordinate +complementOutputCoordinate
AnnotatedAbstractRegister
AnnotatedLargeMemory
+extraInputCoordinate
+selectInputCoordinate
+enableInputCoordinate
AnnotatedShiftRegister +shiftInputCoordinate
AnnotatedRam
AnnotatedCounter +loadInputCoordinate +carryOutputCoordinate AnnotatedOneInputFlipFlop
AnnotatedRandom
+loadInputCoordinate +storeInputCoordinate +dataInputCoordinate
AnnotatedRom
AnnotatedRegister AnnotatedTwoInputFlipFlop +secondInputCoordinate
AnnotatedStandardShiftRegister
AnnotatedParallelLoadShiftRegister +loadInputCoordinate +parallelInputCoordinates +parallelOutputCoordinates
5.2
Intermediate Classes
Op de hierna volgende pagina ziet u een voorstelling van de klassen die kunnen voorkomen in de intermediaire boom, samen met de intermediaire boom klasse. Op deze boom worden dus de logical checks uitgevoerd. De intermediaire boom bevat een lijst van circuits, die overeenstemmen met de in Logisim gedefinieerde circuits.
37
IntermediateBuilder -xmldoc -faultList +makeIntermediateTree()
AnnotatedElementFactory
Output Input
+connections : [Connection]
+connection : Connection
NumberedOutput
ReferencedOutput
NumberedInput +number : int
NegatedInput +negated : bool
ReferencedInput +reference : BaseNode
IntermediateTree +circuitList : [Circuit] +traverse(in visitor)
Element +name : string
Circuit
Node
Splitter
Connection
+connectionList : [Connection] +nodeList : [Node]
+bits : int +outputWire : Output
+start : Element +end : Element +bits : int
+start : Element +end : Element +direction : string Wire
Tunnel +bits : int
BitExtenderNode
ArithmeticNode
+widthIn : int +extensionType : string +inputWire : Input +extraInputWire : Input
+inputWire : Input
PriorityEncoderNode
ImportedCircuitNode
+inputWires : [NumberedInput] +inputWires : [Input] +enableInputWire : Input +referencedCircuit : Circuit +enableOutputWire : Output +groupOutputWire : Output
DisplayNode +color : string +offColor : string +inputWires : [Input]
BaseNode
PlexerNode
GateNode
MemoryNode
+selectBits : int +selectLine : Input
+inputWires : [NegatedInput]
+inputWire : Input +clockInputWire : Input +resetInputWire : Input +trigger : string
ArithmeticNode
PlexerNode
+inputWire : Input
+selectBits : int +selectLine : Input
CarryArithmetic
ArithmeticWithoutCarry
+secondInputWire : Input +extraInputWire : Input +extraOuputWire : Input
Multiplier
Adder
Subtractor
DemultiPlexer
MultiPlexer
+threeState : bool -inputWire : Input
+inputWires : [NumberedInput]
BitAdder
Comparator
BitSelector
Decoder
+inputWires : [Input]
+numericType : string +secondInputWire : Input +greaterOutputWire : Input +lessOutputWire : Input
+outputBit : int +inputWire : Input
+threeState : bool
Negator
Divider
BitFinder
Shifter
+type : string +presentOutputWire : Output
+shiftType +distanceInputWire
GateNode +inputWires : [NegatedInput]
BaseNode
OrGate
NandGate
NorGate
JoystickBase
ConstantBase
+secondOutputWire : Output +color : string
+value : string ClockBase
NotGate
EvenParityGate
AndGate
+highDuration : int +lowDuration : int InputBase ProbeBase
OutputBase +inputWire : Input
LedBase
+radix : string
StandardOutputBase
ButtonBase
StandardInputBase
+color : string
+pullBehavior : string
ControlledInverterGate
ControlledBufferGate
+controlLine : Input
+controlLine : Input
XorGate
BufferGate
+OneInputMultipleInputBehavior : bool
+color : string +offColor : string DisplayNode
XnorGate
+color : string +offColor : string
+OneInputMultipleInputBehavior : bool
7SegmentDisplay
HexDigitDisplay
+inputWires : [Input] +backGround : string
+numberInputWire : Input +pointInputWire : Input +backGround : string
LedMatrix +inputWires : [Input] +dotShape : string +persist : int +numberOfInputs : int
OddParityGate
MemoryNode +inputWire : Input +clockInputWire : Input +resetInputWire : Input +trigger : string
LargeMemory
Random
FlipFlop
ShiftRegister
AbstractRegister
+selectInputWire : Input +dataBit : int
+enableInputWire : Input +seed : int
+enableInputWire : Input +setInputWire : Input +complementOutputWire : Output
+shiftInputWire : Input +numberOfStages : int
+extraInputWire : Input
Ram
Rom StandardShiftRegister
+loadInputWire : Input +storeInputWire : Input +dataInputWire : Input +dataInterface : string
ParallelLoadShiftRegister +loadInputWire : Input +parallelInputWires : [Input] +parallelOutputWire : [Output]
OneInputFlipFlop
TwoInputFlipFlop +secondInputWire : Input
Counter +loadInputWire : Input +carryOutputWire : Input +maxValue : string +actionOverflow : string
DFlipFlop
TFlipFlop
SRFlipFlop
JKFlipFlop
Register
5.3
Visitor Classes
Er zijn twee hoofdvisitor klassen. De VerilogVisitor loopt over een VerilogTree, terwijl de IntermediateVisitor over de IntermediateTree loopt.
42
VerilogVisitor +visit(in element)
ModuleDescriptor +name : string +heading : string +parameters : string +inputs : [string] +outputs : [string] +nets : [string] +initialBlock : string +initialBlockEnding : string +alwaysBlockEnding : string +alwaysBlock : string +ending : string +extraBlocks +extraModules
VerilogWriteVisitor +fileList : [ModuleDescriptor] +visit(in module)
IntermediateVisitor +visit(in element : Element)
IntermediateTranslatorVisitor
IntermediateConnectivityVisitor
IntermediateNamingVisitor
IntermediateIndependentCheckVisitor
+moduleList : [Module] +gatedir +wiredir +resdir +basedir +plexerdir +arithmeticdir +memorydir +otherdir +wireNameList +visit(in element : Element)
+attributesOfElement1 +attributesOfElement2 +found : bool +visit(in element : Element)
+inputCount : int +outputCount : int +gateCount : int +netCount : int +parameterCount : int +statementCount : int +nameList +visit(in element : Element)
+listOfAttributeMaps +visit(in element : Element)
5.4
Verilog Classes
Op de volgende pagina vindt u de weergave van de klassen die kunnen voorkomen in de Verilog boom. De Verilog boom is de syntactische voorstelling van de Verilog code.
44
Node -name : string
Constant
Wire
+value : int +bits : int
+bits : int +value : string
Arithmetic +input +output
ResistingWire +inputWire : Wire +outputWire : Wire +direction : string +name : string
CollidingWire +inputWire : Wire +outputWire : Wire
Splitter
Clock
Module +inputList +outputList : [OutputRegister] +gateList : [Gate] +netList : [Wire] +parameterList +statementList
Memory
+start : Wire +end : Wire +bits : int
+highDuration : int +lowDuration : int
Gate +inputs +output
Register
+input +clockInput +resetInput +output +trigger : string
+bits : int
ImportedCircuit
BitExtender
+inputs +outputs +referencedCircuit : string
+extensionType : string +input +output +extraInput +inBit : int
Plexer +selectLine
PriorityEncoder +inputs +enableInput -output +enableOutput +groupOutput +outBit : int
Register
Gate
+bits : int
InputRegister
+inputs +output
AndGate
OutputRegister
OrGate NorGate
+connectedWire
ControlledInverterGate
+input +output
ControlledBufferGate
NandGate
+controlLine
Arithmetic
NotGate
XnorGate
+controlLine
OneInputOnGate NotOneInputOnGate
CarryArithmetic
XorGate
ArithmeticWithoutCarry
+secondInput +extraInput +extraOuput BitFinder
Multiplier
Adder
Shifter
Comparator
+type : string +presentOutput
+numericType : string +secondInput +greaterOutput +lessOutput
Negator
Plexer
+shiftType : string +distanceInput : int
+selectLine : Wire
Multiplexer Divider
Decoder
+inputs +ouput
Subtractor BitAdder +inputs +numberOfInputs : int
+outputs +threeState : bool
Demultiplexer +input +outputs +threeState : bool
BitSelector +output +input
Memory +input +clockInput +resetInput +output +trigger : string
Rom
FlipFlop
+selectInput
RegisterMemory
+enableInput +setInput +complementOutput
+enableInput
Ram
ShiftRegister
Counter
+selectInput +loadInput +dataInput +extraNames : [string]
+shiftInput +numberOfStages : int
-countInput +loadInput +carryOutput +maxValue : string +actionOverflow : string +bits : int
DFlipFlop
SeparateRam JKFlipFlop +secondInput
+storeInput StandardRam ParallelLoadShiftRegister
+hasClock : bool StandardShiftRegister TFlipFlop
SRFlipFlop +secondInput
+loadInput +parallelInputs +parallelOutputs
Random +enableInput