public static class Module {
private int id = 0;
- private HashSet<InstantiatedModule> instantiatedModules =
- new HashSet<InstantiatedModule>();
private final String name;
public String getName() { return name; }
- private final HashSet<Action> actions = new HashSet<Action>();
+ private HashSet<InstantiatedModule> instantiatedModules = new HashSet<InstantiatedModule>();
+ private final ArrayList<Action> actions = new ArrayList<Action>();
// FIXME: always-alphabetical convention?
private final HashMap<String,Port> ports = new HashMap<String,Port>();
private final ArrayList<String> portorder = new ArrayList<String>();
+ private StringBuffer crap = new StringBuffer();
+ private StringBuffer precrap = new StringBuffer();
+ public void addCrap(String s) { crap.append(s); crap.append('\n'); }
+ public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); }
+
public Module(String name) {
this.name = name;
}
}
private abstract class Port {
public final String name;
+ public String getName() { return name; }
public final int width;
public boolean hasLatch = false;
+ public boolean supress = false;
+ public boolean noAssignData = false;
public boolean external;
+ public boolean pretendDriven = false;
+ public boolean noreg = false;
public Port(String name, int width, boolean external) {
this.width = width;
this.name = name;
private class InstantiatedModule {
public final Module module;
public final int id;
+ private final HashMap<String,Port> ports = new HashMap<String,Port>();
public String getName() { return module.getName()+"_"+id; }
public InstantiatedModule(Module module) {
this.module = module;
}
public Port getPort(String name, int width) {
if (module.ports.get(name) instanceof SinkPort)
- return getInputPort(name, width);
- return getOutputPort(name, width, "");
+ return getOutputPort(name, width, "");
+ return getInputPort(name, width);
}
public SinkPort getInputPort(String name, int width) {
- // FIXME: should not re-instantiate, but so what
- return new SinkPort(getName()+"_"+name, width, false, "");
+ SinkPort port = (SinkPort)ports.get(name);
+ if (port == null) {
+ port = new SinkPort(getName()+"_"+name, width, false, "");
+ ports.put(name, port);
+ }
+ return port;
}
public SourcePort getOutputPort(String name, int width, String resetBehavior) {
- // FIXME: should not re-instantiate, but so what
- return new SourcePort(getName()+"_"+name, width, false);
+ SourcePort port = (SourcePort)ports.get(name);
+ if (port == null) {
+ port = new SourcePort(getName()+"_"+name, width, false);
+ ports.put(name, port);
+ }
+ return port;
}
}
}
public String getAssignments() {
StringBuffer sb = new StringBuffer();
- if (external) {
+ if (external && !pretendDriven) {
sb.append("assign " + name +"_a_ = " + name + "_a;\n");
}
if (driven != null) {
} else {
sb.append("reg " + name +"_r;\n");
sb.append("initial " + name +"_r = 0;\n");
- sb.append("reg ["+(width-1)+":0]" + name +";\n");
- sb.append("initial " + name +" = 0;\n");
+ if (!noreg) {
+ sb.append("reg ["+(width-1)+":0]" + name +";\n");
+ sb.append("initial " + name +" = 0;\n");
+ }
}
return sb.toString();
}
public String getAssignments() {
StringBuffer sb = new StringBuffer();
- if (external) {
+ if (external && !pretendDriven) {
sb.append("assign " + name +"_r_ = " + name + "_r;\n");
- sb.append("assign " + name +"_ = " + name + ";\n");
+ if (!noAssignData) {
+ sb.append("assign " + name +"_ = " + name + ";\n");
+ }
}
return sb.toString();
}
}
public void dump(PrintWriter pw) {
+ pw.println("`include \"macros.v\"");
pw.println("module "+name+"(clk");
for(String name : portorder) {
Port p = ports.get(name);
for(InstantiatedModule m : instantiatedModules) {
m.dump(pw);
}
+ pw.println(precrap);
pw.println("always @(posedge clk) begin");
- for(String name : portorder) {
- Port p = ports.get(name);
+ for(Port p : ports.values()) {
if (p instanceof SourcePort) {
SourcePort ip = (SourcePort)p;
- if (ip.hasLatch)
+ if (ip.hasLatch && !ip.supress)
pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
} else {
SinkPort op = (SinkPort)p;
- if (op.hasLatch)
+ if (op.hasLatch && !op.supress)
pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
op.getReq()+"<=0; "+
op.getResetBehavior()+" end");
for(Action a : actions) a.dump(pw);
pw.println(" begin end");
pw.println("end");
+
+ pw.println(crap);
pw.println("endmodule");
}
public static final int WORD_WIDTH = 37;
public static final int DESTINATION_WIDTH = 11;
public static final int PACKET_WIDTH = WORD_WIDTH + DESTINATION_WIDTH;
+ public static final int INSTRUCTION_WIDTH = WORD_WIDTH;
public static void main(String[] s) throws Exception {
String prefix = "src/edu/berkeley/fleet/slipway/";
PrintWriter pw;
- Module funnel = new Module("funnel");
- Module.SinkPort out = funnel.getOutputPort("out", PACKET_WIDTH, "");
+ mkfunnel("funnel", prefix);
+ mkhorn( "horn", prefix, PACKET_WIDTH-1, DESTINATION_WIDTH-1, 0, 0);
+ mkhorn( "ihorn", prefix, PACKET_WIDTH-1, 34, 24, 0);
+
+ Module fifostage = mkfifo("fifostage", 0, null, prefix);
+ Module fifo4 = mkfifo("fifo4", 4, fifostage, prefix);
+ Module fifoship = mkfifo("fifo", 4, fifo4, prefix);
+ mkoutbox("outbox", false, prefix, fifo4);
+ mkoutbox("inbox", true, prefix, fifo4);
+
+ mkkill("kill", prefix);
+ }
+
+ private static Module mkkill(String name, String prefix) throws Exception {
+ Module killm = new Module(name);
+ Module.SourcePort instr = killm.getInputPort("instr", INSTRUCTION_WIDTH);
+ Module.SinkPort kill = killm.getOutputPort("kill", INSTRUCTION_WIDTH+1, "");
+ Module.SinkPort notkill = killm.getOutputPort("notkill", INSTRUCTION_WIDTH, "");
+ killm.addPreCrap(" reg ifull;");
+ killm.addPreCrap(" initial ifull = 0;");
+ killm.new Action(new Object[] { "!ifull", instr, notkill },
+ new Object[] { "notkill = instr;", instr, "ifull = 1;" }
+ );
+ killm.new Action(new Object[] { kill, "ifull", "`instruction_is_kill(notkill)" },
+ new Object[] { kill, "ifull=0;",
+ "kill = { `instruction_bit_kill_only_standing(notkill), `instruction_count(notkill) };" }
+ );
+ killm.new Action(new Object[] { notkill, "ifull", "!`instruction_is_kill(notkill)" },
+ new Object[] { notkill, "ifull=0;" }
+ );
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
+ killm.dump(pw);
+ pw.flush();
+ return killm;
+ }
+
+ private static Module mkfunnel(String name, String prefix) throws Exception {
+ Module funnel = new Module(name);
+ Module.SinkPort out = funnel.getOutputPort("out", PACKET_WIDTH, "");
Module.SourcePort in1 = funnel.getInputPort("in1", PACKET_WIDTH);
Module.SourcePort in2 = funnel.getInputPort("in2", PACKET_WIDTH);
funnel.new Action(new Object[] { in1, out }, new Object[] { in1, out, "out = in1;" });
funnel.new Action(new Object[] { in2, out }, new Object[] { in2, out, "out = in2;" });
- pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/funnel.v")));
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
funnel.dump(pw);
pw.flush();
+ return funnel;
+ }
+
+ private static Module mkoutbox(String name, boolean inbox, String prefix, Module fifo) throws Exception {
+ Module box = new Module(name);
+ Module.SourcePort instr = box.getInputPort("instr", INSTRUCTION_WIDTH);
+ //instr.hasLatch = true;
+ //instr.supress = true;
+ Module.SourcePort fabric_in = box.getInputPort("fabric_in", PACKET_WIDTH);
+ Module.SinkPort fabric_out = box.getOutputPort("fabric_out", PACKET_WIDTH, "");
+ fabric_out.hasLatch = true;
+ //fabric_out.supress = true;
- mkhorn( "horn", prefix, PACKET_WIDTH-1, DESTINATION_WIDTH-1, 0, 0);
- mkhorn("ihorn", prefix, PACKET_WIDTH-1, 34, 24, 0);
+ Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo);
+ fabric_in.connect(dfifo.getInputPort("in", PACKET_WIDTH));
+
+ Module.SourcePort dfifo_out = dfifo.getOutputPort("out", PACKET_WIDTH, "");
+ String fabric_in_d0 = dfifo_out.name;
+ String fabric_in_r0 = fabric_in_d0+"_r";
+ String fabric_in_a0 = fabric_in_d0+"_a";
+ dfifo_out.hasLatch = true;
+
+ Module.SourcePort ship_out = null;
+ if (!inbox) {
+ ship_out = box.getInputPort("ship", WORD_WIDTH);
+ ship_out.hasLatch = true;
+ }
+
+ Module.SinkPort ship_in = null;
+ if (inbox) {
+ ship_in = box.getOutputPort("ship", PACKET_WIDTH, "");
+ ship_in.hasLatch = true;
+ }
+
+ box.addPreCrap(" reg[(`INSTRUCTION_WIDTH-1):0] ondeck;");
+ box.addPreCrap(" reg[(`COUNT_WIDTH-1):0] repcount;");
+ box.addPreCrap(" initial ondeck=0;");
+ box.addPreCrap(" reg ondeck_full; initial ondeck_full=0;");
+ box.addPreCrap(" reg newmayproceed; initial newmayproceed=1;");
+ box.addPreCrap(" reg dorepeat; initial dorepeat=0;");
+ box.addPreCrap(" reg dorepeatkill; initial dorepeatkill=0;");
+ box.addPreCrap(" reg dokill; initial dokill=0;");
+ box.addPreCrap(" reg clogged; initial clogged=0;");
+
+ // FIXME: destination
+ Module.SinkPort token_out = fabric_out;
+ Module.SourcePort token_in = dfifo_out;
+ Module.SinkPort data_out = inbox ? ship_in : fabric_out;
+ Module.SourcePort data_in = inbox ? dfifo_out : ship_out;
+
+ Module.InstantiatedModule ififo = box.new InstantiatedModule(fifo);
+ Module.SinkPort ififo_in = ififo.getInputPort("in", PACKET_WIDTH);
+ ififo_in.hasLatch = true;
+ Module.SourcePort ififo_out = ififo.getOutputPort("out", PACKET_WIDTH, "");
+
+ // Clog (must be first)
+ box.new Action(
+ new Object[] { ififo_out, "newmayproceed==1", "`instruction_is_clog("+ififo_out.getName()+")" },
+ new Object[] { ififo_out, "clogged <= 1;", "newmayproceed<=0;" }
+ );
+
+ // UnClog
+ box.new Action(
+ new Object[] { instr, "clogged==1", "`instruction_is_unclog(instr)" },
+ new Object[] { instr, "clogged <= 0;", "newmayproceed<=1;" }
+ );
+
+ // First Kill
+ box.new Action(
+ new Object[] { instr, ififo_out, "`instruction_is_kill(instr)", "!`instruction_is_unclog(instr)", "newmayproceed==1" },
+ new Object[] { instr, ififo_out,
+ "if (`instruction_count(instr)!=0)"+
+ " begin repcount <= `instruction_count(instr)-1; newmayproceed <= 0; "+
+ " dorepeatkill <= 1; end else begin newmayproceed<=1; end" }
+ );
- Module fifostage = new Module("fifostage");
- Module.SourcePort in = fifostage.getInputPort("in", PACKET_WIDTH);
- Module.SinkPort outf = fifostage.getOutputPort("out", PACKET_WIDTH, "");
- fifostage.new Action(new Object[] { in, outf }, new Object[] { in, outf, "out = in;" });
- pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/fifostage.v")));
- fifostage.dump(pw);
+ // Kill
+ box.new Action(
+ new Object[] { "dokill==1" },
+ new Object[] { "dokill<=0;",
+ "if (`instruction_count(ondeck)!=0)"+
+ " begin repcount <= `instruction_count(ondeck)-1;"+
+ " dorepeatkill <= 1; end else begin newmayproceed<=1; end" }
+ );
+
+ // RepKill
+ box.new Action(
+ new Object[] { "dorepeatkill==1", ififo_out },
+ new Object[] { "dorepeatkill<=0;", ififo_out, "dokill<=1;", "`instruction_count(ondeck)<=repcount;" }
+ );
+
+ // Enqueue
+ box.new Action(
+ new Object[] { instr, ififo_in, "!`instruction_is_kill(instr)" },
+ new Object[] { instr, ififo_in, ififo_in.getName()+"<=instr;" }
+ );
+
+ // New
+ box.new Action(
+ new Object[] { ififo_out, "ondeck_full==0", "newmayproceed==1" },
+ new Object[] { ififo_out, "ondeck_full<=1;", "newmayproceed<=0;",
+ "ondeck<="+ififo_out.getName()+";" }
+ );
+
+ // RepeatExecute
+ box.new Action(
+ new Object[] { "dorepeat==1", },
+ new Object[] { "dorepeat<=0;", "ondeck_full<=1;", "`instruction_count(ondeck)<=repcount;" }
+ );
+
+ for(int di=0; di<=1; di++)
+ for(int dout=0; dout<=1; dout++)
+ for(int tout=0; tout<=1; tout++)
+ for(int ti=0; ti<=1; ti++) {
+ box.new Action(
+ new Object[] { "ondeck_full==1",
+ data_out,
+ token_out,
+ ififo_in,
+ (di==1 ? "" : "!")+"`instruction_bit_datain(ondeck)",
+ (di==1 ? data_in : "1"),
+ (ti==1 ? "" : "!")+"`instruction_bit_tokenin(ondeck)",
+ (ti==1 ? token_in : "1"),
+ (dout==1 ? "" : "!")+"`instruction_bit_dataout(ondeck)",
+ (tout==1 ? "" : "!")+"`instruction_bit_tokenout(ondeck)"
+ },
+ new Object[] { "ondeck_full<=0;",
+ "if (`instruction_count(ondeck)==1 || `instruction_bit_recycle(ondeck)) newmayproceed<=1;",
+ "if (`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1) "+
+ " begin "+ififo_in.getName()+"<=ondeck; "+
+ " `instruction_count("+ififo_in.getName()+")<=(`instruction_count(ondeck)==0?0:`instruction_count(ondeck)-1);"+
+ " "+ififo_in.getReq()+"<=1; end",
+ "if (!`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1) "+
+ " dorepeat <= 1;",
+ "repcount <= (`instruction_count(ondeck)==0 ? 0 : (`instruction_count(ondeck)-1));",
+ (di==1 ? data_in : ""),
+ (dout==1 ? data_out : ""),
+ (ti==1 ? token_in : ""),
+ (tout==1 ? token_out : ""),
+ ("if (`instruction_bit_latch(ondeck)) "+
+ (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+
+ "<="+
+ (inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName())+";"),
+ (tout==1 ? "`packet_dest("+token_out.getName()+")<=`instruction_bit_dest(ondeck);" : ""),
+ (dout==1 && !inbox ? "`packet_dest("+data_out.getName()+")<=`instruction_bit_dest(ondeck);" : "")
+ }
+ );
+ }
+
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
+ box.dump(pw);
pw.flush();
+ return box;
+ }
- Module fifo4 = new Module("fifo4");
+ private static Module mkfifo(String name, int len, Module instance, String prefix) throws Exception {
+ Module fifo4 = new Module(name);
Module.SourcePort inx = fifo4.getInputPort("in", PACKET_WIDTH);
Module.SinkPort outx = fifo4.getOutputPort("out", PACKET_WIDTH, "");
- int len = 4;
Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
- for(int i=0; i<=len; i++) {
- if (i<len) stages[i] = fifo4.new InstantiatedModule(fifostage);
+ if (len==0) {
+ fifo4.new Action(new Object[] { inx, outx }, new Object[] { inx, outx, "out = in;" });
+ } else for(int i=0; i<=len; i++) {
+ if (i<len) stages[i] = fifo4.new InstantiatedModule(instance);
Module.SourcePort driver = i==0 ? inx : stages[i-1].getOutputPort("out", PACKET_WIDTH, "");
Module.SinkPort driven = i==len ? outx : stages[i].getInputPort("in", PACKET_WIDTH);
driver.connect(driven);
}
- pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/fifo4.v")));
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
fifo4.dump(pw);
pw.flush();
+ return fifo4;
}
public static void mkhorn(String name,
+++ /dev/null
- reg have_instruction;
- reg need_to_read_token;
- reg need_to_read_data;
- reg need_to_send_token;
- reg need_to_send_data;
- reg parse_instruction;
- reg do_recycle;
- reg fire_ok;
- reg kill_only_standing;
- reg [(`COUNT_BITS-1):0] kill_count;
- reg [(`INSTRUCTION_WIDTH-1):0] instruction;
-
- wire [(`INSTRUCTION_WIDTH-1):0] instr_d2;
- wire [(`INSTRUCTION_WIDTH-1):0] instr_d0;
-
- reg kill_r;
- reg kill_a;
- reg [(`COUNT_WIDTH-1+1):0] kill_d;
-
- reg [(`INSTRUCTION_WIDTH-1):0] kinstruction;
- reg instr_rx;
- wire instr_ax;
- reg ifull;
-
- always @(posedge clk) begin
- if (!ifull) begin
- `onread(instr_r, instr_a)
- ifull = 1;
- kinstruction = instr_d;
- end
- end else begin
- if (`instruction_is_kill(kinstruction)) begin
- kill_d = { `instruction_bit_kill_only_standing(kinstruction), `instruction_count(kinstruction) };
- `onwrite(kill_r, kill_a)
- ifull = 0;
- end
- end else begin
- `onwrite(instr_rx, instr_ax)
- ifull = 0;
- end
- end
- end
- end
-
- reg recycle_r;
- wire recycle_r_;
- assign recycle_r_ = recycle_r;
- wire recycle_a;
- wire [(`INSTRUCTION_WIDTH-1):0] recycle_inst;
- assign recycle_inst = instruction;
-
- wire instr_a2_;
- reg instr_a2;
- assign instr_a2_ = instr_a2;
-
- funnel ifunnel(clk, instr_r0, instr_a0, instr_d0,
- instr_rx, instr_ax, kinstruction,
- recycle_r_, recycle_a, recycle_inst);
-
- fifo4 ififo(clk, instr_r0, instr_a0, instr_d0,
- instr_r2, instr_a2_, instr_d2);
-
- always @(posedge clk) begin
-
- if (do_recycle) begin
- `onwrite(recycle_r, recycle_a)
- do_recycle = 0;
- have_instruction = 0;
- parse_instruction = 0;
- end
-
- end else if (fire_ok) begin
- if (need_to_send_data) begin
- `onwrite(`data_out_r, `data_out_a)
- need_to_send_data = 0;
- end
-
- end else if (need_to_send_token) begin
- `onwrite(`token_out_r, `token_out_a)
- need_to_send_token = 0;
- end
-
- end else begin
- fire_ok = 0;
- case (`instruction_count(instruction))
- 0: begin end
- 1: have_instruction = 0;
- default: `instruction_count(instruction) = `instruction_count(instruction) - 1;
- endcase
- if (have_instruction && `instruction_bit_recycle(instruction)) begin
- do_recycle = 1;
- end else begin
- parse_instruction = have_instruction;
- end
- end
-
- end else if (!have_instruction && !parse_instruction) begin
- `onread(instr_r2, instr_a2)
- instruction = instr_d2;
- parse_instruction = 1;
- end
-
- end else begin
- // FIXME: actually don't want to kill partway through an instruction
- `onread(kill_r, kill_a)
- kill_only_standing = kill_d[`COUNT_WIDTH];
- kill_count = kill_count + kill_d[(`COUNT_WIDTH-1):0];
- end
-
- if ((parse_instruction || have_instruction) && (kill_count > 0) &&
- (!kill_only_standing || `instruction_count(instruction)==0))
- begin
- kill_count = kill_count - 1;
- have_instruction = 0;
- parse_instruction = 0;
- end
-
- if (parse_instruction) begin
- need_to_read_token = `instruction_bit_tokenin(instruction);
- need_to_read_data = `instruction_bit_datain(instruction);
- `packet_dest(`data_out_d) = `instruction_bit_dest(instruction);
- `packet_dest(`token_out_d) = `instruction_bit_dest(instruction);
- need_to_send_data = `instruction_bit_dataout(instruction);
- need_to_send_token = `instruction_bit_tokenout(instruction);
- have_instruction = 1;
- parse_instruction = 0;
- end
-
- // return to zero
- if (!`token_in_r && `token_in_a) `token_in_a = 0;
- if (!`data_in_r && `data_in_a) `data_in_a = 0;
-
- if (have_instruction &&
- (!need_to_read_token || (`token_in_r && !`token_in_a)) &&
- (!need_to_read_data || (`data_in_r && !`data_in_a))
- ) begin
- if (need_to_read_token) begin
- `token_in_a = 1;
- need_to_read_token = 0;
- end
- if (need_to_read_data) begin
- `data_in_a = 1;
- need_to_read_data = 0;
- end
- if (`instruction_bit_latch(instruction)) begin
- `packet_data(`data_out_d) = `data_in_d;
- `extra
- end
- fire_ok = 1;
- end
-
- end
- end