package jazz.circuit.esterel; ////////////////////////////////////////////////////////////////////////////// // // Compilation of Pure Esterel programs // ////////////////////////////////////////////////////////////////////////////// import jazz.circuit.*; import jazz.circuit.expr.*; import jazz.circuit.expr.BoolExpr.*; import jazz.unsafe.Hashtable; require jazz.util; ////////////////////////////////////////////////////////////////////////////// // // Compilation environment // ////////////////////////////////////////////////////////////////////////////// final class Env { c: BoolExpr; // Incoming control wire s: BoolExpr; // Selection wire a: BoolExpr; // Activation wire i: BoolExpr; // Inhibition wire c0: BoolExpr; // Termination wire c1: BoolExpr; // Halting wire n: int; // Number of exit wires C: BoolExpr[n]; // Exit wires S: fun(String): BoolExpr; // Input and output signal wires T: fun(String): int; // Trap environment } ////////////////////////////////////////////////////////////////////////////// // // Compilation of a module // ////////////////////////////////////////////////////////////////////////////// compile@Module()(innets) = ( sigtovar.assoc(in)(insig, invars) ; sigtovar.assoc(out)(outsig, outvars) ; stmt.compile(env) ; instanciate([i -> S(outsig[i])]) (invalues, Net.reg, Net.constant)) { // Input signals in = inputs.length(); insig = [i -> inputs.nth(i)]; // Output signals out = outputs.length(); outsig = [i -> outputs.nth(i)]; // Boot boot = newInput(0); // Zero zero = newInput(1); // One one = newInput(2); // Dummy local wire for the initial environment dummy = newLocal(); // Association of input signals names to Net expression input variables invars = [i -> newInput(i + 3)]; // Association of output signal names to local Net expression variables outvars = [i -> newLocal()]; // Hashtable mapping signal names to Net variables sigtovar = Hashtable.create(); fun S(name) = (BoolExpr) sigtovar.get(name, error("undefined signal: %s", name)); // Empty trap environment fun T(sig) = error("trap signal \"%s\" undefined", sig); // Input values of the circuit invalues[0] = ~Net.reg(Net.constant(#(1))); invalues[1] = Net.constant(#(0)); invalues[2] = Net.constant(#(1)); invalues[3..] = innets; // Initial environment env = new Env(c = boot, s = one, a = one, i = zero, c0 = dummy, c1 = dummy, n = 0, C = [], S = S, T = T); } ////////////////////////////////////////////////////////////////////////////// // // Compilation rules for statements // ////////////////////////////////////////////////////////////////////////////// compile@NothingStmt(env) = env.c0.setOr(env.c); compile@HaltStmt(env) = ( env.c1.setOr(x) ; env.s.setOr(s') ; s'.setEq(reg(x & ~env.i)) ) { s' = newLocal(); x = env.c | env.a & env.s; } compile@SequenceStmt(env) = ( stmt1.compile(env1) ; stmt2.compile(env2) ) { c' = newLocal(); env1 = env.clone(c0 = c'); env2 = env.clone(c = c'); } compile@EmitStmt(env) = ( S.setOr(env.c) ; env.c0.setOr(env.c) ) { S = env.S(sig); } compile@LoopStmt(env) = ( c'.setEq(env.c) ; stmt.compile(env')) { c' = newLocal(); env' = env.clone(c = c', c0 = c'); } compile@PresentStmt(env) = ( c1.setEq(env.c & S) ; c2.setEq(env.c & ~S) ; stmt1.compile(env1) ; stmt2.compile(env2) ) { S = env.S(sig); c1 = newLocal(); c2 = newLocal(); env1 = env.clone(c = c1); env2 = env.clone(c = c2); } compile@WatchStmt(env) = ( env.s.setOr(s') ; a'.setEq(env.a & env.s & ~S) ; env.c0.setOr(env.a & env.s & S) ; stmt.compile(env') ) { S = env.S(sig); s' = newLocal(); a' = newLocal(); env' = env.clone(s = s', a = a'); } compile@TrapStmt(env) = stmt.compile(env') { env' = env.clone(n = env.n + 1, C = [env.c0, i -> env.C[i-1]], T = T); fun T(sig) = (sig == sig) ? 0 : 1 + env.T(sig); } compile@ExitStmt(env) = env.C[env.T(sig)].setOr(env.c); compile@SignalStmt(env) = stmt.compile(env); compile@ParallelStmt(env) = ( env.s.setOr(s') ; i'.setEq(n <= 3 ? env.i : env.i | p[2]) ; eval(n)([k -> c[k].setOr(cdef[k])]) ; eval(n - 1)([k -> p[k].setEq(pdef[k])]) ; stmt1.compile(env') ; stmt2.compile(env') ) { // Locals s' = newLocal(); i' = newLocal(); c' = [i -> newLocal()]; p = [i -> newLocal()]; // Definitions n = env.n + 2; c = [env.c0, env.c1, i -> env.C[i - 2]]; cdef[n - 1] = c'[n - 1]; for (k < n - 1) { cdef[k] = c'[k] & ~p[k]; } pdef[n - 2] = c'[n - 1]; for (k < n - 2) { pdef[k] = c'[k + 1] & ~p[k + 1]; } // New environment env' = env.clone(s = s', i = i', c0 = c'[0], c1 = c'[1], C = c'[2..]); // Sequential evaluation fun eval(n)(x) = eval(0) { fun eval(k) = (k == n) ? () : (x[k]; eval(k+1)); } }