From: adam Date: Mon, 20 Aug 2007 06:55:23 +0000 (+0100) Subject: massive revamp of fpga code X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=3b6aafe3252b2509d08004a3f5e1bd09ca6e9ffb;p=fleet.git massive revamp of fpga code --- diff --git a/doc/archman.tex b/doc/archman.tex index 6938fc6..06798bf 100644 --- a/doc/archman.tex +++ b/doc/archman.tex @@ -245,11 +245,11 @@ Normal \item [\tt Do] ({\bf Data Output}) emit a datum. \item [\tt To] ({\bf Token Output}) emit a token.\footnote{ {\tt To}=1,{\tt - Do}=1 is invalid on outbox.} + Do}=1 have special meaning on an outbox.} \item [\tt Ig] ({\bf Ignore {\tt To} Until Last Iteration}) ignore the {\tt To} bit unless {\tt Count=0} \footnote{{\tt - To}=0,{\tt Ig}=1 is invalid, {\tt Rq}=0,{\tt Ig}=1 is invalid} + To}=0,{\tt Ig}=1 is invalid} \item [\tt Rq] ({\bf ReQueue}) if set, instructions having nonzero count are ``Re-Queued'' rather than RePeated. See @@ -262,7 +262,7 @@ Normal if (Count==0) { discard this instruction } else { - if Count<1111111 { + if Count < MAX_COUNT { decrement count } if Rq=1 or Literal { @@ -275,8 +275,15 @@ if (Count==0) { Note how a ``standing'' instruction is encoded as {\tt Count=1111111} \item [\tt Dest] ({\bf Data/Token Destination}) - This field is copied into the address portion of any outgoing - packet ({\tt Do} on an outbox or {\tt To}). + Normally, this field is copied into the address portion of any + outgoing packet ({\tt Do} on an outbox or {\tt To}). + + However, in the special case of an outbox, if {\tt Do=1,To=1}, then + the {\it most significant} {\tt 11} bits of the value in the {\it + data register} are used as a destination address instead. \footnote{This + functionality eliminates the need for any sort of ``{\tt Execute}'' + ship, and lets a {\tt Fifo} ship act as an extension of the + instruction queue in the pump.} \end{itemize} diff --git a/src/edu/berkeley/fleet/slipway/Generator.java b/src/edu/berkeley/fleet/slipway/Generator.java index 35b606c..32e39c8 100644 --- a/src/edu/berkeley/fleet/slipway/Generator.java +++ b/src/edu/berkeley/fleet/slipway/Generator.java @@ -15,18 +15,102 @@ import java.io.*; public class Generator { + public static class SimpleValue implements Value { + private final String s; + public SimpleValue(String s) { this.s = s; } + public SimpleValue(String s, int high, int low) { this.s = s+"["+high+":"+low+"]"; } + public Value getBits(int high, int low) { return new SimpleValue(s, high, low); } + public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); } + public String getVerilogName() { return s; } + public String toString() { return s; } + } + + public static interface Action { + public String getVerilogAction(); + } + + public static interface Trigger { + public String getVerilogTrigger(); + } + + public static interface Assignable { + public String getVerilogName(); + public Assignable getAssignableBits(int high, int low); + } + + public static interface Value extends Assignable { + public String getVerilogName(); + public Value getBits(int high, int low); + } + + public static class ConditionalAction implements Action { + private String condition; + private Action action; + public ConditionalAction(String condition, Action action) { + this.condition = condition; + this.action = action; + } + public String toString() { return getVerilogAction(); } + public String getVerilogAction() { return "if ("+condition+") begin "+action.getVerilogAction()+" end"; } + } + + public static class ConditionalTrigger implements Trigger { + private String condition; + private Trigger trigger; + public ConditionalTrigger(String condition, Trigger trigger) { + this.condition = condition; + this.trigger = trigger; + if (trigger instanceof Module.Port) + ((Module.Port)trigger).hasLatch = true; + } + public String getVerilogTrigger() { + return "&& (("+condition+") ? (1 " + trigger.getVerilogTrigger() + ") : 1)"; + } + } + + public static class SimpleAssignable implements Assignable { + private final String s; + public SimpleAssignable(String s) { this.s = s; } + public String getVerilogName() { return s; } + public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); } + } + + public static class AssignAction implements Action { + private String left; + private String right; + public AssignAction(Assignable left, Value right) { + this.left = left.getVerilogName(); + this.right = right.getVerilogName().toString(); + } + public AssignAction(Assignable left, String right) { + this.left = left.getVerilogName(); + this.right = right; + } + public String getVerilogAction() { return left + "<=" + right + ";"; } + public String toString() { return getVerilogAction(); } + } + + public static class SimpleAction implements Action { + private final String verilog; + public SimpleAction(String verilog) { this.verilog = verilog; } + public String getVerilogAction() { return verilog; } + public String toString() { return verilog; } + } public static class Module { private int id = 0; private final String name; public String getName() { return name; } + public Port getPort(String name) { return ports.get(name); } private HashSet instantiatedModules = new HashSet(); - private final ArrayList actions = new ArrayList(); + private final ArrayList events = new ArrayList(); // FIXME: always-alphabetical convention? private final HashMap ports = new HashMap(); private final ArrayList portorder = new ArrayList(); + private final HashMap statewires = new HashMap(); + private final HashMap latches = new HashMap(); private StringBuffer crap = new StringBuffer(); private StringBuffer precrap = new StringBuffer(); @@ -37,26 +121,69 @@ public class Generator { this.name = name; } - public SourcePort getInputPort(String name, int width) { + public SourcePort createInputPort(String name, int width) { + if (ports.get(name)!=null) throw new RuntimeException(); + return new SourcePort(name, width, true); + } + public SourcePort getInputPort(String name) { SourcePort ret = (SourcePort)ports.get(name); - if (ret==null) ret = new SourcePort(name, width, true); + if (ret==null) throw new RuntimeException(); return ret; } - public SinkPort getOutputPort(String name, int width, String resetBehavior) { + public SinkPort createOutputPort(String name, int width, String resetBehavior) { + if (ports.get(name)!=null) throw new RuntimeException(); + return new SinkPort(name, width, true, resetBehavior); + } + public SinkPort getOutputPort(String name) { SinkPort ret = (SinkPort)ports.get(name); - if (ret==null) ret = new SinkPort(name, width, true, resetBehavior); + if (ret==null) throw new RuntimeException(); return ret; } - private abstract class Port { + + private class StateWire { public final String name; + public final boolean initiallyFull; public String getName() { return name; } + public Action isFull() { return new SimpleAction(name+"==1"); } + public Action isEmpty() { return new SimpleAction(name+"==0"); } + public Action doFill() { return new SimpleAction(name+"<=1;"); } + public Action doDrain() { return new SimpleAction(name+"<=0;"); } + public StateWire(String name) { this(name, false); } + public StateWire(String name, boolean initiallyFull) { + this.name = name; + this.initiallyFull = initiallyFull; + statewires.put(name, this); + } + public void dump(PrintWriter pw) { + pw.println(" reg "+name+";"); + pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";"); + } + } + + public class Latch implements Assignable, Value { + public final String name; public final int width; + public Latch(String name, int width) { + this.width = width; + this.name = name; + latches.put(name, this); + } + public String getVerilogName() { return name; } + public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + public void dump(PrintWriter pw) { + pw.println(" reg ["+(width-1)+":0] "+name+";"); + //pw.println(" initial "+name+"="+(initiallyFull?"1":"0")+";"); + } + } + + private abstract class Port implements Action, Assignable, Trigger { + public final String name; + public String getName() { return name; } + public final int width; + public int getWidth() { return 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; @@ -65,6 +192,7 @@ public class Generator { if (external) portorder.add(name); } + public String getVerilogName() { return name; } public String getAck() { return name+"_a"; } public String getReq() { return name+"_r"; } public abstract String getInterface(); @@ -86,15 +214,14 @@ public class Generator { public void dump(PrintWriter pw) { pw.println(" " + module.getName() + " " + getName() + "(clk"); for(String s : module.portorder) - pw.println(", " + getPort(s, module.ports.get(s).width).getSimpleInterface()); + pw.println(", " + getPort(s).getSimpleInterface()); pw.println(" );"); } - public Port getPort(String name, int width) { - if (module.ports.get(name) instanceof SinkPort) - return getOutputPort(name, width, ""); - return getInputPort(name, width); + public Port getPort(String name) { + return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name); } - public SinkPort getInputPort(String name, int width) { + public SinkPort getInputPort(String name) { + int width = module.getPort(name).getWidth(); SinkPort port = (SinkPort)ports.get(name); if (port == null) { port = new SinkPort(getName()+"_"+name, width, false, ""); @@ -102,7 +229,8 @@ public class Generator { } return port; } - public SourcePort getOutputPort(String name, int width, String resetBehavior) { + public SourcePort getOutputPort(String name) { + int width = module.getPort(name).getWidth(); SourcePort port = (SourcePort)ports.get(name); if (port == null) { port = new SourcePort(getName()+"_"+name, width, false); @@ -112,10 +240,14 @@ public class Generator { } } - private class SourcePort extends Port { + private class SourcePort extends Port implements Value { private SinkPort driven = null; public SourcePort(String name, int width, boolean external) { super(name, width, external); } + public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); } + public String getVerilogAction() { return getAck() + " <= 1;"; } public String getInterface() { return getReq()+", "+getAck()+"_, "+name+""; } public String getSimpleInterface() { return getReq()+", "+getAck()+", "+name+""; } public String getDeclaration() { @@ -138,9 +270,8 @@ public class Generator { } public String getAssignments() { StringBuffer sb = new StringBuffer(); - if (external && !pretendDriven) { + if (external) sb.append("assign " + name +"_a_ = " + name + "_a;\n"); - } if (driven != null) { sb.append("assign " + driven.name +"_r = " + name + "_r;\n"); sb.append("assign " + name +"_a = " + driven.name + "_a;\n"); @@ -154,6 +285,9 @@ public class Generator { } private class SinkPort extends Port { public final String resetBehavior; + public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + public String getVerilogAction() { return getReq() + " <= 1;"; } + public String getVerilogTrigger() { return " && !" + getReq() + " && !"+getAck(); } public SinkPort(String name, int width, boolean external, String resetBehavior) { super(name, width, external); this.resetBehavior=resetBehavior; } public String getResetBehavior() { return resetBehavior; } @@ -174,20 +308,16 @@ public class Generator { } else { sb.append("reg " + name +"_r;\n"); sb.append("initial " + name +"_r = 0;\n"); - if (!noreg) { - sb.append("reg ["+(width-1)+":0]" + name +";\n"); - sb.append("initial " + name +" = 0;\n"); - } + 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 && !pretendDriven) { + if (external) { sb.append("assign " + name +"_r_ = " + name + "_r;\n"); - if (!noAssignData) { - sb.append("assign " + name +"_ = " + name + ";\n"); - } + sb.append("assign " + name +"_ = " + name + ";\n"); } return sb.toString(); } @@ -207,6 +337,10 @@ public class Generator { Port p = ports.get(name); pw.println(" " + p.getDeclaration()); } + for(StateWire sw : statewires.values()) + sw.dump(pw); + for(Latch l : latches.values()) + l.dump(pw); for(String name : ports.keySet()) { Port p = ports.get(name); pw.println(" " + p.getAssignments()); @@ -219,18 +353,18 @@ public class Generator { for(Port p : ports.values()) { if (p instanceof SourcePort) { SourcePort ip = (SourcePort)p; - if (ip.hasLatch && !ip.supress) + if (ip.hasLatch) pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;"); } else { SinkPort op = (SinkPort)p; - if (op.hasLatch && !op.supress) + if (op.hasLatch) pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+ op.getReq()+"<=0; "+ op.getResetBehavior()+" end"); } } - for(Action a : actions) a.dump(pw); + for(Event a : events) a.dump(pw); pw.println(" begin end"); pw.println("end"); @@ -238,49 +372,26 @@ public class Generator { pw.println("endmodule"); } - private class Action { - private String[] triggers; - private SourcePort[] inports; - private SinkPort[] outports; + private class Event { + private Object[] triggers; private Object[] actions; - public Action(Object[] triggers, String action) { this(triggers, new Object[] { action }); } - public Action(Object[] triggers, Object[] actions) { - int numtriggers = 0; - int numinports = 0; - int numoutports = 0; - Module.this.actions.add(this); + public Event(Object[] triggers, Object action) { this(triggers, new Object[] { action }); } + public Event(Object[] triggers, Object[] actions) { + Module.this.events.add(this); + this.triggers = triggers; + this.actions = actions; for(int i=0; i> 1) "; if (bot_of_addr_field > 0) shifted_packet += ", in["+(bot_of_addr_field-1)+":0] "; shifted_packet += " }"; // same behavior as FLEET -- wait for both - horn.new Action(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" }, - new Object[] { in, out0, "out0 = " + shifted_packet + ";" }); - horn.new Action(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" }, - new Object[] { in, out1, "out1 = " + shifted_packet + ";" }); - + horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" }, + new Action[] { in, out0, new AssignAction(out0, shifted_packet) }); + horn.new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" }, + new Action[] { in, out1, new AssignAction(out1, shifted_packet) }); PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); horn.dump(pw); pw.flush(); } + private static Module mkBox(String name, boolean inbox, String prefix, Module fifo) throws Exception { + Module box = new Module(name); + Module.SourcePort instr = box.createInputPort("instr", INSTRUCTION_WIDTH); + Module.SourcePort fabric_in = box.createInputPort("fabric_in", PACKET_WIDTH); + Module.SinkPort fabric_out = box.createOutputPort("fabric_out", PACKET_WIDTH, ""); + Module.InstantiatedModule dfifo = box.new InstantiatedModule(fifo); + fabric_in.connect(dfifo.getInputPort("in")); + + Module.SourcePort dfifo_out = dfifo.getOutputPort("out"); + Module.SourcePort ship_out = null; + if (!inbox) { + ship_out = box.createInputPort("ship", WORD_WIDTH); + ship_out.hasLatch = true; + } + + Module.SinkPort ship_in = null; + if (inbox) { + ship_in = box.createOutputPort("ship", PACKET_WIDTH, ""); + ship_in.hasLatch = true; + } + + Module.Latch ondeck = box.new Latch("ondeck", INSTRUCTION_WIDTH); + Module.Latch repcount = box.new Latch("repcount", COUNT_WIDTH); + Module.StateWire ondeckFull = box.new StateWire("ondeck_full"); + Module.StateWire newMayProceed = box.new StateWire("newmayproceed", true); + Module.StateWire doRepeat = box.new StateWire("dorepeat", false); + Module.StateWire doRepeatKill = box.new StateWire("dorepeatkill", false); + Module.StateWire doKill = box.new StateWire("dokill", false); + Module.StateWire isClogged = box.new StateWire("clogged", false); + + 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"); + Module.SourcePort ififo_out = ififo.getOutputPort("out"); + + Value instruction_count_ondeck = ondeck .getBits(1+DESTINATION_WIDTH+COUNT_WIDTH-1, 1+DESTINATION_WIDTH); + Value instruction_count_instr = instr .getBits(1+DESTINATION_WIDTH+COUNT_WIDTH-1, 1+DESTINATION_WIDTH); + Assignable instruction_count_ififo_in = ififo_in.getAssignableBits(1+DESTINATION_WIDTH+COUNT_WIDTH-1, 1+DESTINATION_WIDTH); + + // Clog (must be first) + box.new Event( + new Object[] { ififo_out, newMayProceed.isFull(), "`instruction_is_clog("+ififo_out.getName()+")" }, + new Action[] { ififo_out, isClogged.doFill(), newMayProceed.doDrain() } + ); + + // UnClog + box.new Event( + new Object[] { instr, isClogged.isFull(), "`instruction_is_unclog(instr)" }, + new Action[] { instr, isClogged.doDrain(), newMayProceed.doFill() } + ); + + // First Kill + box.new Event( + new Object[] { instr, ififo_out, + "`instruction_is_kill(instr)", + "!`instruction_is_unclog(instr)", + newMayProceed.isFull() }, + new Action[] { instr, ififo_out, + new ConditionalAction("`instruction_count(instr)!=0", new AssignAction(repcount, instruction_count_instr+"-1")), + new ConditionalAction("`instruction_count(instr)!=0", doRepeatKill.doFill()), + new ConditionalAction("`instruction_count(instr)!=0", newMayProceed.doDrain()), + new ConditionalAction("`instruction_count(instr)==0", newMayProceed.doFill()) + }); + + // Kill + box.new Event( + new Object[] { doKill.isFull() }, + new Action[] { doKill.doDrain(), + new ConditionalAction("`instruction_count(instr)!=0", new AssignAction(repcount, instruction_count_instr+"-1")), + new ConditionalAction("`instruction_count(instr)!=0", doRepeatKill.doFill()), + new ConditionalAction("`instruction_count(instr)==0", newMayProceed.doFill()) + }); + + // RepKill + box.new Event( + new Object[] { doRepeatKill.isFull(), ififo_out }, + new Action[] { doRepeatKill.doDrain(), ififo_out, doKill.doFill(), + new AssignAction(instruction_count_ondeck, repcount) } + ); + + // Enqueue + box.new Event( + new Object[] { instr, ififo_in, "!`instruction_is_kill(instr)" }, + new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr) } + ); + + // New + box.new Event( + new Object[] { ififo_out, ondeckFull.isEmpty(), newMayProceed.isFull() }, + new Action[] { ififo_out, ondeckFull.doFill(), newMayProceed.doDrain(), + new AssignAction(ondeck, ififo_out) } + ); + + // RepeatExecute + box.new Event( + new Object[] { doRepeat.isFull() }, + new Action[] { doRepeat.doDrain(), + ondeckFull.doFill(), + new AssignAction(instruction_count_ondeck, repcount) } + ); + + Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")"); + String data_latch_input = inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName(); + box.new Event( + new Object[] { ondeckFull.isFull(), + data_out, + token_out, + ififo_in, + new ConditionalTrigger("`instruction_bit_datain(ondeck)", data_in), + new ConditionalTrigger("`instruction_bit_tokenin(ondeck)", token_in) + }, + new Action[] { new SimpleAction("ondeck_full<=0;"), + new ConditionalAction("`instruction_count(ondeck)==1 || `instruction_bit_recycle(ondeck)", newMayProceed.doFill()), + new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1", + new AssignAction(ififo_in, ondeck)), + new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1 && `instruction_count(ondeck)==0", + new AssignAction(instruction_count_ififo_in, "0")), + new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1 && `instruction_count(ondeck)!=0", + new AssignAction(instruction_count_ififo_in, instruction_count_ondeck+"-1")), + new ConditionalAction("`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1", ififo_in), + new ConditionalAction("!`instruction_bit_recycle(ondeck) && `instruction_count(ondeck)!=1", doRepeat.doFill()), + new ConditionalAction("`instruction_count(ondeck)==0", new AssignAction(repcount, "0")), + new ConditionalAction("`instruction_count(ondeck)!=0", new AssignAction(repcount, instruction_count_ondeck+"-1")), + new ConditionalAction("`instruction_bit_datain(ondeck)", data_in), + new ConditionalAction("`instruction_bit_dataout(ondeck)", data_out), + new ConditionalAction("`instruction_bit_tokenin(ondeck)", token_in), + new ConditionalAction("`instruction_bit_tokenout(ondeck)", token_out), + new ConditionalAction("`instruction_bit_latch(ondeck)", new AssignAction(data_latch, data_latch_input)), + new ConditionalAction("`instruction_bit_tokenout(ondeck)", + new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"), + "`instruction_bit_dest(ondeck)")), + new ConditionalAction("`instruction_bit_dataout(ondeck)", + inbox ? new SimpleAction("") + : new AssignAction(new SimpleAssignable("`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; + } + } diff --git a/src/edu/berkeley/fleet/slipway/Slipway.java b/src/edu/berkeley/fleet/slipway/Slipway.java index cdad214..8f3da87 100644 --- a/src/edu/berkeley/fleet/slipway/Slipway.java +++ b/src/edu/berkeley/fleet/slipway/Slipway.java @@ -43,7 +43,7 @@ public class Slipway extends Fleet { // above is the minimal ship set needed to run the regression suite // below are extra bonush ships - + /* createShip("Alu2", "alu2b"); createShip("Alu2", "alu2c"); createShip("Alu2", "alu2d"); @@ -52,6 +52,7 @@ public class Slipway extends Fleet { createShip("Choice", "Choice"); createShip("Choice", "Choice"); createShip("Choice", "Choice"); + */ dumpFabric(true); }