• Keine Ergebnisse gefunden

Die letzte L¨osung basiert auf einer Erweiterung von Haskell, die allerdings einen kleinen Bruch mit der funktionalen Idee beinhaltet. Dabei wird die referentielle Transparenz f¨ur genau den gew¨unschten Bereich aufgeweicht, indem vergleichbare Referenzen zur Verf¨ugung gestellt werden.

Listing 21: Der Referenztyp type Ref = [ . . . ]

r e f : : a −> Ref a d e r e f : : Ref a −> a

(<=>) : : Ref a −> Ref a −> Bool

Auf die Implementation von Ref gehen wir sp¨ater ein. Mit ref kann man einen gegebenen Wert in eine Referenz einpacken, mit deref wieder auspacken und mit

<=>Referenzen vergleichen.

Damit ist die referenzielle Transparenz f¨ur Referenzen aufgehoben, an unter-schiedlicher Stelle konstruierte, aber ansonsten gleiche Wert k¨onnen nun unterschie-den werunterschie-den.

∗Main> l e t x = 42 i n l e t r = r e f x i n r <=> r True

∗Main> l e t x = 42 i n r e f x <=> r e f x F a l s e

Da im zweiten Ausdruck zwei unterschiedliche Referenzen mit selbem Inhalt erstellt werden, ergibt sichFalse. W¨ahrend im ersten Fall dieselbe Referenz mit sich selbst verglichen wird, daraus muss sich dann True ergeben.

Das kann jetzt benutzt werden, umBit zu definieren, in einer Schleife wiederho-len sich dieselben Referenzen, andernfalls unterscheiden sie sich. Damit sind Kreise und Wiederholungen genauso erkennbar wie bei der expliziten Bezeichnung von Teilb¨aumen.

Listing 22: Implementation mittels Shared Observables data B i t = Var String

| Comp Ref ( (String, [ B i t] ) ) deriving (Eq,Show)

comp : : String −> [B i t] −> B i t comp s b = Comp (r e f (s,b) )

i n v : : B i t −> B i t

i n v b = comp ” i n v ” [b]

d e l a y d e = comp ” d e l a y ” [d,e] and2 (a,b) = comp ” and ” [a,b] or2 (a,b) = comp ” o r ” [a,b] l o w = comp ” low ” [ ]

Wieder fungiert comp als eigentliche Konstruktionsfunktion, Bit ist wie im Ur-sprungsansatz definiert, nur dass ¨uber eine Referenz auf den Inhalt zugegriffen wird.

Diese Referenz l¨asst sich dann mit bisherigen Referenzen verglichen und gegebenfalls wird auf die Unterkomponenten zugegriffen.

Das rs-Flipflop kann dadurch wieder auf gew¨ohnliche Weise, mit direkt ausge-dr¨uckter Rekursion, aufgeschrieben werden, siehe Listing 9.

Mit der Aufgabe der referentiellen Transparenz muss sich der Programmierer nun im Klaren dar¨uber sein, wann ein bestimmter Ausdruck neu berechnet und wann derselbe genommen wird. Das ist jetzt ein Unterschied, denn im ersten Fall sind die Ergebnisse zwei unterschiedliche Referenzen, im zweiten Fall ist es nur eine einzige. In den g¨angigen Haskellimplementationen wird nachcall-by-need gehandelt, konstante Ausdr¨ucke sind also alle gleich, nicht-konstante sind unterschiedlich.

Listing 23: Beispiel call-by-need c1 ( ) = a

where s = i n v a r = a

a = rsFF (r ,s) c2 ( ) = r

where s = i n v (rsFF (r,s) ) r = (rsFF (r,s) )

Beide,c1 und c2, ergeben eine Leitung, die mit jedem Takt den Wert wechselt.

W¨ahrend aberc1 nur aus einem einzigen, r¨uckgekoppelten Flipflop mit Inverter vor dem s-Eingang besteht, enth¨altc2 zwei Flipflops. Diese zwei Flipflops erhalten genau die gleichen Eingaben und sind entstanden, weil inc2 rsFF (r,s) tats¨achlich zweimal ausgef¨uhrt wurde, nicht einmal, wie man es nach funktionaler Lesart erwarten w¨urde.

Implementiert werden k¨onnte Ref zum Beispiel mit der Hugs-BibliothekIOExts, diese bietet bereits Referenzen basierend auf der IO-Monade an, zusammen mit der FunktionunsafePerformIO. Mit dieser k¨onnen IO-Monaden verborgen und als scheinbar normale Funktion genutzt werden.

Listing 24: Implementation von Ref import IOExts

newtype Ref a = MkRef (IORef a) r e f : : a −> Ref a

r e f x = MkRef (u n s a fe P e r f o r m IO (newIORef x) ) d e r e f : : Ref a −> a

d e r e f (MkRef r e f) = u n s a fe P e r f o r m IO (readIORef r e f) (<=>) : : Ref a −> Ref a −> Bool

(MkRef r e f 1) <=> (MkRef r e f 2) = r e f 1 == r e f 2

Der Hauptvorteil dieses Ansatzes liegt darin, dass die intuitive Syntax der Schal-tungen beibehalten werden kann. Es wird kein spezieller Operator f¨ur Rekursionen ben¨otigt, sie sind direkt mit benannten Leitungen im where-Bereich ausdr¨uckbar.

Daf¨ur gibt man allerdings die reine funktionale Programmierung auf, sodass nicht mehr alle aus Haskell bekannten Transformationen m¨oglich sind. ¨Uber diesen Umstand muss sich der Programmierer im Klaren sein.

4 Realisierung in FPGAs

Eine, auch in der Praxis verwendete, Anwendung f¨ur Lavaschaltungen ist die Rea-lisierung in FPGAs.

Ein Field Programmable Gate Array FPGA besteht aus vielen, sehr einfachen Zellen, die sich programmieren lassen und zusammen eine Funktionalit¨at bereitstel-len. Dabei kann jede Zelle eine einfache logische Funktion implementieren, einen Wert speichern und Ausgaben an andere Zellen weitergeben.

Mit Lava beschriebene Schaltungen lassen sich in FPGAs implementieren und so relativ einfach realisieren.

Eine Schaltung kann mit der Funktion writeVhdl in VHDL-Code umwandelt werden, der dann wie andere Beschreibungen verwendet werden kann. Dabei gilt nat¨urlich, wie bei der Verifikation, dass Eingaben konkrete Leitungen sein m¨ussen, wie einfacheBits, und nicht in Listenform sind.

Listing 25: 4-Bit Demuxer

demuxn4 : : ( (B i t ,B i t) ,B i t ,B i t) −> (B i t ,B i t ,B i t ,B i t) demuxn4 ( (s0 ,s 1) ,d,e) = (a0,a1,a2,a3)

where [a0,a1,a2,a3] = demuxn ( [s0,s 1] ,d,e)

∗Main> w r i t e V h d l ”demux4” demuxn4

W r i t i n g t o f i l e ”demux4 . vhd ” . . . Done.

F¨ur demux4 ergibt sich damit der VHDL-Code in Listing 26, der sich mit g¨angigen Werkzeugen in einem FPGA realisieren ließe. Auch speziellere Werkzeuge zur Realisierung in FPGAs sind verf¨ugbar, zum Beispiel von Xilinx Inc.

Listing 26: demux4 in VHDL, gek¨urzt

−− G e n e r a t e d by Lava 2000 use work.a l l ;

entity demuxn4 i s port ( c l k : in b i t

−− i n p u t s

; i n p 1 1 : in b i t ; i n p 1 2 : in b i t

; i n p 2 : in b i t ; i n p 3 : in b i t

−− o u t p u t s

; o u t p 0 : out b i t ; o u t p 1 : out b i t

; o u t p 2 : out b i t ; o u t p 3 : out b i t ) ;

end entity demuxn4;

architecture s t r u c t u r a l o f demuxn4 i s s i g n a l w1 : b i t ;

s i g n a l w2 : b i t ; [ . . . ]

s i g n a l w28 : b i t ; begin

c w3 : entity i d port map (c l k , i n p 1 2 , w3) ; c w4 : entity i d port map (c l k , i n p 3 , w4) ; c w2 : entity and2 port map (c l k , w3, w4, w2) ; c w6 : entity i n v port map (c l k , w3, w6) ;

c w9 : entity i d port map (c l k , i n p 1 1 , w9) ; c w8 : entity and2 port map (c l k , w9, w4, w8) ; c w11 : entity i n v port map (c l k , w9, w11) ; c w12 : entity i d port map (c l k , i n p 2 , w12) ; c w10 : entity and2 port map (c l k , w11, w12, w10) ; c w7 : entity or2 port map (c l k , w8, w10, w7) ; [ . . . 18 w e i t e r e Z e i l e n]

−− naming o u t p u t s

c o u t p 0 : entity i d port map (c l k , w1, o u t p 0 ) ; c o u t p 1 : entity i d port map (c l k , w13, o u t p 1) ; c o u t p 2 : entity i d port map (c l k , w17, o u t p 2) ; c o u t p 3 : entity i d port map (c l k , w25, o u t p 3) ; end s t r u c t u r a l;

5 Zusammenfassung und Ausblick

Lava bietet eine M¨oglichkeit an Schaltungen sehr kompakt zu formulieren und un-terst¨utzt die Realisierung und die Verifikation gleichermaßen. Durch den funktio-nalen Ansatz k¨onnen alle Elemente sehr allgemein und auf sehr hohem Abstrakti-onsniveau formuliert werden, allerdings kann die Fehlersuche dadurch aufwendiger werden. M¨ochte man den Wert einer internen Leitung erfahren, muss diese von ihrer Nutzung bis zur

”Hauptfunktion“ durchgereicht werden, anstatt sie kurzzeitig per Seiteneffekten ausgeben zu k¨onnen.

Das Ausrollen der Listen beliebiger L¨ange funktioniert nicht immer reibungslos.

In Situationen mit Kreisen dieser Listen kann es n¨otig sein alle Werte explizit her-auszuholen und wieder hineinzustecken, selbst wenn es eigentlich m¨oglich w¨are, die L¨ange durch andere Eingaben zu erkennen. Dadurch wird der Vorteil der allgemeinen Formulierung teilweise wieder zunichtegemacht.

Die Vorteile von Schaltungsprogrammierung in funktionaler Sprache ist f¨ur den Anwender sichtbar, wird allerdings ein wenig ad absurdum gef¨uhrt, dadurch, dass in der Implementierung entweder Vorteile der Formulierung von Schaltungen aufge-geben werden, oder das funktionale Prinzip selbst aufgeweicht wird.

In diesem Dokument wurden die Implementation der Verifikation [Cla00], sowie weitergehende Beispiele der Nutzung von Lava nicht behandelt.

Mit, in Lava elegant formulierbaren, Schmetterlingsnetzen lassen sich Sortier-netze, Kopplungsnetze und schnelle Fouriertransformation kompakt beschreiben.

[CSS03] [Cla00] [BCSS98]

Es gibt unterschiedliche Versionen von Lava, wie die von Xilinx Inc., in der Filter, Bezierkurvenzeichner und Schaltungen zur digitalen Signalverarbeitung beschrieben und realisiert werden. [CSS03]

Nat¨urlich kann Lava auch noch erweitert werden, zum Beispiel gibt es Wired, mit dem sich die Verlegung von Leitungen direkt beeinflussen l¨asst, und so die Ein-schr¨ankungen von Lava im Low-Level-Bereich etwas aufgeweicht werden. [ACS05]

Literatur

[ACS05] Emil Axelsson, Koen Claessen, and Mary Sheeran. Wired: Wire-aware circuit design. In Proc. of Conference on Correct Hardware Design and Verification Methods (CHARME), volume 3725 ofLecture Notes in Com-puter Science. Springer Verlag, October 2005.

[BCSS98] Per Bjesse, Koen Claessen, Mary Sheeran, and Satnam Singh. Lava:

Hardware design in Haskell. In Proc. of International Conference on Functional Programming (ICFP). ACM SIGPLAN, 1998.

[Cla00] Koen Claessen. An embedded language approach to hardware description and verification, August 2000. Dept. of Computer Science and Enginee-ring, Chalmers University of Technology. Lic. thesis.

[CSS03] Koen Claessen, Mary Sheeran, and Satnam Singh. Functional hardware description in Lava. In The Fun of Programming, Cornerstones of Com-puting, pages 151–176. Palgrave, 2003.

[She85] Mary Sheeran. Designing regular array architectures using higher order functions. InProc. of a conference on Functional programming languages and computer architecture, pages 220–237, New York, NY, USA, 1985.

Springer-Verlag New York, Inc.

[She90] Mary Sheeran. Describing butterfly networks in ruby. In Proceedings of the 1989 Glasgow Workshop on Functional Programming, pages 182–205, London, UK, 1990. Springer-Verlag.

ÄHNLICHE DOKUMENTE