300 likes | 410 Views
Access to Circuit Generators in Embedded HDLs. Gordon Pace Christian Tabone University of Malta March 2008. As circuits grow in size, we require more abstract techniques for concise descriptions. The circuits generated by these abstract descriptions are then typically analysed .
E N D
Access to Circuit Generators in Embedded HDLs Gordon Pace Christian Tabone University of Malta March 2008
As circuits grow in size, we require more abstract techniques for concise descriptions. The circuits generated by these abstract descriptions are then typically analysed. But the circuits generators themselves contain a lot of potentially useful information: Circuit structure ‘Similar’ families of structured descriptions Circuit transformations Introduction
Embedded Languages for h/w Design • Embedding a HDL in a general-purpose language provides a meta-language to the HDL. Host Language Embedded language • Creating basic components • Component composition • Access to components • etc
Embedded Languages for h/w Design • Embedding a HDL in a general-purpose language provides a meta-language to the HDL. Host Language Embedded language Circuit generators • Creating basic components • Component composition • Access to components • etc Circuit analysis Circuit transformations
Functional View of Circuits: Lava, Hydra, Hawk… • Circuits are described and used as functions: adder 1 (cin, ([a],[b])) = …. adder n (cin, (as,bs)) = …. where n’ = n `div` 2 (ss1, cmid) = adder n’ (cin, (as1, bs1)) (ss20, cout0) = adder (n-n’) (low, (as2, bs2)) (ss21, cout1) = adder (n-n’) (high, (as2, bs2)) ss2 = mux (cmid, (ss20, ss21)) cout = mux (cmid, (cout0, cout1))
Functional View of Circuits: Lava, Hydra, Hawk… Circuits are described and used as functions: The description induces a hierarchical structure, grouping gates together (ones produced by the same call), which is lost adder 1 (cin, ([a],[b])) = …. adder n (cin, (as,bs)) = (ss1++ss2, cout) where n’ = n `div` 2 (ss1, cmid) = adder n’ (cin, (as1, bs1)) (ss20, cout0) = adder (n-n’) (low, (as2, bs2)) (ss21, cout1) = adder (n-n’) (high, (as2, bs2)) ss2 = mux (cmid, (ss20, ss21)) cout = mux (cmid, (cout0, cout1))
Functional View of Circuits: Lava, Hydra, Hawk… Circuits are described and used as functions: adder 1 (cin, ([a],[b])) = …. adder n (cin, (as,bs)) = …. where n’ = n `div` 2 (ss1, cmid) = adder n’ (cin, (as1, bs1)) (ss20, cout0) = adder (n-n’) (low, (as2, bs2)) (ss21, cout1) = adder (n-n’) (high, (as2, bs2)) ss2 = mux (cmid, (ss20, ss21)) cout = mux (cmid, (cout0, cout1)) There is no way in which we can access information about the parametrised circuit adder as a family of circuits to analyse/reason about them as a single class
Block View of Circuits: Wired • Circuits are viewed as objects, which can have their ports wired together explicitly or through combinators: sklansky op 1 = idWire sklansky op k = left ~||~ right where half_k = k `div` 2 left = forkLast (sklansky op half_k) right = extend op (sklansky op half_k)
Block View of Circuits: Wired Information about blocks is kept thanks to the use of combinators to glue circuits together. This information can be useful for placement, delay analysis, etc. • Circuits are viewed as objects, which can have their ports wired together explicitly or through combinators: sklansky op 1 = idWire sklansky op k = left ~||~ right where half_k = k `div` 2 left = forkLast (sklansky op half_k) right = extend op (sklansky op half_k)
Block View of Circuits: Wired The enforced use of combinators to keep placement information makes it more awkward to use than the functional approach • Circuits are viewed as objects, which can have their ports wired together explicitly or through combinators: sklansky op 1 = idWire sklansky op k = left ~||~ right where half_k = k `div` 2 left = forkLast (sklansky op half_k) right = extend op (sklansky op half_k)
Block View of Circuits: Wired • Circuits are viewed as objects, which can have their ports wired together explicitly or through combinators: We still have no way of accessing the family of circuits encoded in the sklansky (or sklansky op n) function. sklansky op 1 = idWire sklansky op k = left ~||~ right where half_k = k `div` 2 left = forkLast (sklansky op half_k) right = extend op (sklansky op half_k)
HDLs Embedded in Meta-Languages • One possible solution is to use a meta-language as a host language. • Circuit generators can be quoted and would then be considered just like any other data object. • Delaying circuit application gives us the structure induced by the description without losing the functional view of circuits. • But at a cost: complexity of the host programming language. • Can the use of reflection features be limited to (hidden) inside of the embedded language?
reFLect • Developed by Intel specifically for applications in hardware design and verification. • Strongly typed functional language with meta-programming features. • reFLect programs are able to examine, modify or create other reFLect programs as data objects.
Composing Circuit Representations • Meta-constructs are used to provide a structural representation of the circuits. • Primitive gates decompose the input to obtain the required signals, and constructs the respective object program. let inv (Signal {| `a |}) = Signal {| NOT `a |}; let and2 (Signal {| (`a, `b) |} = Signal {| `a AND `b |};
Representing Signals • The inputs and outputs can be modelled as: • A structure of signals each containing a single bit • A single signal consisting of a structure of bits • Current implementation uses a signal of structures representation • Simple design • One common type • Overhead code zipp unzipp Signal Signal *a *a Signal *b *b
Circuit Descriptions let muxs_ab = val (s, ab) = unzipps_ab in val (a, b) = unzippab in or2 (zipp (and2 (zipp (inv s, a)), and2 (zipp (s, b)))); : mux (zipp (low, zipp (low, high))); Signal {| ((NOT low) AND low) OR (low AND high) |}
Marking Circuit Blocks • Circuit descriptions are defined as modular functions by the designer, but the internal structure discards the boundaries of sub-functions resulting in a netlist of interconnected gates. s n0 c0 c1 c2 c3 c4 n1
Marking Circuit Blocks let makeBlock circuit = let vars = genInputVariables circuit in let fnct = circuit vars in \(Signal inp) . {| (\`vars . `fnct) `inp |};
Marking Circuit Blocks let muxBlk = makeBlockmux; : muxBlk(zipp (low, zipp (low, high))); Signal {| (\(v1,(v2,v3)) . ((NOT v1) AND v2) OR (v1 AND v3)) (low, (low, high)) |} (\(v1,(v2,v3)) . ((NOT v1) AND v2) OR (v1 AND v3))
Marking Circuit Blocks The structure of the described circuit is retained as a function, and not simply as an unevaluated expression let muxBlk = makeBlockmux; : muxBlk(zipp (low, zipp (low, high))); Signal {| (\(v1,(v2,v3)) . ((NOT v1) AND v2) OR (v1 AND v3)) (low, (low, high)) |} (\(v1,(v2,v3)) . ((NOT v1) AND v2) OR (v1 AND v3))
Prefix Circuits: Sklansky letrecskl n op inp = let skl' 1 op inps = inps /\ skl' n op inps = val (lst,rst) = unzipp (splitSignalBus n inps) in let ls2 = skl (busLengthlst) op lst in let rs2 = skl (busLengthrst) op rst in let carry = lastSignal ls2 in let apply r = op (zipp (carry, r)) in zipp (ls2 @ map apply rs2) in makeBlock (skl' n op) inp;
Related Work: reFLectHDL • An HDL embedded in reFLect similar to Lava. • The reflection features of reFLect are used to provide access to the circuit structure. • The meta-programming constructs are not concealed. • No relationship is maintained between the generator and the circuit. • No hierarchical structure of sub-functions (blocks) • No access to a single class of “family of circuits”
Related Work: DUAL-EVAL • The Lisp quotation is used to mark module boundaries thus delaying the evaluation. • Modules are a block representation. (HALF-ADDER*) = `(HALF-ADDER (A B) (SUM CARRY) (( G0 (SUM) B-XOR (A B)) ( G1 (CARRY) B-AND (A B))) NIL)
Hardware Compilers • We are looking into the use of these techniques for hardware compilers. • Access to structure enables: • Generating placement hints • Post-compilation optimisations • Access to the generator (compiler) gives us means of: • Analysing the generator in general • Proving compiler invariants automatically using structural induction on the input program.
Placement Hints • We are looking into means of introducing placement hints for blocks. • Clustering/grouping of blocks is already possible, but we are looking into adding Ruby/Pebble/Wired-style placement information. • Such hints will accompany, not replace, the functional descriptions.
Modular Verification • Access to generators enabling: • Parametrised circuit verification. • Proving properties of circuit combinators (eg commutativity of certain h/w compiler cases). • Structural analysis: • Enables tagging of properties of subcircuits. • Allow assume-guarantee style reasoning for circuit analysis.
Conclusions • Techniques enabling abstract descriptions of circuits should provide techniques to analyse: • not only the circuits, • but also the generation structrure, and • the abstract generators/transformers. • Meta-programming seems to be providing the necessary infrastructure to enrich embedded languages with this. • But we’d much rather keep as much of this hidden beneath the bonnet.