add support for a "standing" count value
[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 String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
154             public StateWire(String name) { this(name, false); }
155             public StateWire(String name, boolean initiallyFull) {
156                 this.name = name;
157                 this.initiallyFull = initiallyFull;
158                 statewires.put(name, this);
159             }
160             public void dump(PrintWriter pw) {
161                 pw.println("  reg "+name+";");
162                 pw.println("  initial "+name+"="+(initiallyFull?"1":"0")+";");
163             }
164         }
165
166         public class Latch implements Assignable, Value {
167             public final String name;
168             public final int width;
169             public Latch(String name, int width) {
170                 this.width = width;
171                 this.name = name;
172                 latches.put(name, this);
173             }
174             public String getVerilogName() { return name; }
175             public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
176             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
177             public String doReset() { return name+"<=0;"; }
178             public void dump(PrintWriter pw) {
179                 pw.println("  reg ["+(width-1)+":0] "+name+";");
180                 pw.println("  initial "+name+"=0;");
181             }
182         }
183
184         private abstract class Port implements Action, Assignable, Trigger {
185             public final String name;
186             public String getName() { return name; }
187             public final int width;
188             public int getWidth() { return width; }
189             public boolean hasLatch = false;
190             public boolean external;
191             public Port(String name, int width, boolean external) {
192                 this.width = width;
193                 this.name = name;
194                 this.external = external;
195                 ports.put(name, this);
196                 if (external)
197                     portorder.add(name);
198             }
199             public String getVerilogName() { return name; }
200             public String getAck() { return name+"_a"; }
201             public String getReq() { return name+"_r"; }
202             public abstract String getInterface();
203             public abstract String getSimpleInterface();
204             public abstract String getDeclaration();
205             public abstract String getAssignments();
206         }
207
208         private class InstantiatedModule {
209             public final Module module;
210             public final int id;
211             private final HashMap<String,Port> ports = new HashMap<String,Port>();
212             public String getName() { return module.getName()+"_"+id; }
213             public InstantiatedModule(Module module) {
214                 this.module = module;
215                 this.id = Module.this.id++;
216                 instantiatedModules.add(this);
217             }
218             public void dump(PrintWriter pw) {
219                 pw.println("  " + module.getName() + " " + getName() + "(clk, rst ");
220                 for(String s : module.portorder)
221                     pw.println(", " + getPort(s).getSimpleInterface());
222                 pw.println("   );");
223             }
224             public Port getPort(String name) {
225                 return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
226             }
227             public SinkPort getInputPort(String name) {
228                 int width = module.getPort(name).getWidth();
229                 SinkPort port = (SinkPort)ports.get(name);
230                 if (port == null) {
231                     port = new SinkPort(getName()+"_"+name, width, false, "");
232                     ports.put(name, port);
233                 }
234                 return port;
235             }
236             public SourcePort getOutputPort(String name) {
237                 int width = module.getPort(name).getWidth();
238                 SourcePort port = (SourcePort)ports.get(name);
239                 if (port == null) {
240                     port = new SourcePort(getName()+"_"+name, width, false);
241                     ports.put(name, port);
242                 }
243                 return port;
244             }
245         }
246
247         private class SourcePort extends Port implements Value {
248             private SinkPort driven = null;
249             public SourcePort(String name, int width, boolean external) { 
250                 super(name, width, external); }
251             public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
252             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
253             public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
254             public String getVerilogAction() { return getAck() + " <= 1;"; }
255             public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
256             public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
257             public String getDeclaration() {
258                 StringBuffer sb = new StringBuffer();
259                 if (external) {
260                     sb.append("input "  +                 name +"_r;\n");
261                     sb.append("output " +                 name +"_a_;\n");
262                     sb.append("input ["+(width-1)+":0]" + name +";\n");
263                 } else {
264                     sb.append("wire "  +                 name +"_r;\n");
265                     sb.append("wire ["+(width-1)+":0]" + name +";\n");
266                 }
267                 if (!hasLatch) {
268                     sb.append("wire "    +                 name +"_a;\n");
269                 } else {
270                     sb.append("reg "    +                 name +"_a;\n");
271                     sb.append("initial " +                name +"_a = 0;\n");
272                 }
273                 return sb.toString();
274             }
275             public String getAssignments() {
276                 StringBuffer sb = new StringBuffer();
277                 if (external)
278                     sb.append("assign " +                 name +"_a_ = " + name + "_a;\n");
279                 if (driven != null) {
280                     sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
281                     sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
282                     sb.append("assign " + driven.name +"   = " + name + ";\n");
283                 }
284                 return sb.toString();
285             }
286             public void connect(SinkPort driven) {
287                 this.driven = driven;
288             }
289         }
290         private class SinkPort extends Port {
291             public final String resetBehavior;
292             public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
293             public String getVerilogAction() { return getReq() + " <= 1;"; }
294             public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); }
295             public SinkPort(String name, int width, boolean external, String resetBehavior) {
296                 super(name, width, external); this.resetBehavior=resetBehavior; }
297             public String getResetBehavior() { return resetBehavior; }
298             public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
299             public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
300             public String getDeclaration() {
301                 StringBuffer sb = new StringBuffer();
302                 if (external) {
303                     sb.append("output "  +                 name +"_r_;\n");
304                     sb.append("input "   +                 name +"_a;\n");
305                     sb.append("output ["+(width-1)+":0]" + name +"_;\n");
306                 } else {
307                     sb.append("wire "   +                 name +"_a;\n");
308                 }
309                 if (!hasLatch) {
310                     sb.append("wire "    +                 name +"_r;\n");
311                     sb.append("wire   ["+(width-1)+":0]" + name +";\n");
312                 } else {
313                     sb.append("reg "    +                  name +"_r;\n");
314                     sb.append("initial " +                 name +"_r = 0;\n");
315                     sb.append("reg    ["+(width-1)+":0]" + name +";\n");
316                     sb.append("initial " +                 name +" = 0;\n");
317                 }
318                 return sb.toString();
319             }
320             public String getAssignments() {
321                 StringBuffer sb = new StringBuffer();
322                 if (external) {
323                     sb.append("assign " +                  name +"_r_ = " + name + "_r;\n");
324                     sb.append("assign " +                  name +"_ = " + name + ";\n");
325                 }
326                 return sb.toString();
327             }
328         }
329
330         public void dump(PrintWriter pw, boolean fix) {
331             pw.println("`include \"macros.v\"");
332             pw.println("module "+name+"(clk, rst ");
333             for(String name : portorder) {
334                 Port p = ports.get(name);
335                 pw.println("    , " + p.getInterface());
336             }
337             pw.println("   );");
338             pw.println();
339             pw.println("    input clk;");
340             pw.println("    input rst;");
341             for(String name : ports.keySet()) {
342                 Port p = ports.get(name);
343                 pw.println("    " + p.getDeclaration());
344             }
345             for(StateWire sw : statewires.values())
346                 sw.dump(pw);
347             for(Latch l : latches.values())
348                 l.dump(pw);
349             for(String name : ports.keySet()) {
350                 Port p = ports.get(name);
351                 pw.println("    " + p.getAssignments());
352             }
353             for(InstantiatedModule m : instantiatedModules) {
354                 m.dump(pw);
355             }
356             pw.println(precrap);
357             pw.println("always @(posedge clk) begin");
358             pw.println("  if (!rst) begin");
359             for(Latch l : latches.values())
360                 pw.println(l.doReset());
361             for(StateWire sw : statewires.values())
362                 pw.println(sw.doReset());
363             for(Port p : ports.values()) {
364                 if (p instanceof SourcePort) {
365                     SourcePort ip = (SourcePort)p;
366                     if (ip.hasLatch)
367                         pw.println(ip.getAck()+" <=1;");
368                 } else {
369                     SinkPort op = (SinkPort)p;
370                     if (op.hasLatch)
371                         pw.println(op.getReq()+" <=0;");
372                 }
373             }
374             pw.println("  end else begin");
375             for(Port p : ports.values()) {
376                 if (p instanceof SourcePort) {
377                     SourcePort ip = (SourcePort)p;
378                     if (ip.hasLatch)
379                         pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
380                 } else {
381                     SinkPort op = (SinkPort)p;
382                     if (op.hasLatch)
383                         pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
384                                    op.getReq()+"<=0; "+
385                                    op.getResetBehavior()+" end");
386                 }
387             }
388             for(Event a : events) a.dump(pw, fix);
389             pw.println("    begin end");
390             pw.println("    end");
391             pw.println("  end");
392
393             pw.println(crap);
394             pw.println("endmodule");
395         }
396
397         private class Event {
398             private Object[]  triggers;
399             private Object[]  actions;
400             public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); }
401             public Event(Object[] triggers, Object[] actions) {
402                 Module.this.events.add(this);
403                 this.triggers = triggers;
404                 this.actions = actions;
405                 for(int i=0; i<triggers.length; i++)
406                     if (triggers[i] instanceof Port)
407                         ((Port)triggers[i]).hasLatch = true;
408             }
409             public void dump(PrintWriter pw, boolean fix) {
410                 pw.print("if (1");
411                 for(Object o : triggers) {
412                     if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
413                     else                      pw.print(" && " + o);
414                 }
415                 pw.println(") begin ");
416                 for(Object a : actions) pw.println(((Action)a).getVerilogAction());
417                 if (fix) pw.println("end /*else*/ ");
418                 else     pw.println("end else ");
419             }
420         }
421     }
422
423     public static void main(String[] s) throws Exception {
424         String prefix = s[0];
425         PrintWriter pw;
426
427         pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/bitfields.v")));
428         pw.println("`define DATAWIDTH                "+WIDTH_WORD);
429         pw.println("`define CODEBAG_SIZE_BITS        "+WIDTH_CODEBAG_SIZE);
430         pw.println("`define PUMP_ADDRESS_BITS    "+WIDTH_ADDR);
431         pw.println("`define DESTINATION_ADDRESS_BITS "+WIDTH_ADDR);
432         /*
433         pw.println("`define COUNT_BITS               "+WIDTH_COUNT);
434         pw.println("`define COUNT_WIDTH              "+WIDTH_COUNT);
435         */
436         pw.println("`define PACKET_WIDTH             (`DATAWIDTH + `DESTINATION_ADDRESS_BITS)");
437         pw.println("`define INSTRUCTION_WIDTH        "+WIDTH_WORD);
438         pw.println("`define packet_data(p)              p[(`DESTINATION_ADDRESS_BITS+`DATAWIDTH-1):(`DESTINATION_ADDRESS_BITS)]");
439         pw.println("`define packet_dest(p)              p[(`DESTINATION_ADDRESS_BITS-1):0]");
440         pw.println("`define instruction_data(p)         p[(`DATAWIDTH-1):0]");
441         pw.println("`define instruction_dest(p)         "+PUMP_NAME.verilogVal("p"));
442         pw.flush();
443         pw.close();
444
445         mkfunnel("funnel", prefix);
446         mkhorn(    "horn", prefix, WIDTH_PACKET-1, WIDTH_ADDR-1, 0, 0);
447         mkhorn(   "ihorn", prefix, WIDTH_PACKET-1, WIDTH_ADDR-1, 0, 0);
448
449         Module fifostage = mkfifo("fifostage", 0, null,      prefix);
450         Module fifo4     = mkfifo("fifo4",     4, fifostage, prefix);
451         Module fifo8     = mkfifo("fifo8",     8, fifostage, prefix);
452         Module fifoship  = mkfifo("fifo",      4, fifo4,     prefix);
453         mkBox("outbox", false, prefix, fifo4, fifo8);
454         mkBox("inbox", true, prefix, fifo4, fifo8);
455
456         Module fabric = new Module("fabric");
457         fabric.createInputPort("horn_in",     WIDTH_PACKET);
458         fabric.createOutputPort("funnel_out", WIDTH_PACKET, "");
459         mkRoot("root", prefix, fabric);
460     }
461
462     private static Module mkRoot(String name, String prefix, Module fabricm) throws Exception {
463         Module root = new Module(name);
464         Module.SourcePort  in  = root.createInputPort("in", 8);
465         Module.SinkPort    out = root.createOutputPort("out", 8, "");
466         Module.InstantiatedModule fabric = root.new InstantiatedModule(fabricm);
467         Module.SinkPort    fabric_in   = fabric.getInputPort("horn_in");
468         Module.SourcePort  fabric_out  = fabric.getOutputPort("funnel_out");
469         Module.Latch       count       = root.new Latch("count", 8);
470         Module.Latch       count_out   = root.new Latch("count_out", 8);
471         root.new Event(new Object[] { in, fabric_in },
472                        new Object[] { new SimpleAction(fabric_in.getName()+" <= ("+fabric_in.getName()+" << 8) | in;"),
473                                       new SimpleAction("if (count >= 5) begin count <= 0; "+fabric_in.getName()+"_r <= 1; end else count <= count+1; "),
474                                       in
475                        });
476         root.new Event(new Object[] { out, fabric_out },
477                        new Object[] { new SimpleAction(out.getName()+" <= ("+fabric_out.getName()+">> (count_out*8));"),
478                                       new SimpleAction("if (count_out >= 5) begin count_out <= 0; "+fabric_out.getName()+"_a <= 1; end else count_out <= count_out+1; "),
479                                       out });
480         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
481         root.dump(pw, true);
482         pw.flush();
483         return root;
484     }
485
486     private static Module mkfunnel(String name, String prefix) throws Exception {
487         Module funnel = new Module(name);
488         Module.SinkPort    out = funnel.createOutputPort("out", WIDTH_PACKET, "");
489         Module.SourcePort  in1 = funnel.createInputPort("in1", WIDTH_PACKET);
490         Module.SourcePort  in2 = funnel.createInputPort("in2", WIDTH_PACKET);
491         funnel.new Event(new Object[] { in1, out },
492                          new Action[] { in1, out,
493                                         new AssignAction(out, in1) });
494         funnel.new Event(new Object[] { in2, out },
495                          new Action[] { in2, out,
496                                         new AssignAction(out, in2) });
497         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
498         funnel.dump(pw, true);
499         pw.flush();
500         return funnel;
501     }
502
503     private static Module mkfifo(String name, int len, Module instance, String prefix) throws Exception {
504         Module fifo = new Module(name);
505         Module.SourcePort  in  = fifo.createInputPort("in", WIDTH_PACKET);
506         Module.SinkPort    out = fifo.createOutputPort("out", WIDTH_PACKET, "");
507         Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
508         if (len==0) {
509             fifo.new Event(new Object[] { in, out },
510                             new Action[] { in, out, new AssignAction(out, in) });
511         } else for(int i=0; i<=len; i++) {
512             if (i<len) stages[i] = fifo.new InstantiatedModule(instance);
513             Module.SourcePort driver = i==0 ? in : stages[i-1].getOutputPort("out");
514             Module.SinkPort   driven = i==len ? out : stages[i].getInputPort("in");
515             driver.connect(driven);
516         }
517         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
518         fifo.dump(pw, true);
519         /*
520           pw.println("`define FIFO_LENGTH " + len);
521           //pw.println("`define NAME " + name);
522           pw.println("`include \"macros.v\"");
523           pw.println("module "+name+"(clk, rst ");
524           pw.println("              , in_r, in_a_, in");
525           pw.println("              , out_r_, out_a, out_);");
526           BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("src/edu/berkeley/fleet/fpga/fifo.inc")));
527           String s;
528           while((s = br.readLine())!=null)
529           pw.println(s);
530         */
531         pw.flush();
532         return fifo;
533     }
534
535     public static void mkhorn(String name, 
536                               String prefix,
537                               int top,
538                               int top_of_addr_field,
539                               int bot_of_addr_field,
540                               int bot) throws Exception {
541         Module horn = new Module(name);
542         Module.SourcePort in   = horn.createInputPort("in",    WIDTH_PACKET);
543         Module.SinkPort   out0 = horn.createOutputPort("out0", WIDTH_PACKET, "");
544         Module.SinkPort   out1 = horn.createOutputPort("out1", WIDTH_PACKET, "");
545         String shifted_packet = "{ ";
546         if (top_of_addr_field+1 < top) shifted_packet += " in["+top+":"+(top_of_addr_field+1)+"], ";
547         shifted_packet += " (in["+(top_of_addr_field)+":"+bot_of_addr_field+"] >> 1) ";
548         if (bot_of_addr_field > 0) shifted_packet += ",  in["+(bot_of_addr_field-1)+":0]  ";
549         shifted_packet += " }";
550         // same behavior as FLEET -- wait for both
551         horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" },
552                        new Action[] { in, out0, new AssignAction(out0, shifted_packet) });
553         horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" },
554                        new Action[] { in, out1, new AssignAction(out1, shifted_packet) });
555         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
556         horn.dump(pw, true);
557         pw.flush();
558     }
559
560     private static Module mkBox(String name, boolean inbox, String prefix, Module fifo, Module ififo_m) throws Exception {
561         Module box = new Module(name);
562         Module.SourcePort instr         = box.createInputPort("instr",       WIDTH_WORD);
563         Module.SourcePort fabric_in     = box.createInputPort("fabric_in",   WIDTH_PACKET);
564         Module.SinkPort   fabric_out    = box.createOutputPort("fabric_out", WIDTH_PACKET, "");
565         Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo);
566         fabric_in.connect(dfifo.getInputPort("in"));
567         
568         Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
569         Module.SourcePort   ship_out    = null;
570         if (!inbox) {
571             ship_out = box.createInputPort("ship",        WIDTH_WORD);
572             ship_out.hasLatch = true;
573         }
574
575         Module.SinkPort   ship_in     = null;
576         if (inbox) {
577             ship_in = box.createOutputPort("ship",        WIDTH_PACKET, "");
578             ship_in.hasLatch = true;
579         }
580
581         Module.Latch     ondeck         = box.new Latch("ondeck", WIDTH_WORD);
582         Module.Latch     repcount       = box.new Latch("repcount", WIDTH_COUNTER_LITERAL+1);
583         Module.Latch     repcount2      = box.new Latch("repcount2", WIDTH_COUNTER_LITERAL+1);
584         Module.Latch     repeat_counter = box.new Latch("repeat_counter", WIDTH_COUNTER_LITERAL+1);
585         Module.Latch     killcount      = box.new Latch("killcount", WIDTH_COUNTER_LITERAL);
586         Module.Latch     loop_counter   = box.new Latch("loop_counter", WIDTH_COUNTER_LITERAL);
587         Module.StateWire ondeckFull     = box.new StateWire("ondeck_full");
588         Module.StateWire newMayProceed  = box.new StateWire("newmayproceed", true);
589         Module.StateWire doRepeat       = box.new StateWire("dorepeat", false);
590         Module.StateWire doRepeatKill   = box.new StateWire("dorepeatkill", false);
591         Module.StateWire doKill         = box.new StateWire("dokill", false);
592         Module.StateWire isClogged      = box.new StateWire("clogged", false);
593         Module.StateWire isMassacreing  = box.new StateWire("massacreing", false);
594         
595         Module.SinkPort   token_out     = fabric_out;
596         Module.SourcePort token_in      = dfifo_out;
597         Module.SinkPort   data_out      = inbox ? ship_in   : fabric_out;
598         Module.SourcePort data_in       = inbox ? dfifo_out : ship_out;
599
600         Module.InstantiatedModule ififo = box.new InstantiatedModule(ififo_m);
601         Module.SinkPort   ififo_in      = ififo.getInputPort("in");
602         Module.SourcePort ififo_out     = ififo.getOutputPort("out");
603
604
605         // Massacre (when enqueued)
606         box.new Event(
607                       new Object[] { ififo_out, "!`instruction_is_massacre("+ififo_out.getName()+")", isMassacreing.isFull() },
608                       new Action[] { ififo_out }
609                       );
610         box.new Event(
611                       new Object[] { ififo_out, "`instruction_is_massacre("+ififo_out.getName()+")", isMassacreing.isFull() },
612                       new Action[] { ififo_out, isMassacreing.doDrain(), newMayProceed.doFill() }
613                       );
614         box.new Event(
615                       new Object[] { instr, ififo_in, "`instruction_is_massacre(instr)", isMassacreing.isEmpty() },
616                       new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr), isMassacreing.doFill(), ondeckFull.doDrain(), newMayProceed.doDrain() }
617                       );
618
619         // Clog (must be first)
620         box.new Event(
621                       new Object[] { ififo_out, newMayProceed.isFull(), "`instruction_is_clog("+ififo_out.getName()+")", isMassacreing.isEmpty() },
622                       new Action[] { ififo_out, isClogged.doFill(), newMayProceed.doDrain() }
623                       );
624
625         // UnClog
626         box.new Event(
627                       new Object[] { instr, isClogged.isFull(), "`instruction_is_unclog(instr)", isMassacreing.isEmpty() },
628                       new Action[] { instr, isClogged.doDrain(), newMayProceed.doFill()  }
629                       );
630
631         // First Kill
632         box.new Event(
633                       new Object[] { instr,
634                                      "`instruction_is_kill(instr)",
635                                      "!`instruction_is_unclog(instr)",
636                                      ondeckFull.isFull(),
637                                      isMassacreing.isEmpty()
638                       },
639                       new Action[] { instr,
640                                      ondeckFull.doDrain(),
641                                      new ConditionalAction("`instruction_kill_count(instr)!=0", new AssignAction(repcount, "`instruction_kill_count(instr)")),
642                                      new ConditionalAction("`instruction_kill_count(instr)!=0", doRepeatKill.doFill()),
643                                      new ConditionalAction("`instruction_kill_count(instr)!=0", newMayProceed.doDrain()),
644                                      new ConditionalAction("`instruction_kill_count(instr)==0", newMayProceed.doFill())
645                       });
646
647         // Kill              
648         box.new Event(
649                       new Object[] { doKill.isFull() },
650                       new Action[] { doKill.doDrain(),
651                                      new ConditionalAction("killcount!=0", new AssignAction(repcount, "killcount-1")),
652                                      new ConditionalAction("killcount!=0", doRepeatKill.doFill()),
653                                      new ConditionalAction("killcount==0", newMayProceed.doFill())
654                       });
655
656         // RepKill
657         box.new Event(
658                       new Object[] { doRepeatKill.isFull(), ififo_out },
659                       new Action[] { doRepeatKill.doDrain(), ififo_out, doKill.doFill(),
660                                      new AssignAction(killcount, repcount) }
661                       );
662
663         // Enqueue
664         box.new Event(
665                       new Object[] { instr,
666                                      ififo_in,
667                                      "!`instruction_is_kill(instr) && !`instruction_is_unclog(instr) && !`instruction_is_massacre(instr)",
668                                      isMassacreing.isEmpty()
669                       },
670                       new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr)  }
671                       );
672
673         // New
674         box.new Event(
675                       new Object[] { ififo_out,
676                                      ondeckFull.isEmpty(),
677                                      newMayProceed.isFull(),
678                                      "!`instruction_is_clog("+ififo_out.getName()+")",
679                                      "!`instruction_is_kill(instr)",
680                                      isMassacreing.isEmpty() },
681                       new Action[] { ififo_out,
682                                      ondeckFull.doFill(),
683                                      newMayProceed.doDrain(),
684                                      new AssignAction(ondeck, ififo_out),
685                                      new ConditionalAction("`instruction_is_normal("+ififo_out.getName()+") && !`is_standing("+ififo_out.getName()+")",
686                                                            new AssignAction(repcount2, "(repeat_counter==0?1:repeat_counter)")),
687                                      new ConditionalAction("`instruction_is_normal("+ififo_out.getName()+")",
688                                                            new AssignAction(repeat_counter, "1")),
689                       }
690                       );
691
692         // RepeatExecute
693         box.new Event(
694                       new Object[] { doRepeat.isFull() },
695                       new Action[] { doRepeat.doDrain(),
696                                      ondeckFull.doFill(),
697                                      new AssignAction(repcount2, repcount)
698                       }
699                       );
700
701         box.addPreCrap("wire [(`DATAWIDTH-1):0] data_latch_output;");
702         box.addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+";");
703
704         Assignable data_latch    = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")");
705         String data_latch_input  = inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName();
706
707         box.new Event(new Object[] { ondeckFull.isFull(),
708                                      isMassacreing.isEmpty(),
709                                      ififo_in,
710                                      "!`instruction_is_kill(instr)",
711                                      "`instruction_is_load_loop_to_data(ondeck)"
712             },
713             new Action[] { ondeckFull.doDrain(),
714                            newMayProceed.doFill(),
715                            new AssignAction(data_latch, loop_counter),
716                            new AssignAction(ififo_in, ondeck),
717                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
718             }
719             );
720         box.new Event(new Object[] { ondeckFull.isFull(),
721                                      isMassacreing.isEmpty(),
722                                      ififo_in,
723                                      "!`instruction_is_kill(instr)",
724                                      "`instruction_is_load_data_to_loop(ondeck)"
725             },
726             new Action[] { ondeckFull.doDrain(),
727                            newMayProceed.doFill(),
728                            new AssignAction(loop_counter, "data_latch_output"),
729                            new AssignAction(ififo_in, ondeck),
730                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
731             }
732             );
733         box.new Event(new Object[] { ondeckFull.isFull(),
734                                      isMassacreing.isEmpty(),
735                                      ififo_in,
736                                      "!`instruction_is_kill(instr)",
737                                      "`instruction_is_load_literal_to_loop(ondeck)"
738             },
739             new Action[] { ondeckFull.doDrain(),
740                            newMayProceed.doFill(),
741                            new AssignAction(loop_counter, "`instruction_loop_count_literal(ondeck)"),
742                            new AssignAction(ififo_in, ondeck),
743                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
744             }
745             );
746         box.new Event(new Object[] { ondeckFull.isFull(),
747                                      isMassacreing.isEmpty(),
748                                      ififo_in,
749                                      "!`instruction_is_kill(instr)",
750                                      "`instruction_is_decr_loop(ondeck)"
751             },
752             new Action[] { ondeckFull.doDrain(),
753                            newMayProceed.doFill(),
754                            new AssignAction(loop_counter, "loop_counter==0 ? 0 : (loop_counter-1)"),
755                            new AssignAction(ififo_in, ondeck),
756                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
757             }
758             );
759         box.new Event(new Object[] { ondeckFull.isFull(),
760                                      isMassacreing.isEmpty(),
761                                      ififo_in,
762                                      "!`instruction_is_kill(instr)",
763                                      "`instruction_is_load_data_to_repeat(ondeck)"
764             },
765             new Action[] { ondeckFull.doDrain(),
766                            newMayProceed.doFill(),
767                            new AssignAction(repeat_counter, "data_latch_output"),
768                            new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)),
769                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
770             }
771             );
772         box.new Event(new Object[] { ondeckFull.isFull(),
773                                      isMassacreing.isEmpty(),
774                                      ififo_in,
775                                      "!`instruction_is_kill(instr)",
776                                      "`instruction_is_load_literal_to_repeat(ondeck)"
777             },
778             new Action[] { ondeckFull.doDrain(),
779                            newMayProceed.doFill(),
780                            new AssignAction(repeat_counter, "`instruction_repeat_count_literal(ondeck)"),
781                            new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)),
782                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
783             }
784             );
785         box.new Event(new Object[] { ondeckFull.isFull(),
786                                      isMassacreing.isEmpty(),
787                                      ififo_in,
788                                      "!`instruction_is_kill(instr)",
789                                      "`instruction_is_load_standing_to_repeat(ondeck)"
790             },
791             new Action[] { ondeckFull.doDrain(),
792                            newMayProceed.doFill(),
793                            new AssignAction(repeat_counter, "`magic_standing_value"),
794                            new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)),
795                            new ConditionalAction("`should_requeue(ondeck)", ififo_in)
796             }
797             );
798                            
799                                      
800         box.new Event(
801                       new Object[] { ondeckFull.isFull(),
802                                      isMassacreing.isEmpty(),
803                                      data_out,
804                                      token_out,
805                                      ififo_in,
806                                      "!`instruction_is_kill(instr)",
807                                      "(`instruction_is_normal(ondeck) || `instruction_is_literal_hi(ondeck) ||"+
808                                      " `instruction_is_literal_lo(ondeck) || `instruction_is_literal(ondeck))",
809                                      new ConditionalTrigger("`instruction_bit_datain(ondeck)", data_in),
810                                      new ConditionalTrigger("`instruction_bit_tokenin(ondeck)", token_in)
811                               },
812                               new Action[] { ondeckFull.doDrain(),
813                                              new ConditionalAction("`done_executing(ondeck)",                            newMayProceed.doFill()),
814                                              new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", ififo_in),
815                                              new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", new AssignAction(ififo_in, ondeck)),
816                                              new ConditionalAction("repcount2>1 || repcount2==`magic_standing_value", doRepeat.doFill()),
817                                              new ConditionalAction("`is_standing(ondeck)", doRepeat.doFill()),
818                                              new ConditionalAction("!`is_standing(ondeck) && repcount2!=`magic_standing_value",
819                                                                    new AssignAction(repcount, "repcount2-1")),
820                                              new ConditionalAction("!`is_standing(ondeck) && repcount2==`magic_standing_value",
821                                                                    new AssignAction(repcount, "`magic_standing_value")),
822                                              new ConditionalAction("`instruction_is_literal(ondeck)",
823                                                                    new AssignAction(data_latch, "`instruction_literal(ondeck)")),
824                                              new ConditionalAction("`instruction_is_literal_hi(ondeck)",
825                                                                    new AssignAction(data_latch, "`instruction_literal_hi(ondeck,data_latch_output)")),
826                                              new ConditionalAction("`instruction_is_literal_lo(ondeck)",
827                                                                    new AssignAction(data_latch, "`instruction_literal_lo(ondeck,data_latch_output)")),
828                                              new ConditionalAction("`instruction_bit_datain(ondeck)",   data_in),
829                                              new ConditionalAction("`instruction_bit_dataout(ondeck)",  data_out),
830                                              new ConditionalAction("`instruction_bit_tokenin(ondeck)",  token_in),
831                                              new ConditionalAction("`instruction_bit_tokenout(ondeck)", token_out),
832                                              new ConditionalAction("`instruction_bit_latch(ondeck)", new AssignAction(data_latch, data_latch_input)),
833                                              new ConditionalAction("`instruction_path_from_data(ondeck)",
834                                                                    new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"),
835                                                                                     PUMP_NAME.verilogVal(data_latch_input))),
836                                              new ConditionalAction("`instruction_path_from_literal(ondeck)",
837                                                                    new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"),
838                                                                                     "`instruction_path_literal(ondeck)")),
839                               }
840                       );
841
842         PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
843
844         pw.println("`define instruction_is_load_loop_to_data(i)       "+TAKE_LOOP.verilog("i"));
845         pw.println("`define instruction_is_load_data_to_repeat(i)     "+REPEAT_FROM_DATA.verilog("i"));
846         pw.println("`define instruction_is_load_data_to_loop(i)       "+LOOP_FROM_DATA.verilog("i"));
847         pw.println("`define instruction_is_load_literal_to_repeat(i)  "+REPEAT_FROM_LITERAL.verilog("i"));
848         pw.println("`define instruction_is_load_literal_to_loop(i)    "+LOOP_FROM_LITERAL.verilog("i"));
849         pw.println("`define instruction_is_load_standing_to_repeat(i) "+REPEAT_FROM_STANDING.verilog("i"));
850         pw.println("`define instruction_repeat_count_literal(i)       "+REPEAT_FROM_LITERAL.verilogVal("i"));
851         pw.println("`define instruction_loop_count_literal(i)         "+LOOP_FROM_LITERAL.verilogVal("i"));
852
853         pw.println("`define instruction_path_literal(i)              "+PATH_LITERAL.verilogVal("i"));
854         pw.println("`define instruction_path_from_literal(i)         "+PATH_LITERAL.verilog("i"));
855         pw.println("`define instruction_path_from_data(i)            "+PATH_DATA.verilog("i"));
856
857         pw.println("`define instruction_is_literal_hi(i)             "+LITERAL_HI.verilog("i"));
858         pw.println("`define instruction_is_literal_lo(i)             "+LITERAL_LO.verilog("i"));
859         pw.println("`define instruction_is_literal(i)                "+LITERAL.verilog("i"));
860         pw.println("`define instruction_kill_count(i)                "+KILL.verilogVal("i"));
861         pw.println("`define instruction_is_kill(i)                   "+KILL.verilog("i"));
862         pw.println("`define instruction_is_unclog(i)                 "+UNCLOG.verilog("i"));
863         pw.println("`define instruction_is_clog(i)                   "+CLOG.verilog("i"));
864         pw.println("`define instruction_is_massacre(i)               "+MASSACRE.verilog("i"));
865         pw.println("`define instruction_is_normal(i)                 "+MOVE.verilog("i"));
866
867         pw.println("`define instruction_is_decr_loop(i)              "+DL.verilog("i"));
868
869         pw.println("`define instruction_bit_tokenout(i)     (`instruction_is_normal(i) && "+TO.verilog("i")+")");
870         pw.println("`define instruction_bit_dataout(i)      (`instruction_is_normal(i) && "+DO.verilog("i")+")");
871         pw.println("`define instruction_bit_latch(i)        (`instruction_is_normal(i) && "+DC.verilog("i")+")");
872         pw.println("`define instruction_bit_datain(i)       (`instruction_is_normal(i) && "+DI.verilog("i")+")");
873         pw.println("`define instruction_bit_tokenin(i)      (`instruction_is_normal(i) && "+TI.verilog("i")+")");
874         pw.println("`define is_standing(i)                  (`instruction_is_normal(i) && "+STAND.verilog("i")+")");
875         pw.println("`define should_requeue(i)               (loop_counter > 0)");
876         pw.println("`define done_executing(i)               (!`is_standing(i) && (repcount2==0 || repcount2==1))");
877
878         pw.println("`define magic_standing_value            (1<<"+WIDTH_COUNTER_LITERAL+")");
879
880         pw.println("`define instruction_literal_hi(i,d) { (i[17:0]),  (d[18:0]) }");
881         pw.println("`define instruction_literal_lo(i,d) { (d[36:19]), (i[18:0]) }");
882
883         pw.println("`define instruction_literal_sel(i) " + LITERAL_SEL.verilogVal("i"));
884         pw.println("`define instruction_literal(i) " +
885                    "("+
886                    "  `instruction_literal_sel(i) == 0 ? { (i[17:0]),  {19{1'b0}} } "+
887                    ": `instruction_literal_sel(i) == 1 ? { (i[17:0]),  {19{1'b1}} } "+
888                    ": `instruction_literal_sel(i) == 2 ? { {18{1'b0}}, (i[18:0]) } "+
889                    ":                                    { {18{1'b1}}, (i[18:0]) } "+
890                    ")"
891                    );
892
893
894         box.dump(pw, true);
895         pw.flush();
896         return box;
897     }
898
899 }
900
901
902
903