Wired: Low-level hardware design in Haskell Hardware Description and Verification Emil Axelsson, May 2007
Goal (example) bitMult = row andBitM where andBitM = and2 *=* ((cro *||* wireT0) *||* wireX)
Help to reach the goal ● Logic programming library (LP) in Haskell exArith = do *Main> runLP exArith (res,x) <- free [7] res <== x |-| 3 x <== 5 |*| 2 Solve return res constraints Setup constraints ● Relational Lava (uses LP)
Lava ● A Lava “circuit”: A Haskell program that generates a netlist (directed graph with simple boolean gates as nodes) inv :: Signal Bool -> Signal Bool *Main> simulate (inv ->- inv) low low ● Feels like functional programming *Main> (not . not) False False
Recursive generators *Main> simulate (map (inv->-inv)) [low,high,low] [low,high,low] Simple, compact descriptions for complicated structures
Relational Lava (RLava) ● Lava circuits have predefined signal-flow direction ● Reason: Circuits are functions ● Ideally, connection patterns should abstract away from signal flow (think about real electrical wires)
Relational Lava (RLava) ● RLava models circuits as relations instead: *Main> L.simulate (convert (inv <> inv)) L.low low ● Relations implemented using the LP library ● RLava's combinator library mimics Lava's ● Simulation, verification, synthesis, etc. is done through Lava (using convert )
Signal flow abstraction wire :: Term Int -> Signal -> LP Signal exRLava = mapM ((inv <> wire 1) -|- (converse inv <> wire 1) )
Wired background ● Netlists are lacking geometrical information ● Cell placement and wire routing needed before fabrication ● Pre-layout performance estimation very hard!! – Main reason: hard to predict wire properties ● Automatic tools are often not good enough – Evidence: Large parts of Intel's chips are designed manually ● Can Haskell make manual design easier?
Basic idea ● Use connection patterns as in Lava, but let them also represent layout ● Example, row: ● This has been done before (e.g. in Lava), but we want a more direct connection to standard cell layout, including wiring :
Wired circuits ● Wired circuit: A rectangular tile characterized by its four ports ( w , n , s and e ) n w e s and2 :: Circ Ins ((Sig, Sig), Ins) (Ins, Sig) Ins
Wired example and2 :: Circ Ins ((Sig, Sig), Ins) (Ins, Sig) Ins (*||*) :: ( Port wL, Port nL, Port sL, Port x , Port nR, Port sR, Port eR ) (nL,nR) => Circ wL nL sL x -> Circ x nR sR eR -> Circ wL (nL,nR) (sL,sR) eR wL eR (sL,sR)
Wired example and2 :: Circ Ins ((Sig, Sig), Ins) (Ins, Sig) Ins (*||*) :: ( Port wL, Port nL, Port sL, Port x , Port nR, Port sR, Port eR ) (nL,nR) => Circ wL nL sL x -> Circ x nR sR eR -> Circ wL (nL,nR) (sL,sR) eR wL eR and2 *||* and2 (sL,sR) :: Circ Ins (((Sig, Sig), Ins), ((Sig, Sig), Ins)) ((Ins, Sig), (Ins, Sig)) Ins renderCircuit "circ" (and2 *||* and2)
Wires wireX :: Circ Sig Ins Ins Sig wireY :: Circ Ins Sig Sig Ins wireL0 :: Circ Ins Sig Ins Sig wireT0 :: Circ Sig Ins Sig Sig cro :: Circ Sig Sig Sig Sig
Wires wireX :: Circ Sig Ins Ins Sig wireY :: Circ Ins Sig Sig Ins wireL0 :: Circ Ins Sig Ins Sig wireT0 :: Circ Sig Ins Sig Sig cro :: Circ Sig Sig Sig Sig bitMult = row andBitM where andBitM = and2 *=* ((cro *||* wireT0) *||* wireX) renderCircuit "circ" (bitMult `ofLengthX` 3)
Size inference ● Haskell type system checks that interfaces of connected circuits match, but not sizes ● Sizes are checked using logical constraints in the LP library ● By solving size constraints we also get size inference for free!
Size inference bitMult `ofLengthX` 3 length 3 x 64 *=* Unifies intermediate ports
Combinators (*=*) :: ( Port wL, Port x, Port sL, Port eL , Port wH, Port nH, Port eH ) => Circ wL x sL eL -> Circ wH nH x eH -> Circ (wL,wH) nH sL (eL,eH) (*||~) :: (Port w, Port n, Port s, Port e, Port x) => Circ w n s x -> Circ x [n] [s] e -> Circ w [n] [s] e (*=~) :: (Port w, Port n, Port s, Port e, Port x) => Circ w x s e -> Circ [w] n x [e] -> Circ [w] n s [e]
Patterns rowN :: (Port x, Port n, Port s) => Term Int -> Circ x n s x -> Circ x [n] [s] x rowN n circ = unintR n rowN' where nilY circ rowN' 0 = nilY rowN' n = circ *||~ rowN' (n-1) n row :: (Port y, Port n, Port s) => Circ y n s y -> Circ y [n] [s] y row circ = do cR <- free l <- lengthR $ north cR l <== (lengthR $ south cR) cR <== rowN l circ
Softening bitMultR :: (RLava.Signal, [RLava.Signal]) -> LP [RLava.Signal] bitMultR (x,as) = do ys <- sequence [free | _ <- as] -- Outputs (w,n,s,e) <- soften (bitMult `ofLengthX` term (length as)) w =:= ((),x) n =:= term [((a,()), ()) | a <- as] s =:= term [((),y) | y <- ys] return ys *Main> L.simulate (convert bitMultR) (L.high, [L.low, L.high]) [low,high]
Output ● Simulation, verification, synthesis: Wired → RLava → Lava ● Timing estimation: Wired → RLava ● Visualization: Wired → Postscript ● Real layout (not yet): Wired → ?? → GDS2
Case study: Prefix circuits Given inputs x 1 , x 2 , … x n compute y 1 = x 1 y 2 = x 1 ○ x 2 … y n = x 1 ○ x 2 ○ … ○ x n for ○, an associative (but not necessarily commutative) operator
Prefix circuits (2) ● Very central component in microprocessors ● Most common use: Computing carries in fast adders ● Trying different operators – Addition: prefix (+) [1,2,3,4]
Prefix circuits (2) ● Very central component in microprocessors ● Most common use: Computing carries in fast adders ● Trying different operators – Addition: prefix (+) [1,2,3,4] = [1, 1+2, 1+2+3, 1+2+3+4] = [1,3,6,10]
Prefix circuits (2) ● Very central component in microprocessors ● Most common use: Computing carries in fast adders ● Trying different operators – Addition: prefix (+) [1,2,3,4] = [1, 1+2, 1+2+3, 1+2+3+4] = [1,3,6,10] prefix (||) [F,F,F, T ,F, T , T ,F] – Boolean OR:
Prefix circuits (2) ● Very central component in microprocessors ● Most common use: Computing carries in fast adders ● Trying different operators – Addition: prefix (+) [1,2,3,4] = [1, 1+2, 1+2+3, 1+2+3+4] = [1,3,6,10] prefix (||) [F,F,F, T ,F, T , T ,F] – Boolean OR: = [F,F,F, T , T , T , T , T ]
Prefix circuits (3) Implementation choices (relying on associativity): prefix (○) [ x 1 , x 2 , x 3 , x 4 ] = [ y 1 , y 2 , y 3 , y 4 ] – Serial: y 4 = (( x 1 ○ x 2 ) ○ x 3 ) ○ x 4 – Parallel: y 4 = ( x 1 ○ x 2 ) ○ ( x 3 ○ x 4 ) – Sharing: y 4 = y 3 ○ x 4
Serial prefix (standard diagram) 1 2 … 7 8 operator 8 inputs depth 7 size 7 1 1:2 … 1:7 1:8
Parallel prefix (Sklansky) ● Serial: Fewer operators, linear logical depth ● Parallel: More operators, logarithmic depth
Sklansky in Lava sklansky op [a] = [a] sklansky op as = ls' ++ [op (last ls', r) | r <- rs'] where k = (length as + 1) `div` 2 (ls,rs) = splitAt k as ls' = sklansky op ls rs' = sklansky op rs
Sklansky in Lava sklansky op [a] = [a] sklansky op as = ls' ++ [op (last ls', r) | r <- rs'] where k = (length as + 1) `div` 2 (ls,rs) = splitAt k as ls' = sklansky op ls rs' = sklansky op rs
Abstract wires sklansky :: ((a,a) -> a) -> [a] -> [a] Can contain lots of concrete wires ● Need a notion of abstract wires in Wired ● These are called buses
Buses ● Generalization of wireX , wireY , wireLX , wireTX , cro ● Shape determined by context Example instance busT0 wireT0
Bus example bus :: Circ (Sig, Ins, (Sig,Sig)) Ins (Sig, Ins, (Sig,Sig)) (Sig, Ins, (Sig,Sig)) bus = busT0 `withConstraint` \cct -> do [a,b,c,d,e,f] <- replicateM 6 free west cct === tup3 (sig1 a) (Ins 60) (sig2 b c) south cct === tup3 (sig1 d) (Ins 90) (sig2 e f)
Sklansky in Wired sklansky 0 op opFO = rowN 1 $ nilX `withConstraint` \circ -> north circ <== (structure =<< asLP south =<< op) sklansky d op opFO = (joinL ~||~ joinR) *=~ (skl~||~skl) where skl = sklansky (d-1) op opFO n = term (2^(d-1) - 1) op' = op *=* alignLeft 4 opFO' = opFO *=* alignLeft 4 joinL = rowN n (busY*=*busY) ~||* (busT1*=*busY) joinR = rowN n opFO' ~||* op'
Sklansky with single-bit operator renderCircuit "circ" $ sklansky 3 dot1 dot1FO
Sklansky with pair operator renderCircuit "circ" $ sklansky 3 dot dotFO
Summary ● Haskell can alleviate manual design ● Being built on top of other libraries, Wired itself is quite a small library ● LP is the perfect foundation for RLava/Wired ● Read about LP and Wired: Matthew Naylor, Emil Axelsson and Colin Runciman. A Functional-Logic Library for Wired . HFL'07 http://www.cs.chalmers.se/~emax/wired/documents/LP_HFL07.pdf
Future work ● Clever generators ● Connection to realistic design flow ● More performance analyses – Power, cross-talk, etc.
Recommend
More recommend