1 // note: got rid of funnel "fairness" code
2 package edu.berkeley.fleet.slipway;
3 import edu.berkeley.fleet.slipway.*;
4 import edu.berkeley.fleet.doc.*;
5 import edu.berkeley.fleet.api.*;
6 import edu.berkeley.fleet.ies44.*;
7 import edu.berkeley.fleet.*;
8 import java.lang.reflect.*;
9 import edu.berkeley.sbp.chr.*;
10 import edu.berkeley.sbp.misc.*;
11 import edu.berkeley.sbp.meta.*;
12 import edu.berkeley.sbp.util.*;
16 public class Generator {
19 public static class Module {
21 private final String name;
22 public String getName() { return name; }
24 private HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
25 private final ArrayList<Action> actions = new ArrayList<Action>();
27 // FIXME: always-alphabetical convention?
28 private final HashMap<String,Port> ports = new HashMap<String,Port>();
29 private final ArrayList<String> portorder = new ArrayList<String>();
31 private StringBuffer crap = new StringBuffer();
32 private StringBuffer precrap = new StringBuffer();
33 public void addCrap(String s) { crap.append(s); crap.append('\n'); }
34 public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
36 public Module(String name) {
40 public SourcePort getInputPort(String name, int width) {
41 SourcePort ret = (SourcePort)ports.get(name);
42 if (ret==null) ret = new SourcePort(name, width, true);
45 public SinkPort getOutputPort(String name, int width, String resetBehavior) {
46 SinkPort ret = (SinkPort)ports.get(name);
47 if (ret==null) ret = new SinkPort(name, width, true, resetBehavior);
50 private abstract class Port {
51 public final String name;
52 public String getName() { return name; }
53 public final int width;
54 public boolean hasLatch = false;
55 public boolean supress = false;
56 public boolean noAssignData = false;
57 public boolean external;
58 public boolean pretendDriven = false;
59 public boolean noreg = false;
60 public Port(String name, int width, boolean external) {
63 this.external = external;
64 ports.put(name, this);
68 public String getAck() { return name+"_a"; }
69 public String getReq() { return name+"_r"; }
70 public abstract String getInterface();
71 public abstract String getSimpleInterface();
72 public abstract String getDeclaration();
73 public abstract String getAssignments();
76 private class InstantiatedModule {
77 public final Module module;
79 private final HashMap<String,Port> ports = new HashMap<String,Port>();
80 public String getName() { return module.getName()+"_"+id; }
81 public InstantiatedModule(Module module) {
83 this.id = Module.this.id++;
84 instantiatedModules.add(this);
86 public void dump(PrintWriter pw) {
87 pw.println(" " + module.getName() + " " + getName() + "(clk");
88 for(String s : module.portorder)
89 pw.println(", " + getPort(s, module.ports.get(s).width).getSimpleInterface());
92 public Port getPort(String name, int width) {
93 if (module.ports.get(name) instanceof SinkPort)
94 return getOutputPort(name, width, "");
95 return getInputPort(name, width);
97 public SinkPort getInputPort(String name, int width) {
98 SinkPort port = (SinkPort)ports.get(name);
100 port = new SinkPort(getName()+"_"+name, width, false, "");
101 ports.put(name, port);
105 public SourcePort getOutputPort(String name, int width, String resetBehavior) {
106 SourcePort port = (SourcePort)ports.get(name);
108 port = new SourcePort(getName()+"_"+name, width, false);
109 ports.put(name, port);
115 private class SourcePort extends Port {
116 private SinkPort driven = null;
117 public SourcePort(String name, int width, boolean external) {
118 super(name, width, external); }
119 public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; }
120 public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; }
121 public String getDeclaration() {
122 StringBuffer sb = new StringBuffer();
124 sb.append("input " + name +"_r;\n");
125 sb.append("output " + name +"_a_;\n");
126 sb.append("input ["+(width-1)+":0]" + name +";\n");
128 sb.append("wire " + name +"_r;\n");
129 sb.append("wire ["+(width-1)+":0]" + name +";\n");
132 sb.append("wire " + name +"_a;\n");
134 sb.append("reg " + name +"_a;\n");
135 sb.append("initial " + name +"_a = 0;\n");
137 return sb.toString();
139 public String getAssignments() {
140 StringBuffer sb = new StringBuffer();
141 if (external && !pretendDriven) {
142 sb.append("assign " + name +"_a_ = " + name + "_a;\n");
144 if (driven != null) {
145 sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
146 sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
147 sb.append("assign " + driven.name +" = " + name + ";\n");
149 return sb.toString();
151 public void connect(SinkPort driven) {
152 this.driven = driven;
155 private class SinkPort extends Port {
156 public final String resetBehavior;
157 public SinkPort(String name, int width, boolean external, String resetBehavior) {
158 super(name, width, external); this.resetBehavior=resetBehavior; }
159 public String getResetBehavior() { return resetBehavior; }
160 public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
161 public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
162 public String getDeclaration() {
163 StringBuffer sb = new StringBuffer();
165 sb.append("output " + name +"_r_;\n");
166 sb.append("input " + name +"_a;\n");
167 sb.append("output ["+(width-1)+":0]" + name +"_;\n");
169 sb.append("wire " + name +"_a;\n");
172 sb.append("wire " + name +"_r;\n");
173 sb.append("wire ["+(width-1)+":0]" + name +";\n");
175 sb.append("reg " + name +"_r;\n");
176 sb.append("initial " + name +"_r = 0;\n");
178 sb.append("reg ["+(width-1)+":0]" + name +";\n");
179 sb.append("initial " + name +" = 0;\n");
182 return sb.toString();
184 public String getAssignments() {
185 StringBuffer sb = new StringBuffer();
186 if (external && !pretendDriven) {
187 sb.append("assign " + name +"_r_ = " + name + "_r;\n");
189 sb.append("assign " + name +"_ = " + name + ";\n");
192 return sb.toString();
196 public void dump(PrintWriter pw) {
197 pw.println("`include \"macros.v\"");
198 pw.println("module "+name+"(clk");
199 for(String name : portorder) {
200 Port p = ports.get(name);
201 pw.println(" , " + p.getInterface());
205 pw.println(" input clk;");
206 for(String name : ports.keySet()) {
207 Port p = ports.get(name);
208 pw.println(" " + p.getDeclaration());
210 for(String name : ports.keySet()) {
211 Port p = ports.get(name);
212 pw.println(" " + p.getAssignments());
214 for(InstantiatedModule m : instantiatedModules) {
218 pw.println("always @(posedge clk) begin");
219 for(Port p : ports.values()) {
220 if (p instanceof SourcePort) {
221 SourcePort ip = (SourcePort)p;
222 if (ip.hasLatch && !ip.supress)
223 pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
225 SinkPort op = (SinkPort)p;
226 if (op.hasLatch && !op.supress)
227 pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
229 op.getResetBehavior()+" end");
233 for(Action a : actions) a.dump(pw);
234 pw.println(" begin end");
238 pw.println("endmodule");
241 private class Action {
242 private String[] triggers;
243 private SourcePort[] inports;
244 private SinkPort[] outports;
245 private Object[] actions;
246 public Action(Object[] triggers, String action) { this(triggers, new Object[] { action }); }
247 public Action(Object[] triggers, Object[] actions) {
251 Module.this.actions.add(this);
252 for(int i=0; i<triggers.length; i++)
253 if (triggers[i] instanceof String) numtriggers++;
254 else if (triggers[i] instanceof SourcePort) {
256 ((Port)triggers[i]).hasLatch = true;
257 } else if (triggers[i] instanceof SinkPort) {
259 ((Port)triggers[i]).hasLatch = true;
261 this.triggers = new String[numtriggers];
262 this.inports = new SourcePort[numinports];
263 this.outports = new SinkPort[numoutports];
264 for(int i=0; i<triggers.length; i++)
265 if (triggers[i] instanceof String) this.triggers[--numtriggers] = (String)triggers[i];
266 else if (triggers[i] instanceof SourcePort) this.inports[--numinports] = (SourcePort)triggers[i];
267 else if (triggers[i] instanceof SinkPort) this.outports[--numoutports] = (SinkPort)triggers[i];
268 this.actions = actions;
269 for(Object o : actions)
270 if (o instanceof SourcePort) ((Port)o).hasLatch = true;
271 else if (o instanceof SinkPort) ((Port)o).hasLatch = true;
273 public void dump(PrintWriter pw) {
275 for(String s : triggers) pw.print(" && " + s);
276 for(SourcePort ip : inports) pw.print(" && " + ip.getReq() + " && !"+ip.getAck());
277 for(SinkPort op : outports) pw.print(" && !" + op.getReq() + " && !"+op.getAck());
278 pw.println(") begin ");
279 for(Object s : this.actions) {
280 if (s instanceof String) pw.println(s);
281 else if (s instanceof SourcePort) pw.println(((SourcePort)s).getAck() + " <= 1;");
282 else if (s instanceof SinkPort) pw.println(((SinkPort)s).getReq() + " <= 1;");
284 pw.println("end else ");
289 public static final int WORD_WIDTH = 37;
290 public static final int DESTINATION_WIDTH = 11;
291 public static final int PACKET_WIDTH = WORD_WIDTH + DESTINATION_WIDTH;
292 public static final int INSTRUCTION_WIDTH = WORD_WIDTH;
294 public static void main(String[] s) throws Exception {
295 String prefix = "src/edu/berkeley/fleet/slipway/";
298 mkfunnel("funnel", prefix);
299 mkhorn( "horn", prefix, PACKET_WIDTH-1, DESTINATION_WIDTH-1, 0, 0);
300 mkhorn( "ihorn", prefix, PACKET_WIDTH-1, 34, 24, 0);
302 Module fifostage = mkfifo("fifostage", 0, null, prefix);
303 Module fifo4 = mkfifo("fifo4", 4, fifostage, prefix);
304 Module fifoship = mkfifo("fifo", 4, fifo4, prefix);
305 mkoutbox("outbox", false, prefix, fifo4);
306 mkoutbox("inbox", true, prefix, fifo4);
308 mkkill("kill", prefix);
311 private static Module mkkill(String name, String prefix) throws Exception {
312 Module killm = new Module(name);
313 Module.SourcePort instr = killm.getInputPort("instr", INSTRUCTION_WIDTH);
314 Module.SinkPort kill = killm.getOutputPort("kill", INSTRUCTION_WIDTH+1, "");
315 Module.SinkPort notkill = killm.getOutputPort("notkill", INSTRUCTION_WIDTH, "");
316 killm.addPreCrap(" reg ifull;");
317 killm.addPreCrap(" initial ifull = 0;");
318 killm.new Action(new Object[] { "!ifull", instr, notkill },
319 new Object[] { "notkill = instr;", instr, "ifull = 1;" }
321 killm.new Action(new Object[] { kill, "ifull", "`instruction_is_kill(notkill)" },
322 new Object[] { kill, "ifull=0;",
323 "kill = { `instruction_bit_kill_only_standing(notkill), `instruction_count(notkill) };" }
325 killm.new Action(new Object[] { notkill, "ifull", "!`instruction_is_kill(notkill)" },
326 new Object[] { notkill, "ifull=0;" }
328 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
334 private static Module mkfunnel(String name, String prefix) throws Exception {
335 Module funnel = new Module(name);
336 Module.SinkPort out = funnel.getOutputPort("out", PACKET_WIDTH, "");
337 Module.SourcePort in1 = funnel.getInputPort("in1", PACKET_WIDTH);
338 Module.SourcePort in2 = funnel.getInputPort("in2", PACKET_WIDTH);
339 funnel.new Action(new Object[] { in1, out }, new Object[] { in1, out, "out = in1;" });
340 funnel.new Action(new Object[] { in2, out }, new Object[] { in2, out, "out = in2;" });
341 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
347 private static Module mkoutbox(String name, boolean inbox, String prefix, Module fifo) throws Exception {
348 Module box = new Module(name);
349 Module.SourcePort instr = box.getInputPort("instr", INSTRUCTION_WIDTH);
350 //instr.hasLatch = true;
351 //instr.supress = true;
352 Module.SourcePort fabric_in = box.getInputPort("fabric_in", PACKET_WIDTH);
353 Module.SinkPort fabric_out = box.getOutputPort("fabric_out", PACKET_WIDTH, "");
354 fabric_out.hasLatch = true;
355 //fabric_out.supress = true;
357 Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo);
358 fabric_in.connect(dfifo.getInputPort("in", PACKET_WIDTH));
360 Module.SourcePort dfifo_out = dfifo.getOutputPort("out", PACKET_WIDTH, "");
361 String fabric_in_d0 = dfifo_out.name;
362 String fabric_in_r0 = fabric_in_d0+"_r";
363 String fabric_in_a0 = fabric_in_d0+"_a";
364 dfifo_out.hasLatch = true;
366 Module.SourcePort ship_out = null;
368 ship_out = box.getInputPort("ship", WORD_WIDTH);
369 ship_out.hasLatch = true;
372 Module.SinkPort ship_in = null;
374 ship_in = box.getOutputPort("ship", PACKET_WIDTH, "");
375 ship_in.hasLatch = true;
378 box.addPreCrap(" reg[(`INSTRUCTION_WIDTH-1):0] ondeck;");
379 box.addPreCrap(" reg[(`COUNT_WIDTH-1):0] repcount;");
380 box.addPreCrap(" initial ondeck=0;");
381 box.addPreCrap(" reg ondeck_full; initial ondeck_full=0;");
382 box.addPreCrap(" reg newmayproceed; initial newmayproceed=1;");
383 box.addPreCrap(" reg dorepeat; initial dorepeat=0;");
384 box.addPreCrap(" reg dorepeatkill; initial dorepeatkill=0;");
385 box.addPreCrap(" reg dokill; initial dokill=0;");
386 box.addPreCrap(" reg clogged; initial clogged=0;");
388 // FIXME: destination
389 Module.SinkPort token_out = fabric_out;
390 Module.SourcePort token_in = dfifo_out;
391 Module.SinkPort data_out = inbox ? ship_in : fabric_out;
392 Module.SourcePort data_in = inbox ? dfifo_out : ship_out;
394 Module.InstantiatedModule ififo = box.new InstantiatedModule(fifo);
395 Module.SinkPort ififo_in = ififo.getInputPort("in", PACKET_WIDTH);
396 ififo_in.hasLatch = true;
397 Module.SourcePort ififo_out = ififo.getOutputPort("out", PACKET_WIDTH, "");
399 // Clog (must be first)
401 new Object[] { ififo_out, "newmayproceed==1", "`instruction_is_clog("+ififo_out.getName()+")" },
402 new Object[] { ififo_out, "clogged <= 1;", "newmayproceed<=0;" }
407 new Object[] { instr, "clogged==1", "`instruction_is_unclog(instr)" },
408 new Object[] { instr, "clogged <= 0;", "newmayproceed<=1;" }
413 new Object[] { instr, ififo_out, "`instruction_is_kill(instr)", "!`instruction_is_unclog(instr)", "newmayproceed==1" },
414 new Object[] { instr, ififo_out,
415 "if (`instruction_count(instr)!=0)"+
416 " begin repcount <= `instruction_count(instr)-1; newmayproceed <= 0; "+
417 " dorepeatkill <= 1; end else begin newmayproceed<=1; end" }
422 new Object[] { "dokill==1" },
423 new Object[] { "dokill<=0;",
424 "if (`instruction_count(ondeck)!=0)"+
425 " begin repcount <= `instruction_count(ondeck)-1;"+
426 " dorepeatkill <= 1; end else begin newmayproceed<=1; end" }
431 new Object[] { "dorepeatkill==1", ififo_out },
432 new Object[] { "dorepeatkill<=0;", ififo_out, "dokill<=1;", "`instruction_count(ondeck)<=repcount;" }
437 new Object[] { instr, ififo_in, "!`instruction_is_kill(instr)" },
438 new Object[] { instr, ififo_in, ififo_in.getName()+"<=instr;" }
443 new Object[] { ififo_out, "ondeck_full==0", "newmayproceed==1" },
444 new Object[] { ififo_out, "ondeck_full<=1;", "newmayproceed<=0;",
445 "ondeck<="+ififo_out.getName()+";" }
450 new Object[] { "dorepeat==1", },
451 new Object[] { "dorepeat<=0;", "ondeck_full<=1;", "`instruction_count(ondeck)<=repcount;" }
454 for(int di=0; di<=1; di++)
455 for(int dout=0; dout<=1; dout++)
456 for(int tout=0; tout<=1; tout++)
457 for(int ti=0; ti<=1; ti++) {
459 new Object[] { "ondeck_full==1",
463 (di==1 ? "" : "!")+"`instruction_bit_datain(ondeck)",
464 (di==1 ? data_in : "1"),
465 (ti==1 ? "" : "!")+"`instruction_bit_tokenin(ondeck)",
466 (ti==1 ? token_in : "1"),
467 (dout==1 ? "" : "!")+"`instruction_bit_dataout(ondeck)",
468 (tout==1 ? "" : "!")+"`instruction_bit_tokenout(ondeck)"
470 new Object[] { "ondeck_full<=0;",
471 "if (`instruction_count(ondeck)==1 || `instruction_bit_recycle(ondeck)) newmayproceed<=1;",
472 "if (`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1) "+
473 " begin "+ififo_in.getName()+"<=ondeck; "+
474 " `instruction_count("+ififo_in.getName()+")<=(`instruction_count(ondeck)==0?0:`instruction_count(ondeck)-1);"+
475 " "+ififo_in.getReq()+"<=1; end",
476 "if (!`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1) "+
478 "repcount <= (`instruction_count(ondeck)==0 ? 0 : (`instruction_count(ondeck)-1));",
479 (di==1 ? data_in : ""),
480 (dout==1 ? data_out : ""),
481 (ti==1 ? token_in : ""),
482 (tout==1 ? token_out : ""),
483 ("if (`instruction_bit_latch(ondeck)) "+
484 (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+
486 (inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName())+";"),
487 (tout==1 ? "`packet_dest("+token_out.getName()+")<=`instruction_bit_dest(ondeck);" : ""),
488 (dout==1 && !inbox ? "`packet_dest("+data_out.getName()+")<=`instruction_bit_dest(ondeck);" : "")
493 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
499 private static Module mkfifo(String name, int len, Module instance, String prefix) throws Exception {
500 Module fifo4 = new Module(name);
501 Module.SourcePort inx = fifo4.getInputPort("in", PACKET_WIDTH);
502 Module.SinkPort outx = fifo4.getOutputPort("out", PACKET_WIDTH, "");
503 Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
505 fifo4.new Action(new Object[] { inx, outx }, new Object[] { inx, outx, "out = in;" });
506 } else for(int i=0; i<=len; i++) {
507 if (i<len) stages[i] = fifo4.new InstantiatedModule(instance);
508 Module.SourcePort driver = i==0 ? inx : stages[i-1].getOutputPort("out", PACKET_WIDTH, "");
509 Module.SinkPort driven = i==len ? outx : stages[i].getInputPort("in", PACKET_WIDTH);
510 driver.connect(driven);
512 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
518 public static void mkhorn(String name,
521 int top_of_addr_field,
522 int bot_of_addr_field,
523 int bot) throws Exception {
524 Module horn = new Module(name);
525 Module.SourcePort in = horn.getInputPort("in", PACKET_WIDTH);
526 Module.SinkPort out0 = horn.getOutputPort("out0", PACKET_WIDTH, "");
527 Module.SinkPort out1 = horn.getOutputPort("out1", PACKET_WIDTH, "");
528 String shifted_packet = "{ ";
529 if (top_of_addr_field+1 < top) shifted_packet += " in["+top+":"+(top_of_addr_field+1)+"], ";
530 shifted_packet += " (in["+(top_of_addr_field)+":"+bot_of_addr_field+"] >> 1) ";
531 if (bot_of_addr_field > 0) shifted_packet += ", in["+(bot_of_addr_field-1)+":0] ";
532 shifted_packet += " }";
533 // same behavior as FLEET -- wait for both
534 horn.new Action(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" },
535 new Object[] { in, out0, "out0 = " + shifted_packet + ";" });
536 horn.new Action(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" },
537 new Object[] { in, out1, "out1 = " + shifted_packet + ";" });
539 PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));