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