major overhaul: update dock to am33
[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_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+"=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, boolean fix) {
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, fix);
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, boolean fix) {
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                 if (fix) pw.println("end /*else*/ ");
398                 else     pw.println("end else ");
399             }
400         }
401     }
402
403     public static void main(String[] s) throws Exception {
404         String prefix = s[0];
405         PrintWriter pw;
406
407         pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/bitfields.v")));
408         pw.println("`define DATAWIDTH                "+WIDTH_WORD);
409         pw.println("`define CODEBAG_SIZE_BITS        "+WIDTH_CODEBAG_SIZE);
410         pw.println("`define PUMP_ADDRESS_BITS    "+WIDTH_ADDR);
411         pw.println("`define DESTINATION_ADDRESS_BITS "+WIDTH_ADDR);
412         /*
413         pw.println("`define COUNT_BITS               "+WIDTH_COUNT);
414         pw.println("`define COUNT_WIDTH              "+WIDTH_COUNT);
415         */
416         pw.println("`define PACKET_WIDTH             (`DATAWIDTH + `DESTINATION_ADDRESS_BITS)");
417         pw.println("`define INSTRUCTION_WIDTH        "+WIDTH_WORD);
418         pw.println("`define packet_data(p)              p[(`DESTINATION_ADDRESS_BITS+`DATAWIDTH-1):(`DESTINATION_ADDRESS_BITS)]");
419         pw.println("`define packet_dest(p)              p[(`DESTINATION_ADDRESS_BITS-1):0]");
420         pw.println("`define instruction_data(p)         p[(`DATAWIDTH-1):0]");
421         pw.println("`define instruction_dest(p)         "+PUMP_NAME.verilogVal("p"));
422         pw.flush();
423         pw.close();
424
425         mkfunnel("funnel", prefix);
426         mkhorn(    "horn", prefix, WIDTH_PACKET-1, WIDTH_ADDR-1, 0, 0);
427         mkhorn(   "ihorn", prefix, WIDTH_PACKET-1, WIDTH_ADDR-1, 0, 0);
428
429         Module fifostage = mkfifo("fifostage", 0, null,      prefix);
430         Module fifo4     = mkfifo("fifo4",     4, fifostage, prefix);
431         Module fifo8     = mkfifo("fifo8",     8, fifostage, prefix);
432         Module fifoship  = mkfifo("fifo",      4, fifo4,     prefix);
433         mkBox("outbox", false, prefix, fifo4, fifo8);
434         mkBox("inbox", true, prefix, fifo4, fifo8);
435
436         Module fabric = new Module("fabric");
437         fabric.createInputPort("horn_in",     WIDTH_PACKET);
438         fabric.createOutputPort("funnel_out", WIDTH_PACKET, "");
439         mkRoot("root", prefix, fabric);
440     }
441
442     private static Module mkRoot(String name, String prefix, Module fabricm) throws Exception {
443         Module root = new Module(name);
444         Module.SourcePort  in  = root.createInputPort("in", 8);
445         Module.SinkPort    out = root.createOutputPort("out", 8, "");
446         Module.InstantiatedModule fabric = root.new InstantiatedModule(fabricm);
447         Module.SinkPort    fabric_in   = fabric.getInputPort("horn_in");
448         Module.SourcePort  fabric_out  = fabric.getOutputPort("funnel_out");
449         Module.Latch       count       = root.new Latch("count", 8);
450         Module.Latch       count_out   = root.new Latch("count_out", 8);
451         root.addPreCrap("initial count = 0;");
452         root.addPreCrap("initial count_out = 0;");
453         root.new Event(new Object[] { in, fabric_in },
454                        new Object[] { new SimpleAction(fabric_in.getName()+" <= ("+fabric_in.getName()+" << 8) | in;"),
455                                       new SimpleAction("if (count >= 5) begin count <= 0; "+fabric_in.getName()+"_r <= 1; end else count <= count+1; "),
456                                       in
457                        });
458         root.new Event(new Object[] { out, fabric_out },
459                        new Object[] { new SimpleAction(out.getName()+" <= ("+fabric_out.getName()+">> (count_out*8));"),
460                                       new SimpleAction("if (count_out >= 5) begin count_out <= 0; "+fabric_out.getName()+"_a <= 1; end else count_out <= count_out+1; "),
461                                       out });
462         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
463         root.dump(pw, true);
464         pw.flush();
465         return root;
466     }
467
468     private static Module mkfunnel(String name, String prefix) throws Exception {
469         Module funnel = new Module(name);
470         Module.SinkPort    out = funnel.createOutputPort("out", WIDTH_PACKET, "");
471         Module.SourcePort  in1 = funnel.createInputPort("in1", WIDTH_PACKET);
472         Module.SourcePort  in2 = funnel.createInputPort("in2", WIDTH_PACKET);
473         funnel.new Event(new Object[] { in1, out },
474                          new Action[] { in1, out,
475                                         new AssignAction(out, in1) });
476         funnel.new Event(new Object[] { in2, out },
477                          new Action[] { in2, out,
478                                         new AssignAction(out, in2) });
479         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
480         funnel.dump(pw, true);
481         pw.flush();
482         return funnel;
483     }
484
485     private static Module mkfifo(String name, int len, Module instance, String prefix) throws Exception {
486         Module fifo = new Module(name);
487         Module.SourcePort  in  = fifo.createInputPort("in", WIDTH_PACKET);
488         Module.SinkPort    out = fifo.createOutputPort("out", WIDTH_PACKET, "");
489         Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
490         if (len==0) {
491             fifo.new Event(new Object[] { in, out },
492                             new Action[] { in, out, new AssignAction(out, in) });
493         } else for(int i=0; i<=len; i++) {
494             if (i<len) stages[i] = fifo.new InstantiatedModule(instance);
495             Module.SourcePort driver = i==0 ? in : stages[i-1].getOutputPort("out");
496             Module.SinkPort   driven = i==len ? out : stages[i].getInputPort("in");
497             driver.connect(driven);
498         }
499         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
500         fifo.dump(pw, true);
501         pw.flush();
502         return fifo;
503     }
504
505     public static void mkhorn(String name, 
506                               String prefix,
507                               int top,
508                               int top_of_addr_field,
509                               int bot_of_addr_field,
510                               int bot) throws Exception {
511         Module horn = new Module(name);
512         Module.SourcePort in   = horn.createInputPort("in",    WIDTH_PACKET);
513         Module.SinkPort   out0 = horn.createOutputPort("out0", WIDTH_PACKET, "");
514         Module.SinkPort   out1 = horn.createOutputPort("out1", WIDTH_PACKET, "");
515         String shifted_packet = "{ ";
516         if (top_of_addr_field+1 < top) shifted_packet += " in["+top+":"+(top_of_addr_field+1)+"], ";
517         shifted_packet += " (in["+(top_of_addr_field)+":"+bot_of_addr_field+"] >> 1) ";
518         if (bot_of_addr_field > 0) shifted_packet += ",  in["+(bot_of_addr_field-1)+":0]  ";
519         shifted_packet += " }";
520         // same behavior as FLEET -- wait for both
521         horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" },
522                        new Action[] { in, out0, new AssignAction(out0, shifted_packet) });
523         horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" },
524                        new Action[] { in, out1, new AssignAction(out1, shifted_packet) });
525         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
526         horn.dump(pw, true);
527         pw.flush();
528     }
529
530     private static Module mkBox(String name, boolean inbox, String prefix, Module fifo, Module ififo_m) throws Exception {
531         Module box = new Module(name);
532         Module.SourcePort instr         = box.createInputPort("instr",       WIDTH_WORD);
533         Module.SourcePort fabric_in     = box.createInputPort("fabric_in",   WIDTH_PACKET);
534         Module.SinkPort   fabric_out    = box.createOutputPort("fabric_out", WIDTH_PACKET, "");
535         Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo);
536         fabric_in.connect(dfifo.getInputPort("in"));
537         
538         Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
539         Module.SourcePort   ship_out    = null;
540         if (!inbox) {
541             ship_out = box.createInputPort("ship",        WIDTH_WORD);
542             ship_out.hasLatch = true;
543         }
544
545         Module.SinkPort   ship_in     = null;
546         if (inbox) {
547             ship_in = box.createOutputPort("ship",        WIDTH_PACKET, "");
548             ship_in.hasLatch = true;
549         }
550
551         Module.Latch     ondeck         = box.new Latch("ondeck", WIDTH_WORD);
552         Module.Latch     repcount       = box.new Latch("repcount", WIDTH_COUNTER_LITERAL);
553         Module.Latch     repcount2      = box.new Latch("repcount2", WIDTH_COUNTER_LITERAL);
554         Module.Latch     killcount      = box.new Latch("killcount", WIDTH_COUNTER_LITERAL);
555         Module.Latch     loop_counter   = box.new Latch("loop_counter", WIDTH_COUNTER_LITERAL);
556         Module.Latch     repeat_counter = box.new Latch("repeat_counter", WIDTH_COUNTER_LITERAL);
557         Module.StateWire ondeckFull     = box.new StateWire("ondeck_full");
558         Module.StateWire newMayProceed  = box.new StateWire("newmayproceed", true);
559         Module.StateWire doRepeat       = box.new StateWire("dorepeat", false);
560         Module.StateWire doRepeatKill   = box.new StateWire("dorepeatkill", false);
561         Module.StateWire doKill         = box.new StateWire("dokill", false);
562         Module.StateWire isClogged      = box.new StateWire("clogged", false);
563         Module.StateWire isMassacreing  = box.new StateWire("massacreing", false);
564         
565         Module.SinkPort   token_out     = fabric_out;
566         Module.SourcePort token_in      = dfifo_out;
567         Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
568         Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
569
570         Module.InstantiatedModule ififo = box.new InstantiatedModule(ififo_m);
571         Module.SinkPort   ififo_in      = ififo.getInputPort("in");
572         Module.SourcePort ififo_out     = ififo.getOutputPort("out");
573
574
575         // Massacre (when enqueued)
576         box.new Event(
577                       new Object[] { ififo_out, "!`instruction_is_massacre("+ififo_out.getName()+")", isMassacreing.isFull() },
578                       new Action[] { ififo_out }
579                       );
580         box.new Event(
581                       new Object[] { ififo_out, "`instruction_is_massacre("+ififo_out.getName()+")", isMassacreing.isFull() },
582                       new Action[] { ififo_out, isMassacreing.doDrain(), newMayProceed.doFill() }
583                       );
584         box.new Event(
585                       new Object[] { instr, ififo_in, "`instruction_is_massacre(instr)", isMassacreing.isEmpty() },
586                       new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr), isMassacreing.doFill(), ondeckFull.doDrain(), newMayProceed.doDrain() }
587                       );
588
589         // Clog (must be first)
590         box.new Event(
591                       new Object[] { ififo_out, newMayProceed.isFull(), "`instruction_is_clog("+ififo_out.getName()+")", isMassacreing.isEmpty() },
592                       new Action[] { ififo_out, isClogged.doFill(), newMayProceed.doDrain() }
593                       );
594
595         // UnClog
596         box.new Event(
597                       new Object[] { instr, isClogged.isFull(), "`instruction_is_unclog(instr)", isMassacreing.isEmpty() },
598                       new Action[] { instr, isClogged.doDrain(), newMayProceed.doFill()  }
599                       );
600
601         // First Kill
602         box.new Event(
603                       new Object[] { instr,
604                                      "`instruction_is_kill(instr)",
605                                      "!`instruction_is_unclog(instr)",
606                                      ondeckFull.isFull(),
607                                      isMassacreing.isEmpty()
608                       },
609                       new Action[] { instr,
610                                      ondeckFull.doDrain(),
611                                      new ConditionalAction("`instruction_kill_count(instr)!=0", new AssignAction(repcount, "`instruction_kill_count(instr)")),
612                                      new ConditionalAction("`instruction_kill_count(instr)!=0", doRepeatKill.doFill()),
613                                      new ConditionalAction("`instruction_kill_count(instr)!=0", newMayProceed.doDrain()),
614                                      new ConditionalAction("`instruction_kill_count(instr)==0", newMayProceed.doFill())
615                       });
616
617         // Kill              
618         box.new Event(
619                       new Object[] { doKill.isFull() },
620                       new Action[] { doKill.doDrain(),
621                                      new ConditionalAction("killcount!=0", new AssignAction(repcount, "killcount-1")),
622                                      new ConditionalAction("killcount!=0", doRepeatKill.doFill()),
623                                      new ConditionalAction("killcount==0", newMayProceed.doFill())
624                       });
625
626         // RepKill
627         box.new Event(
628                       new Object[] { doRepeatKill.isFull(), ififo_out },
629                       new Action[] { doRepeatKill.doDrain(), ififo_out, doKill.doFill(),
630                                      new AssignAction(killcount, repcount) }
631                       );
632
633         // Enqueue
634         box.new Event(
635                       new Object[] { instr,
636                                      ififo_in,
637                                      "!`instruction_is_kill(instr) && !`instruction_is_unclog(instr) && !`instruction_is_massacre(instr)",
638                                      isMassacreing.isEmpty()
639                       },
640                       new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr)  }
641                       );
642
643         // New
644         box.new Event(
645                       new Object[] { ififo_out,
646                                      ondeckFull.isEmpty(),
647                                      newMayProceed.isFull(),
648                                      "!`instruction_is_clog("+ififo_out.getName()+")",
649                                      "!`instruction_is_kill(instr)",
650                                      isMassacreing.isEmpty() },
651                       new Action[] { ififo_out,
652                                      ondeckFull.doFill(),
653                                      newMayProceed.doDrain(),
654                                      new AssignAction(ondeck, ififo_out),
655                                      new ConditionalAction("`instruction_is_normal("+ififo_out.getName()+") && !`is_standing("+ififo_out.getName()+")",
656                                                            new AssignAction(repcount2, "(repeat_counter==0?1:repeat_counter)")),
657                                      new ConditionalAction("`instruction_is_normal("+ififo_out.getName()+")",
658                                                            new AssignAction(repeat_counter, "1")),
659                       }
660                       );
661
662         // RepeatExecute
663         box.new Event(
664                       new Object[] { doRepeat.isFull() },
665                       new Action[] { doRepeat.doDrain(),
666                                      ondeckFull.doFill(),
667                                      new AssignAction(repcount2, repcount)
668                       }
669                       );
670
671         box.addPreCrap("wire [(`DATAWIDTH-1):0] data_latch_output;");
672         box.addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+";");
673
674         Assignable data_latch    = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")");
675         String data_latch_input  = inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName();
676
677         box.new Event(new Object[] { ondeckFull.isFull(),
678                                      isMassacreing.isEmpty(),
679                                      ififo_in,
680                                      "!`instruction_is_kill(instr)",
681                                      "`instruction_is_load_loop_to_data(ondeck)"
682             },
683             new Action[] { ondeckFull.doDrain(),
684                            newMayProceed.doFill(),
685                            new AssignAction(data_latch, loop_counter),
686                            new AssignAction(ififo_in, ondeck),
687                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
688             }
689             );
690         box.new Event(new Object[] { ondeckFull.isFull(),
691                                      isMassacreing.isEmpty(),
692                                      ififo_in,
693                                      "!`instruction_is_kill(instr)",
694                                      "`instruction_is_load_data_to_loop(ondeck)"
695             },
696             new Action[] { ondeckFull.doDrain(),
697                            newMayProceed.doFill(),
698                            new AssignAction(loop_counter, "data_latch_output"),
699                            new AssignAction(ififo_in, ondeck),
700                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
701             }
702             );
703         box.new Event(new Object[] { ondeckFull.isFull(),
704                                      isMassacreing.isEmpty(),
705                                      ififo_in,
706                                      "!`instruction_is_kill(instr)",
707                                      "`instruction_is_load_literal_to_loop(ondeck)"
708             },
709             new Action[] { ondeckFull.doDrain(),
710                            newMayProceed.doFill(),
711                            new AssignAction(loop_counter, "`instruction_loop_count_literal(ondeck)"),
712                            new AssignAction(ififo_in, ondeck),
713                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
714             }
715             );
716         box.new Event(new Object[] { ondeckFull.isFull(),
717                                      isMassacreing.isEmpty(),
718                                      ififo_in,
719                                      "!`instruction_is_kill(instr)",
720                                      "`instruction_is_decr_loop(ondeck)"
721             },
722             new Action[] { ondeckFull.doDrain(),
723                            newMayProceed.doFill(),
724                            new AssignAction(loop_counter, "loop_counter==0 ? 0 : (loop_counter-1)"),
725                            new AssignAction(ififo_in, ondeck),
726                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
727             }
728             );
729         box.new Event(new Object[] { ondeckFull.isFull(),
730                                      isMassacreing.isEmpty(),
731                                      ififo_in,
732                                      "!`instruction_is_kill(instr)",
733                                      "`instruction_is_load_data_to_repeat(ondeck)"
734             },
735             new Action[] { ondeckFull.doDrain(),
736                            newMayProceed.doFill(),
737                            new AssignAction(repeat_counter, "data_latch_output"),
738                            new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)),
739                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
740             }
741             );
742         box.new Event(new Object[] { ondeckFull.isFull(),
743                                      isMassacreing.isEmpty(),
744                                      ififo_in,
745                                      "!`instruction_is_kill(instr)",
746                                      "`instruction_is_load_literal_to_repeat(ondeck)"
747             },
748             new Action[] { ondeckFull.doDrain(),
749                            newMayProceed.doFill(),
750                            new AssignAction(repeat_counter, "`instruction_repeat_count_literal(ondeck)"),
751                            new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)),
752                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
753             }
754             );
755                            
756                                      
757         box.new Event(
758                       new Object[] { ondeckFull.isFull(),
759                                      isMassacreing.isEmpty(),
760                                      data_out,
761                                      token_out,
762                                      ififo_in,
763                                      "!`instruction_is_kill(instr)",
764                                      "(`instruction_is_normal(ondeck) || `instruction_is_literal_hi(ondeck) ||"+
765                                      " `instruction_is_literal_lo(ondeck) || `instruction_is_literal(ondeck))",
766                                      new ConditionalTrigger("`instruction_bit_datain(ondeck)", data_in),
767                                      new ConditionalTrigger("`instruction_bit_tokenin(ondeck)", token_in)
768                               },
769                               new Action[] { ondeckFull.doDrain(),
770                                              new ConditionalAction("`done_executing(ondeck)",                            newMayProceed.doFill()),
771                                              new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", ififo_in),
772                                              new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", new AssignAction(ififo_in, ondeck)),
773                                              new ConditionalAction("repcount2>1", doRepeat.doFill()),
774                                              new ConditionalAction("`is_standing(ondeck)", doRepeat.doFill()),
775                                              new ConditionalAction("!`is_standing(ondeck)", new AssignAction(repcount, "repcount2-1")),
776                                              new ConditionalAction("`instruction_is_literal(ondeck)",
777                                                                    new AssignAction(data_latch, "`instruction_literal(ondeck)")),
778                                              new ConditionalAction("`instruction_is_literal_hi(ondeck)",
779                                                                    new AssignAction(data_latch, "`instruction_literal_hi(ondeck,data_latch_output)")),
780                                              new ConditionalAction("`instruction_is_literal_lo(ondeck)",
781                                                                    new AssignAction(data_latch, "`instruction_literal_lo(ondeck,data_latch_output)")),
782                                              new ConditionalAction("`instruction_bit_datain(ondeck)",   data_in),
783                                              new ConditionalAction("`instruction_bit_dataout(ondeck)",  data_out),
784                                              new ConditionalAction("`instruction_bit_tokenin(ondeck)",  token_in),
785                                              new ConditionalAction("`instruction_bit_tokenout(ondeck)", token_out),
786                                              new ConditionalAction("`instruction_bit_latch(ondeck)", new AssignAction(data_latch, data_latch_input)),
787                                              new ConditionalAction("`instruction_path_from_data(ondeck)",
788                                                                    new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"),
789                                                                                     PUMP_NAME.verilogVal(data_latch_input))),
790                                              new ConditionalAction("`instruction_path_from_literal(ondeck)",
791                                                                    new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"),
792                                                                                     "`instruction_path_literal(ondeck)")),
793                               }
794                       );
795
796         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
797
798         pw.println("`define instruction_is_load_loop_to_data(i)      "+TAKE_LOOP.verilog("i"));
799         pw.println("`define instruction_is_load_data_to_repeat(i)    "+REPEAT_FROM_DATA.verilog("i"));
800         pw.println("`define instruction_is_load_data_to_loop(i)      "+LOOP_FROM_DATA.verilog("i"));
801         pw.println("`define instruction_is_load_literal_to_repeat(i) "+REPEAT_FROM_LITERAL.verilog("i"));
802         pw.println("`define instruction_is_load_literal_to_loop(i)   "+LOOP_FROM_LITERAL.verilog("i"));
803         pw.println("`define instruction_repeat_count_literal(i)      "+REPEAT_FROM_LITERAL.verilogVal("i"));
804         pw.println("`define instruction_loop_count_literal(i)        "+LOOP_FROM_LITERAL.verilogVal("i"));
805
806         pw.println("`define instruction_path_literal(i)              "+PATH_LITERAL.verilogVal("i"));
807         pw.println("`define instruction_path_from_literal(i)         "+PATH_LITERAL.verilog("i"));
808         pw.println("`define instruction_path_from_data(i)            "+PATH_DATA.verilog("i"));
809
810         pw.println("`define instruction_is_literal_hi(i)             "+LITERAL_HI.verilog("i"));
811         pw.println("`define instruction_is_literal_lo(i)             "+LITERAL_LO.verilog("i"));
812         pw.println("`define instruction_is_literal(i)                "+LITERAL.verilog("i"));
813         pw.println("`define instruction_kill_count(i)                "+KILL.verilogVal("i"));
814         pw.println("`define instruction_is_kill(i)                   "+KILL.verilog("i"));
815         pw.println("`define instruction_is_unclog(i)                 "+UNCLOG.verilog("i"));
816         pw.println("`define instruction_is_clog(i)                   "+CLOG.verilog("i"));
817         pw.println("`define instruction_is_massacre(i)               "+MASSACRE.verilog("i"));
818         pw.println("`define instruction_is_normal(i)                 "+MOVE.verilog("i"));
819
820         pw.println("`define instruction_is_decr_loop(i)              "+DL.verilog("i"));
821
822         pw.println("`define instruction_bit_tokenout(i)     (`instruction_is_normal(i) && "+TO.verilog("i")+")");
823         pw.println("`define instruction_bit_dataout(i)      (`instruction_is_normal(i) && "+DO.verilog("i")+")");
824         pw.println("`define instruction_bit_latch(i)        (`instruction_is_normal(i) && "+DC.verilog("i")+")");
825         pw.println("`define instruction_bit_datain(i)       (`instruction_is_normal(i) && "+DI.verilog("i")+")");
826         pw.println("`define instruction_bit_tokenin(i)      (`instruction_is_normal(i) && "+TI.verilog("i")+")");
827         pw.println("`define is_standing(i)                  (`instruction_is_normal(i) && "+STAND.verilog("i")+")");
828         pw.println("`define should_requeue(i)               (loop_counter > 0)");
829         pw.println("`define done_executing(i)               (!`is_standing(i) && (repcount2==0 || repcount2==1))");
830
831         pw.println("`define instruction_literal_hi(i,d) { (i[17:0]),  (d[18:0]) }");
832         pw.println("`define instruction_literal_lo(i,d) { (d[36:19]), (i[18:0]) }");
833
834         pw.println("`define instruction_literal_sel(i) " + LITERAL_SEL.verilogVal("i"));
835         pw.println("`define instruction_literal(i) " +
836                    "("+
837                    "  `instruction_literal_sel(i) == 0 ? { (i[17:0]),  {19{1'b0}} } "+
838                    ": `instruction_literal_sel(i) == 1 ? { (i[17:0]),  {19{1'b1}} } "+
839                    ": `instruction_literal_sel(i) == 2 ? { {18{1'b0}}, (i[18:0]) } "+
840                    ":                                    { {18{1'b1}}, (i[18:0]) } "+
841                    ")"
842                    );
843
844
845         box.dump(pw, true);
846         pw.flush();
847         return box;
848     }
849
850 }
851
852
853
854