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