250 likes | 399 Views
Direct Synthesis of Hardware Designs Using a SAT Solver. Dr David Greaves University of Cambridge Computer Laboratory http://www.cl.cam.ac.uk/users/djg. RSP 2004 Geneva. (C) 2004 IEEE Computer Society. System Design is a planning problem We deploy resources in time and space
E N D
Direct Synthesis of Hardware Designs Using a SAT Solver Dr David Greaves University of Cambridge Computer Laboratory http://www.cl.cam.ac.uk/users/djg RSP 2004 Geneva (C) 2004 IEEE Computer Society
System Design is a planning problem • We deploy resources in time and space • Meet the design constraints • Don’t use too many resources • Formal proof of correctness nice to have • Synthesis from Formal Spec ? • Good idea provided we can freely mix with conventional design approaches • When designing a transmitter/receiver pair less actually needs to be specified.
Two Major Approaches • Stepwise refinement from Formal Spec ? • Oft been mooted • Hard to control in practice (mixing ?) • Ultimately ‘Syntax-directed’ • Automatic Assembly of Parts ? • Much larger search space • A huge potential spectrum of algorithms • Modular approach assists engineering.
H/W Design Using SAT ? • SAT solvers today handle • 1000’s of clauses • 100’s of variables • Take a few minutes to run • Generate a stream of 1’s and 0’s that meet a goal • An FPGA • Embodies a hardware design • Is programmed by a stream of 1’s and 0’s
A first approach... • Define an FPGA in RTL with many free variables - the ‘fuses’. • Express a design as any mixture of • Regular RTL • Further RTL that refers to nets in the FPGA • Logical assertions over the nets and their future states • Form the conjunction of the assertions viewing the RTL as a macro expansion language. • SAT-solve the resulting formula quantified over all free variable settings. • Back-substitute the solution into the FPGA • Simplify the result using logic trimming identities • Disconnected logic • Boolean identities
FPGA Definition • Can use a full crossbar FPGA • Not constrained by 2-D wiring X(s1) := XFUN(‘xs1’, s1, s2, …, sn, D); X(s2) := XFUN(‘xs2’, s1, s2, …., sn, D); … := … … … … … X(sn) := XFUN(‘xsn’, s1, s2, …., sn, D); XFUN macro expands to a LUT of 2**(n + |D|) fuses. ‘D’ denotes inputs to this local structure. Global clock is implied.
Future State Projection • Assertions can refer to • current state: v • next state: X(v) • future state: X(v, n) n >= 2 X(a|b, n) is expanded to X(a, n) | X(b, n) X(s1, n+1) is expanded to XFUN(‘xs1’, X(s1,n), … X(D, n)) X(D) is not constrained so is further free vars for universal quantification.
Conversion to CNF • Normally an Exponential Blow Up Problem! • Avoid with new intermediate variables (nv) (a + b + l.r) can be converted with three new clauses: (a + b + nv) (a + !l + !r) (!nv + l) (!nv + r) This first new clause can be dropped without affecting SAT. Preserves NNF.
Universal Quantification • Our assertions must hold for all settings of the free variables (current state and current and future inputs). • Form conjunction over all settings …. A new exponential blow up! • Also the ‘nv’ variables need to be skolemised. • Perhaps some input don’t cares or won’t happen vectors reduce the expansion. • Divide clauses into disjoint support sets and quantify each set separately.
Examples: Cambridge Ring, Transputer. One bit per baud over two wires Here we let SAT chose the protocol Example 1: Two Rail Signaling
Transmitter //-------------------------- // Transmitter encoder // Encoder state node bool: s0, tx1, tx2; X(tx1) := XFUN("xtx1", din, tx1, s0); X(tx2) := XFUN("xtx2", din, tx2, s0); X(s0) := XFUN("xtxs", din, tx1, tx2, s0); // Transmitter Constraints - we require a change on at least //one of the two lines. always tx1 != X(tx1) \/ tx2 != X(tx2);
Channel Model //-------------------------- // Channel Model // This two wire channel may be permanently // swapped and/or inverted in one half or the other. node bool: rx1, rx2, ch_inv1, ch_inv2, ch_swap; X(ch_inv1) := ch_inv1; // These assigns mean that X(ch_inv2) := ch_inv2; // the initial value of this variable is not known X(ch_swap) := ch_swap; // but that it will not change. X(rx1) := ((ch_swap) ? tx1:tx2) ^ ch_inv1; X(rx2) := ((ch_swap) ? tx2:tx1) ^ ch_inv2;
Receiver //-------------------------- // Receiver decoder node bool: srx, sry; X(dout) := XFUN("xDOUT", rx1, rx2, dout, srx, sry); X(srx) := XFUN("xSRX", rx1, rx2, dout, srx, sry); X(sry) := XFUN(“xSRY”, rx1, rx2, dout, srx, sry); node bool: match0, match1, match2, match3, working; match1 := X(dout,1) == din; match2 := X(dout,2) == din; match3 := X(dout,3) == din; node bool: xdel0, xdel1; working := (xdel1) ? match3: (xdel0) ? match1 : match2; always working;
Solvers Tried • Chaff Version Spelt 3 • Walksat • A homebrew BDD package SAT DIMACS file size approximately 500 kilobytes. All three solvers solved or failed identically on all problems tried.
A Conventional Solution • As used on CR82.
Example 2: MFM RLL Coding • Encoder and Decoder are again simple FPGAs • Data needs only be transmitted every-other baud interval (clock cycle). // Run length limitation - // max of three consecutive zeros. always ~A => (X(A) \/ X(A, 2) \/ X(A, 3));
MFM Receiver Spec node bool: phaser; X(phaser) := XFUN("xphix", phaser); always X(phaser) == ~phaser; node bool: match0, match1, match2, match3, match4; match0 := din == dout; match1 := din == X(dout); match2 := din == X(dout, 2); match3 := din == X(dout, 3); match4 := din == X(dout, 4); working := .. as before ; always (phaser \/ working); MFM only needs convey a data bit every other baud interval.
Example 2: Failure • The MFM design could not be solved • There is no solution that does not have a start up transient ? • Need a method of modeling system start.
StartupIssuesExaminedExample: NRZI Implementation A - One cycle of delay Implementation B - Not valid at SOD.
Implementation A This works, but has one cycle of delay. Implementation B No solution can be found. X(N, -1) cannot be taken to be equal to another occurrence of X(N, -1) NRZI Illustation:
Adding A Phantom Reset Guard node bool: reset_0, reset_1, resetting; initial reset_0 == 1 && reset_1 == 1; X(reset_0) := 0; X(reset_1) := reset_0; resetting := reset_0 | reset_1; … ... guts of design are unchanged ... always resetting \/ working; We can now use a model checker to generate an expression for SAT solving. The SAT solution holds in all reachable states. The reset nets are purely phantoms - they do not appear in the real hardware. (Also, we might support error-recovery specifications)
Conclusions • A novel approach for a few hundred fuses. • But perhaps constrained to small glue-logic situations ? • Designs larger than the dual rail fail during conversion to CNF (heap explodes) • Better algorithms ? • Use the approach at each tier in a tree ? Thankyou!