final pass to update instruction encoding; should now match the spec
[fleet.git] / src / edu / berkeley / fleet / fpga / Generator.java
1 // note: got rid of funnel "fairness" code
2 package edu.berkeley.fleet.fpga;
3 import edu.berkeley.fleet.doc.*;
4 import edu.berkeley.fleet.api.*;
5 import edu.berkeley.fleet.ies44.*;
6 import edu.berkeley.fleet.*;
7 import java.lang.reflect.*;
8 import edu.berkeley.sbp.chr.*;
9 import edu.berkeley.sbp.misc.*;
10 import edu.berkeley.sbp.meta.*;
11 import edu.berkeley.sbp.util.*;
12 import java.util.*;
13 import java.io.*;
14 import static edu.berkeley.fleet.ies44.InstructionEncoder.*;
15
16 public class Generator {
17
18     public static final int WIDTH_PACKET = WIDTH_WORD + WIDTH_DEST_ADDR;
19
20     public static class SimpleValue implements Value {
21         private final String s;
22         public SimpleValue(String s) { this.s = s; }
23         public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; }
24         public Value getBits(int high, int low) { return new SimpleValue(s, high, low); }
25         public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
26         public String getVerilogName() { return s; }
27         public String toString() { return s; }
28     }
29
30     public static interface Action {
31         public String getVerilogAction();
32     }
33
34     public static interface Trigger {
35         public String getVerilogTrigger();
36     }
37
38     public static interface Assignable {
39         public String getVerilogName();
40         public Assignable getAssignableBits(int high, int low);
41     }
42
43     public static interface Value extends Assignable {
44         public String getVerilogName();
45         public Value getBits(int high, int low);
46     }
47
48     public static class ConditionalAction implements Action {
49         private String condition;
50         private Action action;
51         public ConditionalAction(String condition, Action action) {
52             this.condition = condition;
53             this.action = action;
54         }
55         public String toString() { return getVerilogAction(); }
56         public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; }
57     }
58
59     public static class ConditionalTrigger implements Trigger {
60         private String condition;
61         private Trigger trigger;
62         public ConditionalTrigger(String condition, Trigger trigger) {
63             this.condition = condition;
64             this.trigger = trigger;
65             if (trigger instanceof Module.Port)
66                 ((Module.Port)trigger).hasLatch = true;
67         }
68         public String getVerilogTrigger() {
69             return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)";
70         }
71     }
72
73     public static class SimpleAssignable implements Assignable {
74         private final String s;
75         public SimpleAssignable(String s) { this.s = s; }
76         public String getVerilogName() { return s; }
77         public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
78     }
79
80     public static class AssignAction implements Action {
81         private String left;
82         private String right;
83         public AssignAction(Assignable left, Value right) {
84             this.left = left.getVerilogName();
85             this.right = right.getVerilogName().toString();
86         }
87         public AssignAction(Assignable left, String right) {
88             this.left = left.getVerilogName();
89             this.right = right;
90         }
91         public String getVerilogAction() { return left + "<=" + right + ";"; }
92         public String toString() { return getVerilogAction(); }
93     }
94     
95     public static class SimpleAction implements Action {
96         private final String verilog;
97         public SimpleAction(String verilog) { this.verilog = verilog; }
98         public String getVerilogAction() { return verilog; }
99         public String toString() { return verilog; }
100     }
101
102     public static class Module {
103         private int id = 0;
104         private final String name;
105         public String getName() { return name; }
106         public Port getPort(String name) { return ports.get(name); }
107
108         private HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
109         private final ArrayList<Event> events = new ArrayList<Event>();
110
111         // FIXME: always-alphabetical convention?
112         private final HashMap<String,Port> ports = new HashMap<String,Port>();
113         private final ArrayList<String> portorder = new ArrayList<String>();
114         private final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
115         private final HashMap<String,Latch> latches = new HashMap<String,Latch>();
116         
117         private StringBuffer crap = new StringBuffer();
118         private StringBuffer precrap = new StringBuffer();
119         public void addCrap(String s) { crap.append(s); crap.append('\n'); }
120         public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
121
122         public Module(String name) {
123             this.name = name;
124         }
125
126         public SourcePort createInputPort(String name, int width) {
127             if (ports.get(name)!=null) throw new RuntimeException();
128             return new SourcePort(name, width, true);
129         }
130         public SourcePort getInputPort(String name) {
131             SourcePort ret = (SourcePort)ports.get(name);
132             if (ret==null) throw new RuntimeException();
133             return ret;
134         }
135         public SinkPort createOutputPort(String name, int width, String resetBehavior) {
136             if (ports.get(name)!=null) throw new RuntimeException();
137             return new SinkPort(name, width, true, resetBehavior);
138         }
139         public SinkPort getOutputPort(String name) {
140             SinkPort ret = (SinkPort)ports.get(name);
141             if (ret==null) throw new RuntimeException();
142             return ret;
143         }
144
145         private class StateWire {
146             public final String name;
147             public final boolean initiallyFull;
148             public String getName() { return name; }
149             public Action isFull()  { return new SimpleAction(name+"==1"); }
150             public Action isEmpty() { return new SimpleAction(name+"==0"); }
151             public Action doFill()  { return new SimpleAction(name+"<=1;"); }
152             public Action doDrain() { return new SimpleAction(name+"<=0;"); }
153             public StateWire(String name) { this(name, false); }
154             public StateWire(String name, boolean initiallyFull) {
155                 this.name = name;
156                 this.initiallyFull = initiallyFull;
157                 statewires.put(name, this);
158             }
159             public void dump(PrintWriter pw) {
160                 pw.println("  reg "+name+";");
161                 pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
162             }
163         }
164
165         public class Latch implements Assignable, Value {
166             public final String name;
167             public final int width;
168             public Latch(String name, int width) {
169                 this.width = width;
170                 this.name = name;
171                 latches.put(name, this);
172             }
173             public String getVerilogName() { return name; }
174             public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
175             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
176             public void dump(PrintWriter pw) {
177                 pw.println("  reg ["+(width-1)+":0] "+name+";");
178                 //pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
179             }
180         }
181
182         private abstract class Port implements Action, Assignable, Trigger {
183             public final String name;
184             public String getName() { return name; }
185             public final int width;
186             public int getWidth() { return width; }
187             public boolean hasLatch = false;
188             public boolean external;
189             public Port(String name, int width, boolean external) {
190                 this.width = width;
191                 this.name = name;
192                 this.external = external;
193                 ports.put(name, this);
194                 if (external)
195                     portorder.add(name);
196             }
197             public String getVerilogName() { return name; }
198             public String getAck() { return name+"_a"; }
199             public String getReq() { return name+"_r"; }
200             public abstract String getInterface();
201             public abstract String getSimpleInterface();
202             public abstract String getDeclaration();
203             public abstract String getAssignments();
204         }
205
206         private class InstantiatedModule {
207             public final Module module;
208             public final int id;
209             private final HashMap<String,Port> ports = new HashMap<String,Port>();
210             public String getName() { return module.getName()+"_"+id; }
211             public InstantiatedModule(Module module) {
212                 this.module = module;
213                 this.id = Module.this.id++;
214                 instantiatedModules.add(this);
215             }
216             public void dump(PrintWriter pw) {
217                 pw.println("  " + module.getName() + " " + getName() + "(clk");
218                 for(String s : module.portorder)
219                     pw.println(", " + getPort(s).getSimpleInterface());
220                 pw.println("   );");
221             }
222             public Port getPort(String name) {
223                 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
224             }
225             public SinkPort getInputPort(String name) {
226                 int width = module.getPort(name).getWidth();
227                 SinkPort port = (SinkPort)ports.get(name);
228                 if (port == null) {
229                     port = new SinkPort(getName()+"_"+name, width, false, "");
230                     ports.put(name, port);
231                 }
232                 return port;
233             }
234             public SourcePort getOutputPort(String name) {
235                 int width = module.getPort(name).getWidth();
236                 SourcePort port = (SourcePort)ports.get(name);
237                 if (port == null) {
238                     port = new SourcePort(getName()+"_"+name, width, false);
239                     ports.put(name, port);
240                 }
241                 return port;
242             }
243         }
244
245         private class SourcePort extends Port implements Value {
246             private SinkPort driven = null;
247             public SourcePort(String name, int width, boolean external) { 
248                 super(name, width, external); }
249             public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
250             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
251             public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
252             public String getVerilogAction() { return getAck() + " <= 1;"; }
253             public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
254             public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
255             public String getDeclaration() {
256                 StringBuffer sb = new StringBuffer();
257                 if (external) {
258                     sb.append("input "  +                 name +"_r;\n");
259                     sb.append("output " +                 name +"_a_;\n");
260                     sb.append("input ["+(width-1)+":0]" + name +";\n");
261                 } else {
262                     sb.append("wire "  +                 name +"_r;\n");
263                     sb.append("wire ["+(width-1)+":0]" + name +";\n");
264                 }
265                 if (!hasLatch) {
266                     sb.append("wire "    +                 name +"_a;\n");
267                 } else {
268                     sb.append("reg "    +                 name +"_a;\n");
269                     sb.append("initial " +                name +"_a = 0;\n");
270                 }
271                 return sb.toString();
272             }
273             public String getAssignments() {
274                 StringBuffer sb = new StringBuffer();
275                 if (external)
276                     sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
277                 if (driven != null) {
278                     sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
279                     sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
280                     sb.append("assign " + driven.name +"   = " + name + ";\n");
281                 }
282                 return sb.toString();
283             }
284             public void connect(SinkPort driven) {
285                 this.driven = driven;
286             }
287         }
288         private class SinkPort extends Port {
289             public final String resetBehavior;
290             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
291             public String getVerilogAction() { return getReq() + " <= 1;"; }
292             public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
293             public SinkPort(String name, int width, boolean external, String resetBehavior) {
294                 super(name, width, external); this.resetBehavior=resetBehavior; }
295             public String getResetBehavior() { return resetBehavior; }
296             public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
297             public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
298             public String getDeclaration() {
299                 StringBuffer sb = new StringBuffer();
300                 if (external) {
301                     sb.append("output "  +                 name +"_r_;\n");
302                     sb.append("input "   +                 name +"_a;\n");
303                     sb.append("output ["+(width-1)+":0]" + name +"_;\n");
304                 } else {
305                     sb.append("wire "   +                 name +"_a;\n");
306                 }
307                 if (!hasLatch) {
308                     sb.append("wire "    +                 name +"_r;\n");
309                     sb.append("wire   ["+(width-1)+":0]" + name +";\n");
310                 } else {
311                     sb.append("reg "    +                  name +"_r;\n");
312                     sb.append("initial " +                 name +"_r = 0;\n");
313                     sb.append("reg    ["+(width-1)+":0]" + name +";\n");
314                     sb.append("initial " +                 name +" = 0;\n");
315                 }
316                 return sb.toString();
317             }
318             public String getAssignments() {
319                 StringBuffer sb = new StringBuffer();
320                 if (external) {
321                     sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
322                     sb.append("assign " +                  name +"_ = " + name + ";\n");
323                 }
324                 return sb.toString();
325             }
326         }
327
328         public void dump(PrintWriter pw) {
329             pw.println("`include \"macros.v\"");
330             pw.println("module "+name+"(clk");
331             for(String name : portorder) {
332                 Port p = ports.get(name);
333                 pw.println("    , " + p.getInterface());
334             }
335             pw.println("   );");
336             pw.println();
337             pw.println("    input clk;");
338             for(String name : ports.keySet()) {
339                 Port p = ports.get(name);
340                 pw.println("    " + p.getDeclaration());
341             }
342             for(StateWire sw : statewires.values())
343                 sw.dump(pw);
344             for(Latch l : latches.values())
345                 l.dump(pw);
346             for(String name : ports.keySet()) {
347                 Port p = ports.get(name);
348                 pw.println("    " + p.getAssignments());
349             }
350             for(InstantiatedModule m : instantiatedModules) {
351                 m.dump(pw);
352             }
353             pw.println(precrap);
354             pw.println("always @(posedge clk) begin");
355             for(Port p : ports.values()) {
356                 if (p instanceof SourcePort) {
357                     SourcePort ip = (SourcePort)p;
358                     if (ip.hasLatch)
359                         pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
360                 } else {
361                     SinkPort op = (SinkPort)p;
362                     if (op.hasLatch)
363                         pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
364                                    op.getReq()+"<=0; "+
365                                    op.getResetBehavior()+" end");
366                 }
367             }
368
369             for(Event a : events) a.dump(pw);
370             pw.println(" begin end");
371             pw.println("end");
372
373             pw.println(crap);
374             pw.println("endmodule");
375         }
376
377         private class Event {
378             private Object[]  triggers;
379             private Object[]  actions;
380             public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
381             public Event(Object[] triggers, Object[] actions) {
382                 Module.this.events.add(this);
383                 this.triggers = triggers;
384                 this.actions = actions;
385                 for(int i=0; i<triggers.length; i++)
386                     if (triggers[i] instanceof Port)
387                         ((Port)triggers[i]).hasLatch = true;
388             }
389             public void dump(PrintWriter pw) {
390                 pw.print("if (1");
391                 for(Object o : triggers) {
392                     if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
393                     else                      pw.print(" && " + o);
394                 }
395                 pw.println(") begin ");
396                 for(Object a : actions) pw.println(((Action)a).getVerilogAction());
397                 pw.println("end else ");
398             }
399         }
400     }
401
402     public static void main(String[] s) throws Exception {
403         String prefix = s[0];
404         PrintWriter pw;
405
406         pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/bitfields.v")));
407         pw.println("`define DATAWIDTH                "+WIDTH_WORD);
408         pw.println("`define CODEBAG_SIZE_BITS        "+WIDTH_CODEBAG_SIZE);
409         pw.println("`define PUMP_ADDRESS_BITS    "+WIDTH_PUMP_ADDR);
410         pw.println("`define DESTINATION_ADDRESS_BITS "+WIDTH_DEST_ADDR);
411         pw.println("`define COUNT_BITS               "+WIDTH_COUNT);
412         pw.println("`define COUNT_WIDTH              "+WIDTH_COUNT);
413         pw.println("`define PACKET_WIDTH             (`DATAWIDTH + `DESTINATION_ADDRESS_BITS)");
414         pw.println("`define INSTRUCTION_WIDTH        "+WIDTH_WORD);
415         pw.println("`define packet_data(p)              p[(`DESTINATION_ADDRESS_BITS+`DATAWIDTH-1):(`DESTINATION_ADDRESS_BITS)]");
416         pw.println("`define packet_dest(p)              p[(`DESTINATION_ADDRESS_BITS-1):0]");
417         pw.println("`define instruction_data(p)         p[(`DATAWIDTH-1):0]");
418         pw.println("`define instruction_dest(p)         p["+(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1)+":"+OFFSET_PUMP_ADDR+"]");
419         pw.flush();
420         pw.close();
421
422         mkfunnel("funnel", prefix);
423         mkhorn(    "horn", prefix, WIDTH_PACKET-1, WIDTH_DEST_ADDR-1, 0, 0);
424         mkhorn(   "ihorn", prefix, WIDTH_PACKET-1, WIDTH_DEST_ADDR-1, 0, 0);
425
426         Module fifostage = mkfifo("fifostage", 0, null,      prefix);
427         Module fifo4     = mkfifo("fifo4",     4, fifostage, prefix);
428         Module fifoship  = mkfifo("fifo",      4, fifo4,     prefix);
429         mkBox("outbox", false, prefix, fifo4);
430         mkBox("inbox", true, prefix, fifo4);
431
432         Module fabric = new Module("fabric");
433         fabric.createInputPort("horn_in",     WIDTH_PACKET);
434         fabric.createOutputPort("funnel_out", WIDTH_PACKET, "");
435         mkRoot("root", prefix, fabric);
436     }
437
438     private static Module mkRoot(String name, String prefix, Module fabricm) throws Exception {
439         Module root = new Module(name);
440         Module.SourcePort  in  = root.createInputPort("in", 8);
441         Module.SinkPort    out = root.createOutputPort("out", 8, "");
442         Module.InstantiatedModule fabric = root.new InstantiatedModule(fabricm);
443         Module.SinkPort    fabric_in   = fabric.getInputPort("horn_in");
444         Module.SourcePort  fabric_out  = fabric.getOutputPort("funnel_out");
445         Module.Latch       count       = root.new Latch("count", 8);
446         Module.Latch       count_out   = root.new Latch("count_out", 8);
447         root.addPreCrap("initial count = 0;");
448         root.addPreCrap("initial count_out = 0;");
449         root.new Event(new Object[] { in, fabric_in },
450                        new Object[] { new SimpleAction(fabric_in.getName()+" <= ("+fabric_in.getName()+" << 8) | in;"),
451                                       new SimpleAction("if (count >= 5) begin count <= 0; "+fabric_in.getName()+"_r <= 1; end else count <= count+1; "),
452                                       in
453                        });
454         root.new Event(new Object[] { out, fabric_out },
455                        new Object[] { new SimpleAction(out.getName()+" <= ("+fabric_out.getName()+">> (count_out*8));"),
456                                       new SimpleAction("if (count_out >= 5) begin count_out <= 0; "+fabric_out.getName()+"_a <= 1; end else count_out <= count_out+1; "),
457                                       out });
458         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
459         root.dump(pw);
460         pw.flush();
461         return root;
462     }
463
464     private static Module mkfunnel(String name, String prefix) throws Exception {
465         Module funnel = new Module(name);
466         Module.SinkPort    out = funnel.createOutputPort("out", WIDTH_PACKET, "");
467         Module.SourcePort  in1 = funnel.createInputPort("in1", WIDTH_PACKET);
468         Module.SourcePort  in2 = funnel.createInputPort("in2", WIDTH_PACKET);
469         funnel.new Event(new Object[] { in1, out },
470                          new Action[] { in1, out,
471                                         new AssignAction(out, in1) });
472         funnel.new Event(new Object[] { in2, out },
473                          new Action[] { in2, out,
474                                         new AssignAction(out, in2) });
475         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
476         funnel.dump(pw);
477         pw.flush();
478         return funnel;
479     }
480
481     private static Module mkfifo(String name, int len, Module instance, String prefix) throws Exception {
482         Module fifo = new Module(name);
483         Module.SourcePort  in  = fifo.createInputPort("in", WIDTH_PACKET);
484         Module.SinkPort    out = fifo.createOutputPort("out", WIDTH_PACKET, "");
485         Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
486         if (len==0) {
487             fifo.new Event(new Object[] { in, out },
488                             new Action[] { in, out, new AssignAction(out, in) });
489         } else for(int i=0; i<=len; i++) {
490             if (i<len) stages[i] = fifo.new InstantiatedModule(instance);
491             Module.SourcePort driver = i==0 ? in : stages[i-1].getOutputPort("out");
492             Module.SinkPort   driven = i==len ? out : stages[i].getInputPort("in");
493             driver.connect(driven);
494         }
495         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
496         fifo.dump(pw);
497         pw.flush();
498         return fifo;
499     }
500
501     public static void mkhorn(String name, 
502                               String prefix,
503                               int top,
504                               int top_of_addr_field,
505                               int bot_of_addr_field,
506                               int bot) throws Exception {
507         Module horn = new Module(name);
508         Module.SourcePort in   = horn.createInputPort("in",    WIDTH_PACKET);
509         Module.SinkPort   out0 = horn.createOutputPort("out0", WIDTH_PACKET, "");
510         Module.SinkPort   out1 = horn.createOutputPort("out1", WIDTH_PACKET, "");
511         String shifted_packet = "{ ";
512         if (top_of_addr_field+1 < top) shifted_packet += " in["+top+":"+(top_of_addr_field+1)+"], ";
513         shifted_packet += " (in["+(top_of_addr_field)+":"+bot_of_addr_field+"] >> 1) ";
514         if (bot_of_addr_field > 0) shifted_packet += ",  in["+(bot_of_addr_field-1)+":0]  ";
515         shifted_packet += " }";
516         // same behavior as FLEET -- wait for both
517         horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" },
518                        new Action[] { in, out0, new AssignAction(out0, shifted_packet) });
519         horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" },
520                        new Action[] { in, out1, new AssignAction(out1, shifted_packet) });
521         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
522         horn.dump(pw);
523         pw.flush();
524     }
525
526     private static Module mkBox(String name, boolean inbox, String prefix, Module fifo) throws Exception {
527         Module box = new Module(name);
528         Module.SourcePort instr         = box.createInputPort("instr",       WIDTH_WORD);
529         Module.SourcePort fabric_in     = box.createInputPort("fabric_in",   WIDTH_PACKET);
530         Module.SinkPort   fabric_out    = box.createOutputPort("fabric_out", WIDTH_PACKET, "");
531         Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo);
532         fabric_in.connect(dfifo.getInputPort("in"));
533         
534         Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
535         Module.SourcePort   ship_out    = null;
536         if (!inbox) {
537             ship_out = box.createInputPort("ship",        WIDTH_WORD);
538             ship_out.hasLatch = true;
539         }
540
541         Module.SinkPort   ship_in     = null;
542         if (inbox) {
543             ship_in = box.createOutputPort("ship",        WIDTH_PACKET, "");
544             ship_in.hasLatch = true;
545         }
546
547         Module.Latch     ondeck         = box.new Latch("ondeck", WIDTH_WORD);
548         Module.Latch     repcount       = box.new Latch("repcount", WIDTH_COUNT);
549         Module.StateWire ondeckFull     = box.new StateWire("ondeck_full");
550         Module.StateWire newMayProceed  = box.new StateWire("newmayproceed", true);
551         Module.StateWire doRepeat       = box.new StateWire("dorepeat", false);
552         Module.StateWire doRepeatKill   = box.new StateWire("dorepeatkill", false);
553         Module.StateWire doKill         = box.new StateWire("dokill", false);
554         Module.StateWire isClogged      = box.new StateWire("clogged", false);
555         
556         Module.SinkPort   token_out     = fabric_out;
557         Module.SourcePort token_in      = dfifo_out;
558         Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
559         Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
560
561         Module.InstantiatedModule ififo = box.new InstantiatedModule(fifo);
562         Module.SinkPort   ififo_in      = ififo.getInputPort("in");
563         Module.SourcePort ififo_out     = ififo.getOutputPort("out");
564
565         Value instruction_count_ondeck        = ondeck  .getBits(OFFSET_COUNT+WIDTH_COUNT-1, OFFSET_COUNT);
566         Value instruction_count_instr         = instr   .getBits(OFFSET_COUNT+WIDTH_COUNT-1, OFFSET_COUNT);
567         Assignable instruction_count_ififo_in = ififo_in.getAssignableBits(OFFSET_COUNT+WIDTH_COUNT-1, OFFSET_COUNT);
568
569         // Clog (must be first)
570         box.new Event(
571                       new Object[] { ififo_out, newMayProceed.isFull(), "`instruction_is_clog("+ififo_out.getName()+")" },
572                       new Action[] { ififo_out, isClogged.doFill(), newMayProceed.doDrain() }
573                       );
574
575         // UnClog
576         box.new Event(
577                       new Object[] { instr, isClogged.isFull(), "`instruction_is_unclog(instr)" },
578                       new Action[] { instr, isClogged.doDrain(), newMayProceed.doFill()  }
579                       );
580
581         // First Kill
582         box.new Event(
583                       new Object[] { instr, ififo_out,
584                                      "`instruction_is_kill(instr)",
585                                      "!`instruction_is_unclog(instr)",
586                                      newMayProceed.isFull() },
587                       new Action[] { instr, ififo_out,
588                                      new ConditionalAction("`instruction_count(instr)!=0", new AssignAction(repcount, instruction_count_instr+"-1")),
589                                      new ConditionalAction("`instruction_count(instr)!=0", doRepeatKill.doFill()),
590                                      new ConditionalAction("`instruction_count(instr)!=0", newMayProceed.doDrain()),
591                                      new ConditionalAction("`instruction_count(instr)==0", newMayProceed.doFill())
592                       });
593
594         // Kill              
595         box.new Event(
596                       new Object[] { doKill.isFull() },
597                       new Action[] { doKill.doDrain(),
598                                      new ConditionalAction("`instruction_count(instr)!=0", new AssignAction(repcount, instruction_count_instr+"-1")),
599                                      new ConditionalAction("`instruction_count(instr)!=0", doRepeatKill.doFill()),
600                                      new ConditionalAction("`instruction_count(instr)==0", newMayProceed.doFill())
601                       });
602
603         // RepKill
604         box.new Event(
605                       new Object[] { doRepeatKill.isFull(), ififo_out },
606                       new Action[] { doRepeatKill.doDrain(), ififo_out, doKill.doFill(),
607                                      new AssignAction(instruction_count_ondeck, repcount) }
608                       );
609
610         // Enqueue
611         box.new Event(
612                       new Object[] { instr, ififo_in, "!`instruction_is_kill(instr)" },
613                       new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr)  }
614                       );
615
616         // New
617         box.new Event(
618                       new Object[] { ififo_out, ondeckFull.isEmpty(), newMayProceed.isFull() },
619                       new Action[] { ififo_out, ondeckFull.doFill(), newMayProceed.doDrain(),
620                                      new AssignAction(ondeck, ififo_out)  }
621                       );
622
623         // RepeatExecute
624         box.new Event(
625                       new Object[] { doRepeat.isFull() },
626                       new Action[] { doRepeat.doDrain(),
627                                      ondeckFull.doFill(),
628                                      new AssignAction(instruction_count_ondeck, repcount) }
629                       );
630
631         Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")");
632         String data_latch_input = inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName();
633
634         box.new Event(
635                       new Object[] { ondeckFull.isFull(),
636                                      data_out,
637                                      token_out,
638                                      ififo_in,
639                                      "(`instruction_is_normal(ondeck) || `instruction_is_literal(ondeck))",
640                                      new ConditionalTrigger("`instruction_bit_datain(ondeck)", data_in),
641                                      new ConditionalTrigger("`instruction_bit_tokenin(ondeck)", token_in)
642                               },
643                               new Action[] { new SimpleAction("ondeck_full<=0;"),
644                                              new ConditionalAction("`instruction_count(ondeck)==1 || `instruction_bit_requeue(ondeck)", newMayProceed.doFill()),
645                                              new ConditionalAction("`instruction_bit_requeue(ondeck) && `instruction_count(ondeck)!=1",
646                                                                    new AssignAction(ififo_in, ondeck)),
647                                              new ConditionalAction("`instruction_bit_requeue(ondeck) && `instruction_count(ondeck)!=1 && `instruction_count(ondeck)==0",
648                                                                    new AssignAction(instruction_count_ififo_in, "0")),
649                                              new ConditionalAction("`instruction_bit_requeue(ondeck) && `instruction_count(ondeck)!=1 && `instruction_count(ondeck)!=0",
650                                                                    new AssignAction(instruction_count_ififo_in, instruction_count_ondeck+"-1")),
651                                              new ConditionalAction("`instruction_bit_requeue(ondeck) && `instruction_count(ondeck)!=1", ififo_in),
652                                              new ConditionalAction("!`instruction_bit_requeue(ondeck) && `instruction_count(ondeck)!=1", doRepeat.doFill()),
653                                              new ConditionalAction("`instruction_count(ondeck)==0", new AssignAction(repcount, "0")),
654                                              new ConditionalAction("`instruction_count(ondeck)!=0", new AssignAction(repcount, instruction_count_ondeck+"-1")),
655                                              new ConditionalAction("`instruction_is_literal(ondeck)", new AssignAction(data_latch, "`instruction_literal(ondeck)")),
656                                              new ConditionalAction("`instruction_bit_datain(ondeck)", data_in),
657                                              new ConditionalAction("`instruction_bit_dataout(ondeck)", data_out),
658                                              new ConditionalAction("`instruction_bit_tokenin(ondeck)", token_in),
659                                              new ConditionalAction("`instruction_bit_tokenout(ondeck) && (!`instruction_bit_tokenoutlast(ondeck) || `instruction_count(ondeck)==1)",
660                                                                    token_out),
661                                              new ConditionalAction("`instruction_bit_latch(ondeck)", new AssignAction(data_latch, data_latch_input)),
662                                              new ConditionalAction("`instruction_bit_tokenout(ondeck)",
663                                                                    new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"),
664                                                                                     "`instruction_bit_dest(ondeck)")),
665                                              new ConditionalAction("`instruction_bit_dataout(ondeck) && !`instruction_bit_tokenout(ondeck)",
666                                                                    inbox ? new SimpleAction("")
667                                                                    : new AssignAction(new SimpleAssignable("`packet_dest("+data_out.getName()+")"),
668                                                                                       "`instruction_bit_dest(ondeck)")),
669                                              new ConditionalAction("`instruction_bit_dataout(ondeck) && `instruction_bit_tokenout(ondeck) && !`instruction_bit_datain(ondeck)",
670                                                                    inbox ? new SimpleAction("")
671                                                                    : new AssignAction(new SimpleAssignable("`packet_dest("+data_out.getName()+")"),
672                                                                                       data_out.getName()+"["+(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1)+":"+OFFSET_PUMP_ADDR+"]")),
673                                              new ConditionalAction("`instruction_bit_dataout(ondeck) && `instruction_bit_tokenout(ondeck) && `instruction_bit_datain(ondeck)",
674                                                                    inbox ? new SimpleAction("")
675                                                                    : new AssignAction(new SimpleAssignable("`packet_dest("+data_out.getName()+")"),
676                                                                                       data_latch_input+"["+(OFFSET_PUMP_ADDR+WIDTH_PUMP_ADDR-1)+":"+OFFSET_PUMP_ADDR+"]"))
677                               }
678                       );
679
680         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
681         pw.println("`define instruction_bit_dest(instruction)     instruction["+(OFFSET_DEST+WIDTH_DEST_ADDR-1)+":"+OFFSET_DEST+"]");
682         pw.println("`define instruction_count(instruction)        instruction["+(OFFSET_COUNT+WIDTH_COUNT-1)+":"+OFFSET_COUNT+"]");
683         pw.println("`define instruction_is_literal(i)             (i["+(OFFSET_MASK_LITERAL+WIDTH_MASK_LITERAL-1)+":"+OFFSET_MASK_LITERAL+"]=="+MASK_LITERAL+")");
684         pw.println("`define instruction_is_kill(i)                (i["+(OFFSET_MASK_KILL+WIDTH_MASK_KILL-1)+":"+OFFSET_MASK_KILL+"]=="+MASK_KILL+")");
685         pw.println("`define instruction_is_unclog(i)              (i["+(OFFSET_MASK_UNCLOG+WIDTH_MASK_UNCLOG-1)+":"+OFFSET_MASK_UNCLOG+"]=="+MASK_UNCLOG+")");
686         pw.println("`define instruction_is_clog(i)                (i["+(OFFSET_MASK_CLOG+WIDTH_MASK_CLOG-1)+":"+OFFSET_MASK_CLOG+"]=="+MASK_CLOG+")");
687         pw.println("`define instruction_is_normal(i)              (i["+(OFFSET_MASK_NORMAL+WIDTH_MASK_NORMAL-1)+":"+OFFSET_MASK_NORMAL+"]=="+MASK_NORMAL+")");
688         pw.println("`define instruction_bit_requeue(instruction)  (instruction["+OFFSET_RQ+"] || `instruction_is_literal(instruction))");
689
690         pw.println("`define instruction_bit_tokenout(i)     (!`instruction_is_literal(i) && i["+OFFSET_TO+"])");
691         pw.println("`define instruction_bit_tokenoutlast(i) (!`instruction_is_literal(i) && i["+OFFSET_IG+"])");
692         pw.println("`define instruction_bit_dataout(i)      (!`instruction_is_literal(i) && i["+OFFSET_DO+"])");
693         pw.println("`define instruction_bit_latch(i)        (!`instruction_is_literal(i) && i["+OFFSET_DL+"])");
694         pw.println("`define instruction_bit_datain(i)       (!`instruction_is_literal(i) && i["+OFFSET_DI+"])");
695         pw.println("`define instruction_bit_tokenin(i)      (!`instruction_is_literal(i) && i["+OFFSET_TI+"])");
696
697         int signextbits = WIDTH_WORD - WIDTH_LITERAL;
698         pw.println("`define instruction_literal(i)                {{ "+signextbits+"{i["+(OFFSET_LITERAL+WIDTH_LITERAL-1)+"]}},"+
699                    " i["+(OFFSET_LITERAL+WIDTH_LITERAL-1)+":"+OFFSET_LITERAL+"]}");
700         box.dump(pw);
701         pw.flush();
702         return box;
703     }
704
705 }
706
707
708
709