public interface FabricElement {
- public FpgaPath getPath(FabricElement dest, BitVector signal);
+ public FpgaPath getPath(FpgaDestination dest, BitVector signal);
public void addInput(FabricElement in, Module.Port inPort);
public void addOutput(FabricElement out, Module.Port outPort);
public Module.SourcePort getOutputPort();
public Module.Port getInputPort();
+
+ public static abstract class AbstractFabricElement implements FabricElement {
+ public abstract FpgaPath getPath(FpgaDestination dest, BitVector signal);
+ public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
+ public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); }
+ public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
+ public Module.Port getInputPort() { throw new RuntimeException(); }
+ }
+
}
public FanoutModule(int width) {
super("fanout"+width);
Module.SourcePort in = createInputPort ("in", width);
- Module.SinkPort out0 = createOutputPort("out0", width, "");
- Module.SinkPort out1 = createOutputPort("out1", width, "");
- in.hasLatch = false;
- out0.hasLatch = false;
- out0.forceNoLatch = true;
- out1.hasLatch = false;
- out1.forceNoLatch = true;
+ Module.SinkPort out0 = createOutputPort("out0", width);
+ Module.SinkPort out1 = createOutputPort("out1", width);
- out0.latchDriver = in;
- out1.latchDriver = in;
+ out0.connectValue(in);
+ out1.connectValue(in);
Module.StateWire busy = new StateWire("busy", false);
new Event(new Object[] { in, out0, out1, busy.isEmpty() },
this.len = len;
this.width = width;
Module.SourcePort in = createInputPort("in", width);
- Module.SinkPort out = createOutputPort("out", width, "");
+ Module.SinkPort out = createOutputPort("out", width);
Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len];
if (len==0) {
- in.hasLatch = false;
- out.hasLatch = false;
in.connect(out);
} else if (len==1) {
new Event(new Object[] { in, out },
public void dump(String prefix) throws IOException {
if (len>16) throw new RuntimeException("FifoModule(i>16) not supported due to SRL16 limitation");
- if (len<2) {
- super.dump(prefix);
+
+ if (len>=2) {
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
+ pw.println("`define ADDR_BITS "+dislog(len));
+ pw.println("`define WIDTH " + width);
+ pw.println("`define MODULE_NAME "+name);
+ pw.println("`include \"ramfifo.inc\"");
+ pw.flush();
return;
}
- PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
- pw.println("`define ADDR_BITS "+dislog(len));
- pw.println("`define WIDTH " + width);
- pw.println("`define MODULE_NAME "+name);
- pw.println("`include \"ramfifo.inc\"");
- pw.flush();
+
+ super.dump(prefix);
+ return;
}
}
public class Fpga extends FleetTwoFleet {
public Module top;
- public FabricElement top_horn;
Ship debugShip;
public LinkedHashMap<String,FpgaShip> ships = new LinkedHashMap<String,FpgaShip>();
} catch (Exception e) { throw new RuntimeException(e); }
}
- public BitVector getDestAddr(Path path) {
+ protected BitVector getDestAddr(Path path) {
return ((FpgaPath)path).toBitVector();
}
// Setup //////////////////////////////////////////////////////////////////////////////
- public Ship createShip(String type, String name) throws IOException {
+ Ship createShip(String type) throws IOException {
ShipDescription sd = new ShipDescription(type, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship"))));
+ int count = 0;
+ for(Ship ship : ships.values()) if (ship.getType().equals(type)) count++;
+ String name = type+count;
FpgaShip ship = new FpgaShip(this, sd);
ships.put(name, ship);
return ship;
public Fpga() throws Exception { this(new Module("main")); }
public Fpga(Module top) throws Exception {
this.top = top;
- debugShip = createShip("Debug", "debug");
+ debugShip = createShip("Debug");
- //boolean small = false;
boolean small = true;
-
- createShip("Memory", "memory1");
+ //boolean small = false;
if (small) {
- for(int i=0; i<2; i++)
- createShip("Fifo", "fifo"+i);
- for(int i=0; i<2; i++)
- createShip("Alu", "alu"+i);
- createShip("Counter", "counter");
- createShip("CarrySaveAdder", "csa1");
- createShip("Rotator", "rotator");
- createShip("Lut3", "lut");
+ for(int i=0; i<1; i++) createShip("Memory");
+ for(int i=0; i<2; i++) createShip("Fifo");
+ for(int i=0; i<2; i++) createShip("Alu");
+ createShip("Counter");
+ createShip("CarrySaveAdder");
+ createShip("Rotator");
+ createShip("Lut3");
+ createShip("DDR2");
} else {
- createShip("Memory", "memory2");
- createShip("Memory", "memory3");
-
- for(int i=0; i<3; i++)
- createShip("Alu", "alu"+i);
-
- for(int i=0; i<1; i++)
- createShip("Fifo", "fifo"+i);
-
- for(int i=0; i<14; i++)
- createShip("Counter", "counter"+i);
-
- /*
- createShip("CarrySaveAdder", "csa1");
- createShip("Rotator", "rotator");
- createShip("Lut3", "lut");
- */
- //createShip("DDR2", "ddr2");
+ for(int i=0; i<3; i++) createShip("Memory");
+ for(int i=0; i<3; i++) createShip("Alu");
+ for(int i=0; i<2; i++) createShip("Fifo");
+ for(int i=0; i<14; i++) createShip("Counter");
+
+ // "really big" configuration: 138 docks
+ for(int i=0; i<10; i++) createShip("Alu");
+ createShip("CarrySaveAdder");
+ createShip("Rotator");
+ createShip("Lut3");
+
+ //createShip("DRAM");
+ //createShip("Video");
}
- createShip("DRAM", "dram");
- createShip("Video", "video");
// for FifoShip
new Module.InstantiatedModule(top, new FifoModule(8, WIDTH_WORD));
- Module.Latch temp_in = top.new Latch("temp", WIDTH_PACKET);
- Module.Latch count = top.new Latch("count", 8);
-
- ArrayList inbox_sources = new ArrayList<FabricElement>();
- ArrayList inbox_dests = new ArrayList<FabricElement>();
- ArrayList outbox_sources = new ArrayList<FabricElement>();
- ArrayList outbox_dests = new ArrayList<FabricElement>();
- ArrayList instruction_dests = new ArrayList<FabricElement>();
- int numdocks = 0;
+ ArrayList dests = new ArrayList<FabricElement>();
+ ArrayList sources = new ArrayList<FabricElement>();
for(FpgaShip ship : (Iterable<FpgaShip>)(Object)this) {
for(Dock port : ship) {
if (port.isInputDock()) {
- inbox_sources.add(((FpgaDock)port));
- instruction_dests.add(port.getInstructionDestination());
- inbox_dests.add(port.getDataDestination());
+ sources.add(((FpgaDock)port));
+ dests.add(port.getInstructionDestination());
+ dests.add(port.getDataDestination());
} else {
- outbox_sources.add(((FpgaDock)port));
- instruction_dests.add(port.getInstructionDestination());
- outbox_dests.add(port.getDataDestination());
+ sources.add(((FpgaDock)port));
+ dests.add(port.getInstructionDestination());
+ dests.add(port.getDataDestination());
}
- numdocks++;
+ }
+ for(Module.SourcePort sp0 : ship.docklessPorts.values()) {
+ final Module.SourcePort sp = sp0;
+ sources.add(new FabricElement.AbstractFabricElement() {
+ private FabricElement upstream;
+ public FpgaPath getPath(FpgaDestination dest, BitVector signal) { return upstream.getPath(dest, signal); }
+ public void addOutput(FabricElement out, Module.Port outPort) {
+ this.upstream = out;
+ sp.connect((Module.SinkPort)outPort);
+ }
+ });
}
}
- ArrayList dests = new ArrayList<FabricElement>();
- ArrayList sources = new ArrayList<FabricElement>();
- sources.addAll(inbox_sources);
- sources.addAll(outbox_sources);
- dests.addAll(inbox_dests);
- dests.addAll(instruction_dests);
- dests.addAll(outbox_dests);
- top_horn = mkNode((FabricElement[])dests.toArray(new FabricElement[0]), true);
- FabricElement source = mkNode((FabricElement[])sources.toArray(new FabricElement[0]), false);
- FunnelModule.FunnelInstance top_funnel = new FunnelModule.FunnelInstance(this, top, null, source.getOutputPort());
- ((FunnelModule.FunnelInstance)source).out = top_funnel;
- top_funnel.addOutput(top_horn, top_horn.getInputPort());
- Module.SinkPort debug_in = top_funnel.getInputPort("in1");
-
- top.addPreCrap("reg root_in_a_;");
- top.addPreCrap("assign root_in_a = root_in_a_;");
- top.new Event(new Object[] { "(root_in_r && root_in_a)" },
- new Object[] { new SimpleAction("root_in_a_<=0;") });
- top.new Event(new Object[] { "(root_in_r && !root_in_a)", "count<=7" },
- new Object[] { new SimpleAction(temp_in.getVerilogName()+" <= {" + temp_in.getVerilogName() + "["+(WIDTH_PACKET-(1+8))+":0], root_in_d[7:0] };"),
- new AssignAction(count, count.getVerilogName()+"+1"),
- new SimpleAction("root_in_a_<=1;")
- });
- top.new Event(new Object[] { debug_in, "count>7" },
- new Object[] { new AssignAction(count, "0"),
- new AssignAction(debug_in, temp_in),
- debug_in
- });
+ FabricElement top_horn = mkNode((FabricElement[])dests.toArray(new FabricElement[0]), true);
+ mkNode((FabricElement[])sources.toArray(new FabricElement[0]), false)
+ .addOutput(top_horn, top_horn.getInputPort());
}
public FabricElement mkNode(FabricElement[] ports, boolean is_horn) { return mkNode(ports, is_horn, 0, ports.length); }
public FabricElement mkNode(FabricElement[] ports, boolean is_horn, int start, int end) {
switch(end-start) {
- case 0: return null;
+ case 0: throw new RuntimeException("this should never happen");
case 1: return ports[start];
default: {
FabricElement leftPort = mkNode(ports, is_horn, start, (end+start)/2);
pw.println("`define CODEBAG_SIZE_BITS "+CBD_SIZE.valmaskwidth);
pw.println();
- for(DockDescription dd : sd) {
+ for(DockDescription dd : sd.ports()) {
String name = dd.getName();
pw.println("`define "+name+"_full ("+name+"_r && !"+name+"_a)");
pw.println("`define "+name+"_empty (!"+name+"_r && !"+name+"_a)");
pw.println("`define drain_"+name+" "+name+"_a <= 1;");
} else {
pw.println("`define fill_"+name+" "+name+"_r <= 1;");
- pw.println("`define "+name+"_draining ("+name+"_r && "+name+"_a)");
}
}
pw.print("`define reset ");
- for(DockDescription bb : sd) {
+ for(DockDescription bb : sd.ports()) {
String bb_name = bb.getName();
if (bb.isInputDock()) pw.print(bb_name+"_a <= 1; "+bb_name+"_f <= 0; ");
else pw.print(bb_name+"_r <= 0; ");
pw.println();
pw.print("`define cleanup ");
- for(DockDescription bb : sd) {
+ for(DockDescription bb : sd.ports()) {
String bb_name = bb.getName();
if (bb.isInputDock()) pw.print("if (!"+bb_name+"_r && "+bb_name+"_a) "+bb_name+"_a <= 0; ");
else pw.print("if ( "+bb_name+"_r && "+bb_name+"_a) "+bb_name+"_r <= 0; ");
// FIXME: this corresponds to something
/*
pw.print("`define flush_happening (1");
- for(DockDescription bb : sd)
+ for(DockDescription bb : sd.ports())
if (bb.isInputDock())
pw.print(" && "+bb.getName()+"_r_ && !"+bb.getName()+"_a && "+bb.getName()+"_d["+WIDTH_WORD+"]");
pw.println(")");
*/
pw.print("`define flush ");
- for(DockDescription bb : sd)
+ for(DockDescription bb : sd.ports())
if (bb.isInputDock())
pw.print(" if (!"+bb.getName()+"_r_) "+bb.getName()+"_f <= 0; ");
pw.print("if (1");
- for(DockDescription bb : sd)
+ for(DockDescription bb : sd.ports())
if (bb.isInputDock())
pw.print(" && "+bb.getName()+"_r_ && !"+bb.getName()+"_a");
pw.print(") begin ");
if (true) {
pw.print("if (1");
- for(DockDescription bb : sd)
+ for(DockDescription bb : sd.ports())
if (bb.isInputDock())
pw.print(" && "+bb.getName()+"_d["+WIDTH_WORD+"] ");
pw.print(") begin ");
if (true) {
- for(DockDescription bb : sd)
+ for(DockDescription bb : sd.ports())
if (bb.isInputDock())
pw.print(bb.getName()+"_f <= 1; ");
}
pw.print(" end else if (0");
- for(DockDescription bb : sd)
+ for(DockDescription bb : sd.ports())
if (bb.isInputDock())
pw.print(" || "+bb.getName()+"_d["+WIDTH_WORD+"] ");
pw.print(") begin ");
if (true) {
- for(DockDescription bb : sd)
+ for(DockDescription bb : sd.ports())
if (bb.isInputDock())
pw.print(" if (!"+bb.getName()+"_d["+WIDTH_WORD+"]) "+bb.getName()+"_f <= 1; ");
}
pw.println();
pw.println("module " + filename + "( clk, rst ");
- for(DockDescription bb : sd) {
+ for(DockDescription bb : sd.ports()) {
String bb_name = bb.getName();
pw.print(" ");
if (bb.isInputDock()) {
pw.println(";");
}
- for(DockDescription bb : sd) {
+ for(DockDescription bb : sd.ports()) {
String bb_name = bb.getName();
+ int width = bb.isDockless() ? WIDTH_PACKET : WIDTH_WORD;
if (bb.isInputDock()) {
- pw.println(" input ["+WIDTH_WORD+":0] "+bb_name+"_d;");
+ pw.println(" input ["+width+":0] "+bb_name+"_d;");
pw.println(" input "+bb_name+"_r_;");
pw.println(" wire "+bb_name+"_r;");
- pw.println(" assign "+bb_name+"_r = "+bb_name+"_r_ & ~"+bb_name+"_d["+WIDTH_WORD+"];");
+ pw.println(" assign "+bb_name+"_r = "+bb_name+"_r_ & ~"+bb_name+"_d["+width+"];");
pw.println(" output "+bb_name+"_a_;");
pw.println(" reg "+bb_name+"_a;");
pw.println(" initial "+bb_name+"_a = 0;");
pw.println(" initial "+bb_name+"_f = 0;");
pw.println(" assign "+bb_name+"_a_ = "+bb_name+"_a || "+bb_name+"_f;");
} else {
- pw.println(" output ["+WIDTH_WORD+":0] "+bb_name+"_d_;");
+ pw.println(" output ["+width+":0] "+bb_name+"_d_;");
pw.println(" input "+bb_name+"_a;");
pw.println(" output "+bb_name+"_r_;");
pw.println(" reg "+bb_name+"_r;");
public Module.Port getInputPort() { throw new RuntimeException(); }
public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); }
- public long getAddr() {
- return ((Fpga)dock.getShip().getFleet()).top_horn.getPath(this,null).toLong();
- }
- public FpgaPath getPath(FabricElement dest, BitVector signal) {
+ public FpgaPath getPath(FpgaDestination dest, BitVector signal) {
if (dest==this) return FpgaPath.emptyPath(this, signal);
return null;
}
public void addInput(FabricElement in, Module.Port inPort) {
- inPort.connect((Module.SinkPort)port);
+ ((Module.SourcePort)inPort).connect((Module.SinkPort)port);
}
public String toString() {
return dock.toString();
import edu.berkeley.fleet.two.*;
import java.util.*;
-/** the pump itself is a */
public class FpgaDock extends FleetTwoDock implements FabricElement {
private static final int INSTRUCTION_FIFO_SIZE = 12;
private FabricElement upstream;
public Module.SourcePort getOutputPort() { throw new RuntimeException(); }
public Module.Port getInputPort() { throw new RuntimeException(); }
- public FpgaPath getPath(FabricElement dest, BitVector signal) { return upstream.getPath((FabricElement)dest, signal); }
- public FpgaPath getPath(Destination dest,BitVector signal) { return upstream.getPath((FabricElement)dest, signal); }
+ public Path getPath(Destination dest,BitVector signal) { return getPath((FpgaDestination)dest, signal); }
+ public FpgaPath getPath(FpgaDestination dest,BitVector signal) { return upstream.getPath(dest, signal); }
public void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); }
public void addOutput(FabricElement out, Module.Port outPort) {
this.upstream = out;
public TorpedoBranchModule() {
super("torpedobranch");
Module.SourcePort in = createInputPort ("in", fpga.WIDTH_PACKET);
- Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, "");
- Module.SinkPort torpedo = createOutputPort("torpedo", 0, "");
+ Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
+ Module.SinkPort torpedo = createOutputPort("torpedo", 0);
Module.StateWire busy = new StateWire("busy", false);
- out.forceNoLatch = true;
new Event(new Object[] { in, busy.isFull(), out },
new Action[] { in, busy.doDrain() });
- new Event(new Object[] { in, busy.isEmpty(), out, torpedo, in.getBits(fpga.PACKET_TOKEN) },
+ new Event(new Object[] { in, busy.isEmpty(), out, torpedo, in.testMask(fpga.PACKET_IS_TOKEN) },
new Action[] { in, torpedo });
- new Event(new Object[] { in, busy.isEmpty(), out, in.getBits(fpga.PACKET_TOKEN).invertBits() },
+ new Event(new Object[] { in, busy.isEmpty(), out, in.testMask(fpga.PACKET_IS_TOKEN).invert() },
new Action[] { busy.doFill(), out });
- out.latchDriver = in.getBits(fpga.PACKET_DATA);
+ out.connectValue(in.getBits(fpga.PACKET_DATA));
}
}
Module.SourcePort fabric_in = createInputPort ("fabric_in", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
Module.SourcePort ondeck_in = createInputPort ("ondeck_in", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
Module.SourcePort flag_z = createInputPort ("flag_z", 1);
- Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth, "");
- out.forceNoLatch = true;
+ Module.SinkPort out = createOutputPort("out", fpga.getWordWidth()-fpga.DISPATCH_PATH.valmaskwidth);
Module.StateWire using = new StateWire("using", false);
Module.StateWire circulating = new StateWire("circulating", false);
Module.StateWire doResetFabric = new StateWire("doResetFabric", false);
Module.StateWire doResetOndeck = new StateWire("doResetOndeck", false);
- addPreCrap("assign out = "+circulating.isEmpty()+" ? "+fabric_in.getName()+" : "+ondeck_in.getName()+";");
+ out.connectValue(new MuxValue(circulating.isEmpty(), fabric_in, ondeck_in));
// always: discard one-shot instructions
new Event(new Object[] { ondeck_in, fpga.OS.verilog(ondeck_in.getName()) },
Module.SourcePort fabric_in = createInputPort("fabric_in", fpga.WIDTH_PACKET);
// FIXME: at inboxes, no need for a full set of latches
- Module.SinkPort fabric_out = createOutputPort("fabric_out", fpga.WIDTH_PACKET, "");
+ Module.SinkPort fabric_out = createOutputPort("fabric_out", fpga.WIDTH_PACKET);
Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, dfifo_m);
- fabric_in.hasLatch = false;
fabric_in.connect(dfifo.getInputPort("in"));
- dfifo.getInputPort("in").noDriveLatches = true;
- if (inbox)
- addPreCrap("assign "+dfifo.getInputPort("in").getName()+
- " = { "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+
- ", "+fpga.PACKET_DATA.verilogVal("fabric_in")+" };\n");
- else
- addPreCrap("assign "+dfifo.getInputPort("in").getName()+
- " = "+fpga.PACKET_SIGNAL.verilogVal("fabric_in")+";\n");
-
+ dfifo.getInputPort("in").connectValue(
+ !inbox
+ ? fabric_in.getBits(fpga.PACKET_SIGNAL)
+ : new CatValue(new Value[] {
+ fabric_in.getBits(fpga.PACKET_SIGNAL),
+ fabric_in.getBits(fpga.PACKET_DATA)
+ }));
- Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
- Module.SourcePort ship_out = null;
- if (!inbox) {
- ship_out = createInputPort("ship", fpga.getWordWidth()+1);
- ship_out.hasLatch = true;
- }
-
- Module.SinkPort ship_in = null;
- if (inbox) {
- ship_in = createOutputPort("ship", fpga.getWordWidth()+1, "");
- ship_in.hasLatch = true;
- }
+ Module.SourcePort dfifo_out = dfifo.getOutputPort("out");
+ Module.SourcePort ship_out = !inbox ? createInputPort("ship", fpga.getWordWidth()+1) : null;
+ Module.SinkPort ship_in = inbox ? createOutputPort("ship", fpga.getWordWidth()+1) : null;
Module.Latch ilc = new Latch("ilc", fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1);
Module.Latch olc = new Latch("olc", fpga.SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1);
Module.SinkPort ififo_in = ififo.getInputPort("in");
Module.SourcePort ififo_out = ififo.getOutputPort("out");
- Module.SinkPort data_latch_output_p = createWirePort("data_latch_output", inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth());
-
Module.InstantiatedModule torpedo_branch = new Module.InstantiatedModule(this, new TorpedoBranchModule());
instruction.connect(torpedo_branch.getInputPort("in"));
Module.SourcePort efifo_out = torpedo_branch.getOutputPort("out");
fanout_module_out0.connect(requeue_ondeck);
Module.SourcePort ondeck = fanout_module_out1;
- addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : fpga.PACKET_DATA.verilogVal(data_out.getName()))+";");
- addPreCrap("wire ["+(Math.max(ilc.width,olc.width)-1)+":0] decremented;");
- addPreCrap("assign decremented = ("+fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName())+" ? {1'b0, olc} : ilc)-1;");
- addPreCrap("assign "+requeue_flag_z.getName()+" = (olc==0);");
+ WireValue decremented = new WireValue("decremented", Math.max(ilc.width,olc.width),
+ new SimpleValue("("+ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE).getVerilogTrigger()+
+ " ? {1'b0, olc} : ilc)-1"));
+ WireValue data_latch_output_p = new WireValue("data_latch_output",
+ inbox ? fpga.getWordWidth()+1 : fpga.getWordWidth(),
+ (inbox
+ ? new SimpleValue(data_out.getName())
+ : new SimpleValue(data_out.getBits(fpga.PACKET_DATA).getVerilog()))
+ );
+ requeue_flag_z.connectValue(new SimpleValue("(olc==0)"));
- Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : fpga.PACKET_DATA.verilogVal(data_out.getName()));
- String data_latch_input = inbox ? data_in.getName() : data_in.getName();
+ Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : data_out.getBits(fpga.PACKET_DATA).getVerilog());
+ Module.SourcePort data_latch_input = inbox ? data_in : data_in;
- String magic_standing_value = "(1<<"+fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+")";
- String done_executing = "((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")";
+ BitVector bv = new BitVector(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth+1);
+ bv.set(fpga.SET_ILC_FROM_IMMEDIATE.valmaskwidth, true);
+ Value magic_standing_value = new ConstantValue(bv);
+
+ Trigger done_executing = new SimpleTrigger("((ilc==0) || (ilc==1) || !"+fpga.MOVE.verilog(ondeck.getName())+")");
String predicate_met =
"("+
new Object[] {
ondeck,
torpedo_branch_torpedo,
- new AssignAction(olc, "0"),
- new AssignAction(flag_z, "1"),
- new AssignAction(ilc, "1")
+ new AssignAction(olc, new ConstantValue(new BitVector(olc.width).set(0))),
+ new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0))),
+ new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))
});
// Predicate not met
new Event(new Object[] { ondeck, "!("+predicate_met+")" },
new Action[] { ondeck,
- new ConditionalAction(fpga.MOVE.verilog(ondeck.getName()), new AssignAction(ilc, "1"))
+ new ConditionalAction(ondeck.testMask(fpga.MOVE),
+ new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1))))
});
new Event(new Object[] { ondeck,
token_out,
predicate_met,
"(!"+fpga.MOVE.verilog(ondeck.getName())+" || "+fpga.NOT_INTERRUPTIBLE.verilog(ondeck.getName())+" || !"+torpedo_branch_torpedo.isFull()+")",
- new ConditionalTrigger(fpga.DI.verilog(ondeck.getName()), data_in),
- new ConditionalTrigger(fpga.TI.verilog(ondeck.getName()), token_in)
+ new ConditionalTrigger(ondeck.testMask(fpga.DI), data_in),
+ new ConditionalTrigger(ondeck.testMask(fpga.TI), token_in)
},
new Action[] {
- new ConditionalAction(done_executing+" && "+fpga.MOVE.verilog(ondeck.getName()), new AssignAction(ilc, "1")),
+ new ConditionalAction(new AndTrigger(done_executing, ondeck.testMask(fpga.MOVE)),
+ new AssignAction(ilc, new ConstantValue(new BitVector(ilc.width).set(1)))),
new ConditionalAction(done_executing, ondeck),
- new ConditionalAction("!"+done_executing,
- new AssignAction(ilc,
- "ilc=="+magic_standing_value+"?"+magic_standing_value+":decremented")),
-
- new ConditionalAction(fpga.SET_OLC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(olc, "data_latch_output")),
- new ConditionalAction(fpga.SET_OLC_FROM_IMMEDIATE.verilog(ondeck.getName()),
- new AssignAction(olc, fpga.SET_OLC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))),
- new ConditionalAction(fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName()),
- new AssignAction(olc, "olc==0 ? 0 : decremented")),
-
- new ConditionalAction(fpga.SET_OLC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(flag_z, "0")),
- new ConditionalAction(fpga.SET_OLC_FROM_IMMEDIATE.verilog(ondeck.getName()), new AssignAction(flag_z, "0")),
- new ConditionalAction(fpga.SET_OLC_FROM_OLC_MINUS_ONE.verilog(ondeck.getName()), new AssignAction(flag_z, "(olc==0 || olc==1)")),
-
- new ConditionalAction(fpga.SET_ILC_FROM_DATA_LATCH.verilog(ondeck.getName()), new AssignAction(ilc, "data_latch_output")),
- new ConditionalAction(fpga.SET_ILC_FROM_IMMEDIATE.verilog(ondeck.getName()),
- new AssignAction(ilc, fpga.SET_ILC_FROM_IMMEDIATE.verilogVal(ondeck.getName()))),
- new ConditionalAction(fpga.SET_ILC_FROM_INFINITY.verilog(ondeck.getName()), new AssignAction(ilc, magic_standing_value)),
- new ConditionalAction(fpga.SHIFT.verilog(ondeck.getName()),
+ new ConditionalAction(done_executing.invert(),
+ new AssignAction(ilc, new MuxValue(new TestValue(ilc, TestValue.TestType.EQ, magic_standing_value),
+ magic_standing_value,
+ decremented))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
+ new AssignAction(olc, new SimpleValue("data_latch_output"))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
+ new AssignAction(olc, ondeck.getBits(fpga.SET_OLC_FROM_IMMEDIATE))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
+ new AssignAction(olc, new SimpleValue("olc==0 ? 0 : decremented"))),
+
+ new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_DATA_LATCH),
+ new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_IMMEDIATE),
+ new AssignAction(flag_z, new ConstantValue(new BitVector(1).set(0)))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_OLC_FROM_OLC_MINUS_ONE),
+ new AssignAction(flag_z, new SimpleValue("(olc==0 || olc==1)"))),
+
+ new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_DATA_LATCH),
+ new AssignAction(ilc, new SimpleValue("data_latch_output"))),
+
+ new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_IMMEDIATE),
+ new AssignAction(ilc, ondeck.getBits(fpga.SET_ILC_FROM_IMMEDIATE))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_ILC_FROM_INFINITY),
+ new AssignAction(ilc, magic_standing_value)),
+ new ConditionalAction(ondeck.testMask(fpga.SHIFT),
new AssignAction(data_latch,
- "{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+
- fpga.SHIFT.verilogVal(ondeck.getName())+"}")),
- new ConditionalAction(fpga.SET_IMMEDIATE.verilog(ondeck.getName()),
+ new SimpleValue("{ data_latch_output["+(fpga.getWordWidth()-1-fpga.SHIFT.valmaskwidth)+":0], "+
+ ondeck.getBits(fpga.SHIFT).getVerilog()+"}"))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_IMMEDIATE),
new AssignAction(data_latch,
- "{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+
- "{"+fpga.SET_IMMEDIATE_EXTEND.verilogVal(ondeck.getName())+"}}, "+
- fpga.SET_IMMEDIATE.verilogVal(ondeck.getName())+" }")),
- new ConditionalAction(fpga.SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_a, new_flag(fpga.SET_FLAGS_A.verilogVal(ondeck.getName())))),
- new ConditionalAction(fpga.SET_FLAGS.verilog(ondeck.getName()), new AssignAction(flag_b, new_flag(fpga.SET_FLAGS_B.verilogVal(ondeck.getName())))),
+ new SimpleValue("{ {"+(fpga.getWordWidth()-fpga.DataLatch_WIDTH)+
+ "{"+ondeck.getBits(fpga.SET_IMMEDIATE_EXTEND).getVerilog()+"}}, "+
+ ondeck.getBits(fpga.SET_IMMEDIATE).getVerilog()+" }"))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
+ new AssignAction(flag_a, new_flag(ondeck.getBits(fpga.SET_FLAGS_A),flag_a,flag_b,flag_c))),
+ new ConditionalAction(ondeck.testMask(fpga.SET_FLAGS),
+ new AssignAction(flag_b, new_flag(ondeck.getBits(fpga.SET_FLAGS_B),flag_a,flag_b,flag_c))),
new ConditionalAction(inbox
- ? "("+fpga.DI.verilog(ondeck.getName())+" || "+fpga.TI.verilog(ondeck.getName())+")"
- : "(!"+fpga.DI.verilog(ondeck.getName())+" && "+fpga.TI.verilog(ondeck.getName())+")",
+ ? new OrTrigger(ondeck.testMask(fpga.DI), ondeck.testMask(fpga.TI))
+ : new AndTrigger(ondeck.testMask(fpga.DI).invert(), ondeck.testMask(fpga.TI)),
new AssignAction(flag_c, dfifo_out.getBits(dfifo_width-1, dfifo_width-1))),
- new ConditionalAction(fpga.DI.verilog(ondeck.getName()), data_in),
- new ConditionalAction(fpga.DO.verilog(ondeck.getName()), data_out),
- new ConditionalAction(fpga.FLUSH.verilog(ondeck.getName()), data_out),
+ new ConditionalAction(ondeck.testMask(fpga.DI), data_in),
+ new ConditionalAction(ondeck.testMask(fpga.DO), data_out),
+ new ConditionalAction(ondeck.testMask(fpga.FLUSH), data_out),
inbox
- ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"), fpga.FLUSH.verilog(ondeck.getName())+"?1:0")
- : new ConditionalAction(fpga.DI.verilog(ondeck.getName()), new AssignAction(flag_c, data_latch_input+"["+fpga.getWordWidth()+"]")),
- new ConditionalAction(fpga.TI.verilog(ondeck.getName()), token_in),
- new ConditionalAction(fpga.TO.verilog(ondeck.getName()), token_out),
- new ConditionalAction(fpga.DC.verilog(ondeck.getName()), new AssignAction(data_latch, data_latch_input)),
- new AssignAction(new SimpleAssignable(fpga.PACKET_TOKEN.verilogVal(token_out.getName())), "("+fpga.TO.verilog(ondeck.getName())+")?1:0"),
- new ConditionalAction(fpga.PATH_DATA.verilog(ondeck.getName()),
- new AssignAction(new SimpleAssignable("{ "+fpga.PACKET_SIGNAL.verilogVal(token_out.getName())+", "+
- fpga.PACKET_DEST.verilogVal(token_out.getName())+" }"),
- fpga.DISPATCH_PATH.verilogVal(data_latch_input))),
- new ConditionalAction(fpga.PATH_IMMEDIATE.verilog(ondeck.getName()),
- new AssignAction(new SimpleAssignable("{ "+fpga.PACKET_SIGNAL.verilogVal(token_out.getName())+", "+
- fpga.PACKET_DEST.verilogVal(token_out.getName())+" }"),
- fpga.PATH_IMMEDIATE.verilogVal(ondeck.getName()))),
+ ? new AssignAction(new SimpleAssignable(data_out.getName()+"["+fpga.getWordWidth()+"]"), new SimpleValue(fpga.FLUSH.verilog(ondeck.getName())+"?1:0"))
+ : new ConditionalAction(ondeck.testMask(fpga.DI), new AssignAction(flag_c, new SimpleValue(data_latch_input.getVerilog()+"["+fpga.getWordWidth()+"]"))),
+ new ConditionalAction(ondeck.testMask(fpga.TI), token_in),
+ new ConditionalAction(ondeck.testMask(fpga.TO), token_out),
+ new ConditionalAction(ondeck.testMask(fpga.DC), new AssignAction(data_latch, data_latch_input)),
+ new AssignAction(token_out.getBits(fpga.PACKET_TOKEN),
+ new SimpleValue("("+fpga.TO.verilog(ondeck.getName())+")?1:0")),
+ new ConditionalAction(ondeck.testMask(fpga.PATH_DATA),
+ new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
+ token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
+ data_latch_input.getBits(fpga.DISPATCH_PATH))),
+ new ConditionalAction(ondeck.testMask(fpga.PATH_IMMEDIATE),
+ new AssignAction(new SimpleAssignable("{ "+token_out.getBits(fpga.PACKET_SIGNAL).getVerilog()+", "+
+ token_out.getBits(fpga.PACKET_DEST).getVerilog()+" }"),
+ ondeck.getBits(fpga.PATH_IMMEDIATE)))
}
- );
+ );
}
- private String new_flag(String x) {
- return "("+
- "( (("+x+" >> 0) & 1) & !flag_c) |" +
- "( (("+x+" >> 1) & 1) & flag_c) |" +
- "( (("+x+" >> 2) & 1) & !flag_b) |" +
- "( (("+x+" >> 3) & 1) & flag_b) |" +
- "( (("+x+" >> 4) & 1) & !flag_a) |" +
- "( (("+x+" >> 5) & 1) & flag_a) | 0" +
- ")";
+ private Value new_flag(Value v, Value flag_a, Value flag_b, Value flag_c) {
+ Value[] vals = new Value[] {
+ new LogicValue(v.getBits(0,0), LogicValue.LogicType.AND, flag_c.invertBits()),
+ new LogicValue(v.getBits(1,1), LogicValue.LogicType.AND, flag_c),
+ new LogicValue(v.getBits(2,2), LogicValue.LogicType.AND, flag_b.invertBits()),
+ new LogicValue(v.getBits(3,3), LogicValue.LogicType.AND, flag_b),
+ new LogicValue(v.getBits(4,4), LogicValue.LogicType.AND, flag_a.invertBits()),
+ new LogicValue(v.getBits(5,5), LogicValue.LogicType.AND, flag_a),
+ };
+ Value ret = new ConstantValue(new BitVector(1).set(0));
+ for(int i=0; i<vals.length; i++)
+ ret = new LogicValue(ret, LogicValue.LogicType.OR, vals[i]);
+ return ret;
}
}
}
private Module module;
private Module.InstantiatedModule instance;
private LinkedHashMap<String,FpgaDock> ports = new LinkedHashMap<String,FpgaDock>();
+ LinkedHashMap<String,Module.SourcePort> docklessPorts = new LinkedHashMap<String,Module.SourcePort>();
/** You should instantiate a bunch of Inboxes and Outboxes in your constructor */
public FpgaShip(Fpga fleet, ShipDescription sd) {
super(fleet, sd);
this.module = new Module(getType().toLowerCase());
this.instance = new Module.InstantiatedModule(fleet.getVerilogModule(), module);
- for(DockDescription sdbb : sd) {
- if (sdbb.isInputDock()) module.createInputPort(sdbb.getName(), getFleet().getWordWidth()+1);
- else module.createOutputPort(sdbb.getName(), getFleet().getWordWidth()+1, "");
- ports.put(sdbb.getName(), new FpgaDock(this, sdbb));
+ for(DockDescription sdbb : sd.ports()) {
+ if (sdbb.isDockless()) {
+ module.createOutputPort(sdbb.getName(), fleet.WIDTH_PACKET);
+ docklessPorts.put(sdbb.getName(), instance.getOutputPort(sdbb.getName()));
+ } else {
+ if (sdbb.isInputDock()) module.createInputPort(sdbb.getName(), getFleet().getWordWidth()+1);
+ else module.createOutputPort(sdbb.getName(), getFleet().getWordWidth()+1);
+ ports.put(sdbb.getName(), new FpgaDock(this, sdbb));
+ }
}
for(PercolatedPort pp : sd.percolatedPorts)
this.module.percolatedPorts.add(pp);
public FunnelModule(Fpga fpga) {
super("funnel");
- Module.SinkPort outp = createOutputPort("out", fpga.WIDTH_PACKET, "");
+ Module.SinkPort outp = createOutputPort("out", fpga.WIDTH_PACKET);
Module.SourcePort in1p = createInputPort("in1", fpga.WIDTH_PACKET);
Module.SourcePort in2p = createInputPort("in2", fpga.WIDTH_PACKET);
public void addInput(FabricElement in, Module.Port source) {
throw new RuntimeException("cannot add inputs to a funnel once constructed");
}
- public FpgaPath getPath(FabricElement dest, BitVector signal) {
+ public FpgaPath getPath(FpgaDestination dest, BitVector signal) {
return out.getPath(dest, signal);
}
}
int bot) {
super("horn");
Module.SourcePort in = createInputPort("in", top+1);
- Module.SinkPort out0 = createOutputPort("out0", top+1, "");
- Module.SinkPort out1 = createOutputPort("out1", top+1, "");
+ Module.SinkPort out0 = createOutputPort("out0", top+1);
+ Module.SinkPort out1 = createOutputPort("out1", top+1);
Module.Latch out = new Module.Latch("out", top+1);
- out.connect(out0);
- out.connect(out1);
+ out0.connectValue(out);
+ out1.connectValue(out);
Value shifted_packet =
new CatValue(new Value[] {
(top_of_addr_field < top) ? in.getBits(top, top_of_addr_field+1) : null,
//in.getBits(bot_of_addr_field, bot_of_addr_field),
// we drop address bits instead of rotating to help synthesis eliminate unused junk
- new SimpleValue("1'b0"),
+ new ConstantValue(new BitVector(1).set(0)),
in.getBits(top_of_addr_field, bot_of_addr_field+1),
(bot_of_addr_field > 0) ? in.getBits(bot_of_addr_field-1, 0) : null,
});
public static class HornInstance extends Module.InstantiatedModule implements FabricElement {
private FabricElement out0;
private FabricElement out1;
- public void addInput(FabricElement in, Module.Port source) { source.connect(getInputPort("in")); }
+ public void addInput(FabricElement in, Module.Port source) { ((Module.SourcePort)source).connect(getInputPort("in")); }
public Module.SourcePort getOutputPort() { throw new RuntimeException("horn has multiple outputs"); }
public Module.Port getInputPort() { return getInputPort("in"); }
public HornInstance(Fpga fpga, Module thisModule, FabricElement out0, FabricElement out1) {
out1.addInput(this, getOutputPort("out1"));
}
public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); }
- public FpgaPath getPath(FabricElement dest, BitVector signal) {
+ public FpgaPath getPath(FpgaDestination dest, BitVector signal) {
FpgaPath path0 = out0==null ? null : out0.getPath(dest, signal);
FpgaPath path1 = out1==null ? null : out1.getPath(dest, signal);
if (path0 != null) path0 = path0.prepend(false);
import static edu.berkeley.fleet.two.FleetTwoFleet.*;
/*
-=> get rid of getInputPort(String) and instead use members
-=> get rid of addcrap
-=> automatic width-setting/checking on ports
+
+- ideally: want to merge Fpga.dump() with this... but have to resolve
+ the handling of flushing first.
+
+- eliminate uses of SimpleXXX
+ - force width parameter in remaining uses
+ - re-enable width checking (add zero-extend and sign-extend)
+
+- ideally: make getVerilog() package-private somehow
+
+- change Event constructors from Object[] to Event[]/Action[]
+- change portorder to LinkedHashMap
+
=> mangle the names given for strings
+=> ensure uniquification of percolated ports
+
+=> later: scan chain
*/
+/**
+ * Among the benefits are:
+ * - automatic scan-chain insertion
+ * - better error-checking (for example, width mismatches) than Verilog provides
+ * - pin percolation
+ *
+ * One of the most annoying things about Verilog is that you cannot
+ * "double-slice" a value; in other words, foo[10:2] is valid
+ * Verilog, but foo[10:2][4:3] is not; the programmer must write
+ * foo[4+2:3+2]. This lack of compositionality is the reason for
+ * most of the complexity in the Value class.
+ */
public class Verilog {
- public static class PercolatedPort {
- public static enum PortType { UP, DOWN, INOUT };
- public final String name;
- public final int width;
- public final PortType type;
- public PercolatedPort(String name, int width, PortType type) {
- this.name = name;
- this.width = width;
- this.type = type;
- }
+ public static interface Value {
+ public String getVerilog();
+ public Value getBits(int high, int low);
+ public Value getBits(Mask mask);
+ public Trigger testMask(Mask mask);
+ public Value invertBits();
+ public int getWidth();
}
public static class SimpleValue implements Value {
public 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); }
+ private final String s0;
+ private final int high;
+ private final int low;
+ private final int width;
+ public SimpleValue(String s) { this(s, -1); }
+ public SimpleValue(String s, int width) {
+ this.s = s;
+ this.s0 = s;
+ this.high = -1;
+ this.low = -1;
+ this.width = width;
+ }
+ public SimpleValue(String s, int high, int low) {
+ this.s = s+"["+high+":"+low+"]";
+ this.s0 = s;
+ this.high = high;
+ this.low = low;
+ this.width = 1+high-low;
+ }
public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
- public Assignable getAssignableBits(int high, int low) { return new SimpleValue(s, high, low); }
- public String getVerilogName() { return s; }
- public String toString() { return s; }
- public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
+ public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+ public Value getBits(int high, int low) {
+ if (this.high==-1 && this.low==-1) return new SimpleValue(s, high, low);
+ if (high+this.low > this.high) throw new RuntimeException("out of range");
+ return new SimpleValue(s0, high+this.low, low+this.low);
+ }
+ public String getVerilog() { return s; }
+ public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",width); }
+ public int getWidth() {
+ if (width==-1) throw new RuntimeException("not implemented");
+ return width;
+ }
+ }
+
+ public static class MuxValue implements Value {
+ private final Trigger sel;
+ private final Value if0;
+ private final Value if1;
+ public MuxValue(Trigger sel, Value if1, Value if0) {
+ this.sel = sel;
+ this.if0 = if0;
+ this.if1 = if1;
+ if (if0.getWidth() != if1.getWidth())
+ throw new RuntimeException("width mismatch; "+if0+"="+if0.getWidth()+", "+if1+"="+if1.getWidth());
+ }
+ public int getWidth() { return if0.getWidth(); }
+ public String getVerilog() { return "("+sel.getVerilogTrigger()+" ? "+if1.getVerilog()+" : "+if0.getVerilog()+")"; }
+ public Value getBits(int high, int low) { return new MuxValue(sel, if1.getBits(high,low), if0.getBits(high,low)); }
+ public Value getBits(Mask mask) { return new MuxValue(sel, if1.getBits(mask), if0.getBits(mask)); }
+ public Value invertBits() { return new MuxValue(sel, if1.invertBits(), if0.invertBits()); }
+ public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+ }
+
+ public static class ConstantValue implements Value {
+ private final BitVector bits;
+ public ConstantValue(BitVector bits) { this.bits = bits; }
+ public Value getBits(int high, int low) { return new ConstantValue(bits.get(high, low)); }
+ public Value getBits(Mask mask) { throw new RuntimeException("FIXME"); }
+ public Value invertBits() {
+ BitVector ret = new BitVector(bits.length());
+ for(int i=0; i<bits.length(); i++) ret.set(i, !bits.get(i));
+ return new ConstantValue(ret);
+ }
+ public String getVerilog() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(bits.length());
+ sb.append("'b");
+ for(int i=bits.length()-1; i>=0; i--)
+ sb.append(bits.get(i) ? '1' : '0');
+ return sb.toString();
+ }
+ public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+ public int getWidth() { return bits.length(); }
}
public static class CatValue implements Value {
private final Value[] values;
public CatValue(Value[] values) { this.values = values; }
public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
- public Value getBits(int high, int low) {
- throw new RuntimeException();
- }
- public Assignable getAssignableBits(int high, int low) {
- throw new RuntimeException();
+ public Value getBits(int high, int low) { throw new RuntimeException(); }
+ public int getWidth() {
+ int ret = 0;
+ for (Value val : values) ret += val.getWidth();
+ return ret;
}
- public String toString() { return getVerilogName(); }
- public String getVerilogName() {
+ public String getVerilog() {
StringBuffer sb = new StringBuffer();
sb.append("{ ");
boolean first = true;
for(int i=0; i<values.length; i++) {
if (values[i]==null) continue;
if (!first) sb.append(", ");
- sb.append(values[i].getVerilogName());
+ sb.append(values[i].getVerilog());
first = false;
}
sb.append(" }");
return sb.toString();
}
- public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
+ public Value invertBits() {
+ Value[] newvals = new Value[values.length];
+ for(int i=0; i<values.length; i++)
+ newvals[i] = values[i].invertBits();
+ return new CatValue(newvals);
+ }
+ public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
}
- public static interface Action {
- public String getVerilogAction();
+ public static class LogicValue implements Value {
+ public static enum LogicType { OR, AND };
+ private final Value v1;
+ private final Value v2;
+ private final LogicType tt;
+ public LogicValue(Value v1, LogicType tt, Value v2) {
+ this.v1 = v1;
+ this.v2 = v2;
+ this.tt = tt;
+ // FIXME: check width match
+ }
+ public String getVerilog() {
+ switch(tt) {
+ case OR: return "("+v1.getVerilog()+"||"+v2.getVerilog()+")";
+ case AND: return "("+v1.getVerilog()+"&&"+v2.getVerilog()+")";
+ }
+ throw new RuntimeException("impossible");
+ }
+ public Value getBits(int high, int low) { return new LogicValue(v1.getBits(high,low),tt,v2.getBits(high,low)); }
+ public Value getBits(Mask mask) { return new LogicValue(v1.getBits(mask),tt,v2.getBits(mask)); }
+ public Trigger testMask(Mask mask) { throw new RuntimeException("FIXME"); }
+ public Value invertBits() {
+ switch(tt) {
+ case OR: return new LogicValue(v1.invertBits(), LogicType.AND, v2.invertBits());
+ case AND: return new LogicValue(v1.invertBits(), LogicType.OR, v2.invertBits());
+ }
+ throw new RuntimeException("impossible");
+ }
+ public int getWidth() { return v1.getWidth(); }
+ }
+
+ public static class TestValue implements Value, Trigger {
+ public static enum TestType { NE, EQ, LT, GT, LE, GE };
+ private final Value v1;
+ private final Value v2;
+ private final TestType tt;
+ public TestValue(Value v1, TestType tt, Value v2) {
+ this.v1 = v1;
+ this.v2 = v2;
+ this.tt = tt;
+ // FIXME: check width match
+ }
+ public String getVerilogTrigger() { return getVerilog(); }
+ public String getVerilog() {
+ switch(tt) {
+ case NE: return "("+v1.getVerilog()+"!="+v2.getVerilog()+")";
+ case EQ: return "("+v1.getVerilog()+"=="+v2.getVerilog()+")";
+ case LE: return "("+v1.getVerilog()+"<="+v2.getVerilog()+")";
+ case GE: return "("+v1.getVerilog()+">="+v2.getVerilog()+")";
+ case LT: return "("+v1.getVerilog()+"<" +v2.getVerilog()+")";
+ case GT: return "("+v1.getVerilog()+">" +v2.getVerilog()+")";
+ }
+ throw new RuntimeException("impossible");
+ }
+ public Value getBits(int high, int low) { throw new RuntimeException("you probably didn't mean to do this"); }
+ public Value getBits(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
+ public Trigger testMask(Mask mask) { throw new RuntimeException("you probably didn't mean to do this"); }
+ public Trigger invert() { return invertMe(); }
+ public Value invertBits() { return invertMe(); }
+ private TestValue invertMe() {
+ switch(tt) {
+ case NE: return new TestValue(v1, TestType.EQ, v2);
+ case EQ: return new TestValue(v1, TestType.NE, v2);
+ case LE: return new TestValue(v1, TestType.GT, v2);
+ case GE: return new TestValue(v1, TestType.LT, v2);
+ case LT: return new TestValue(v1, TestType.GE, v2);
+ case GT: return new TestValue(v1, TestType.LE, v2);
+ }
+ throw new RuntimeException("impossible");
+ }
+ public int getWidth() { return 1; }
}
+ // Triggers //////////////////////////////////////////////////////////////////////////////
+
public static interface Trigger {
public String getVerilogTrigger();
public Trigger invert();
}
+ public static class SimpleTrigger implements Trigger {
+ private final String s;
+ public SimpleTrigger(String s) { this.s = s; }
+ public String getVerilogTrigger() { return s; }
+ public Trigger invert() { return new SimpleTrigger("!("+s+")"); }
+ }
+
+ public static class AndTrigger implements Trigger {
+ private final Trigger t1, t2;
+ public AndTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
+ public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" && "+t2.getVerilogTrigger()+")"; }
+ public Trigger invert() { return new InvertedTrigger(this); }
+ }
+
+ public static class OrTrigger implements Trigger {
+ private final Trigger t1, t2;
+ public OrTrigger(Trigger t1, Trigger t2) { this.t1 = t1; this.t2 = t2; }
+ public String getVerilogTrigger() { return "("+t1.getVerilogTrigger()+" || "+t2.getVerilogTrigger()+")"; }
+ public Trigger invert() { return new InvertedTrigger(this); }
+ }
+
public static class InvertedTrigger implements Trigger {
private final Trigger original;
public InvertedTrigger(Trigger original) { this.original = original; }
public Trigger invert() { return original; }
}
- public static interface Assignable {
- public String getVerilogName();
- public Assignable getAssignableBits(int high, int low);
+ public static class ConditionalTrigger implements Trigger {
+ public Trigger condition;
+ public Trigger trigger;
+ public ConditionalTrigger(Trigger condition, Trigger trigger) {
+ this.condition = condition;
+ this.trigger = trigger;
+ }
+ public String getVerilogTrigger() {
+ return "(("+condition.getVerilogTrigger()+") ? (" + trigger.getVerilogTrigger() + ") : 1)";
+ }
+ public Trigger invert() { return new InvertedTrigger(this); }
}
- public static interface Value extends Assignable {
- public String getVerilogName();
- public Value getBits(int high, int low);
- public Value getBits(Mask mask);
- public Value invertBits();
+ // Actions //////////////////////////////////////////////////////////////////////////////
+
+ public static interface Action {
+ public String getVerilogAction();
}
public static class ConditionalAction implements Action {
- public String condition;
+ public Trigger condition;
public Action action;
- public ConditionalAction(String condition, Action action) {
+ public ConditionalAction(Trigger 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 String getVerilogAction() { return "if ("+condition.getVerilogTrigger()+") begin "+action.getVerilogAction()+" end"; }
}
- public static class ConditionalTrigger implements Trigger {
- public String condition;
- public 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 AssignAction implements Action {
+ public Assignable left;
+ public Value right;
+ public AssignAction(Assignable left, Value right) {
+ this.left = left;
+ this.right = right;
}
- public Trigger invert() { return new InvertedTrigger(this); }
+ public String getVerilogAction() { return left.getVerilog() + "<=" + right.getVerilog() + ";"; }
+ }
+
+ // Assignables //////////////////////////////////////////////////////////////////////////////
+
+ public static interface Assignable {
+ public String getVerilog();
}
public static class SimpleAssignable implements Assignable {
public 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 Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
+ public String getVerilog() { return s; }
}
- public static class AssignAction implements Action {
- public String left;
- public 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(); }
- }
+ // Percolated Ports //////////////////////////////////////////////////////////////////////////////
- public static class SimpleAction implements Action {
- public final String verilog;
- public SimpleAction(String verilog) { this.verilog = verilog; }
- public String getVerilogAction() { return verilog; }
- public String toString() { return verilog; }
+ /**
+ * A PercolatedPort is a connection to a top-level pin; it is
+ * propagated up or down the hierarchy
+ */
+ public static class PercolatedPort {
+ public static enum PortType { UP, DOWN, INOUT };
+ public final String name;
+ public final int width;
+ public final PortType type;
+ public PercolatedPort(String name, int width, PortType type) {
+ this.name = name;
+ this.width = width;
+ this.type = type;
+ }
}
+
+ // Module Internals //////////////////////////////////////////////////////////////////////////////
+
public static class Module {
public void dump(String prefix) throws IOException {
PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v")));
public final ArrayList<String> portorder = new ArrayList<String>();
public final HashMap<String,StateWire> statewires = new HashMap<String,StateWire>();
public final HashMap<String,Latch> latches = new HashMap<String,Latch>();
+ public final HashMap<String,WireValue> wires = new HashMap<String,WireValue>();
- public StringBuffer crap = new StringBuffer();
- public 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 void addPreCrap0(String s) { precrap.append(s); }
+ public Module(String name) { this.name = name; }
- public Module(String name) {
- this.name = name;
- }
+ public SourcePort createInputPort(String name, int width) { return new SourcePort(name, width, true); }
+ public SinkPort createOutputPort(String name, int width) { return new SinkPort(name, width, true); }
- 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) throw new RuntimeException();
- return ret;
- }
- 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 createWirePort(String name, int width) {
- if (ports.get(name)!=null) throw new RuntimeException();
- return new SinkPort(name, width, false, "");
- }
- public SourcePort createWireSourcePort(String name, int width) {
- if (ports.get(name)!=null) throw new RuntimeException();
- return new SourcePort(name, width, false);
- }
- public SinkPort getOutputPort(String name) {
- SinkPort ret = (SinkPort)ports.get(name);
- if (ret==null) throw new RuntimeException();
- return ret;
- }
+ // Latches and Wires //////////////////////////////////////////////////////////////////////////////
public 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 String doReset() { return name+"<="+(initiallyFull?"1":"0")+";"; }
+ public Trigger isFull() { return new SimpleTrigger("("+name+"==1)"); }
+ public Trigger isEmpty() { return new SimpleTrigger("("+name+"==0)"); }
+ public Action doFill() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(1))); }
+ public Action doDrain() { return new AssignAction(new SimpleAssignable(name), new ConstantValue(new BitVector(1).set(0))); }
+ public String getResetCode() { return name+"<="+(initiallyFull?"1":"0")+";"; }
public StateWire(String name) { this(name, false); }
public StateWire(String name, boolean initiallyFull) {
this.name = name;
this.initial = initial;
latches.put(name, this);
}
- public String getVerilogName() { return name; }
- public Value getBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
+ public int getWidth() { return width; }
+ public String getVerilog() { return name; }
+ public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
- public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
- public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
- public String doReset() { return name+"<="+initial+";"; }
+ public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
+ public String getResetCode() { return name+"<="+initial+";"; }
public void dump(PrintWriter pw) {
pw.println(" reg ["+(width-1)+":0] "+name+";");
pw.println(" initial "+name+"="+initial+";");
}
- public void connect(SinkPort driven) {
- driven.latchDriver = this;
- }
+ public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
}
- public abstract class Port implements Action, Assignable, Trigger {
- public abstract String doReset();
+ public class WireValue implements Value {
public final String name;
- public String getName() { return name; }
public final int width;
+ public final Value assign;
+ public WireValue(String name, int width, Value assign) {
+ this.width = width;
+ this.name = name;
+ this.assign = assign;
+ wires.put(name, this);
+ }
public int getWidth() { return width; }
- public boolean hasLatch = false;
- public boolean external;
+ public String getVerilog() { return name; }
+ public Value getBits(int high, int low) { return new SimpleValue(getVerilog(), high, low); }
+ public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
+ public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
+ public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
+ public void dump(PrintWriter pw) { pw.println(" wire ["+(width-1)+":0] "+name+";"); }
+ public String getAssignments() { return " assign "+name+" = "+assign.getVerilog()+";"; }
+ }
+
+ // Ports //////////////////////////////////////////////////////////////////////////////
+
+ public abstract class Port implements Action, Trigger {
+ final String name;
+ final int width;
+ final boolean external;
public Port(String name, int width, boolean external) {
this.width = width;
this.name = name;
this.external = external;
+ if (ports.get(name)!=null)
+ throw new RuntimeException("port "+name+" already exists");
ports.put(name, this);
if (external)
portorder.add(name);
}
- public String getVerilogName() { return name; }
+ public String getName() { return name; }
+ public int getWidth() { return width; }
+ public String getVerilog() { return name; }
String getAck() { return name+"_a"; }
String getReq() { return name+"_r"; }
public String isFull() { return "("+name+"_r"+" && !"+name+"_a)"; }
+ public abstract String getResetCode();
public abstract String getInterface();
public abstract String getSimpleInterface();
public abstract String getDeclaration();
public abstract String getAssignments();
- public abstract void connect(SinkPort driven);
+ public abstract String getCleanup();
public Trigger invert() { return new InvertedTrigger(this); }
- }
-
- public static class InstantiatedModule {
- public final Module module;
- public final Module thisModule;
- public final int id;
- public final HashMap<String,Port> ports = new HashMap<String,Port>();
- public String getName() { return module.getName()+"_"+id; }
- public InstantiatedModule(Module thisModule, Module module) {
- this.thisModule = thisModule;
- this.module = module;
- this.id = thisModule.id++;
- thisModule.instantiatedModules.add(this);
- }
- public void dump(PrintWriter pw) {
- pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
- for(String s : module.portorder)
- pw.println(", " + getPort(s).getSimpleInterface());
- for(PercolatedPort pp : module.percolatedPorts)
- pw.println(" , "+pp.name);
- pw.println(" );");
- }
- public Port getPort(String name) {
- return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
- }
- public SinkPort getInputPort(String name) {
- int width = module.getPort(name).getWidth();
- SinkPort port = (SinkPort)ports.get(name);
- if (port == null) {
- port = thisModule.new SinkPort(getName()+"_"+name, width, false, "");
- ports.put(name, port);
- }
- return port;
- }
- public SourcePort getOutputPort(String name) {
- int width = module.getPort(name).getWidth();
- SourcePort port = (SourcePort)ports.get(name);
- if (port == null) {
- port = thisModule.new SourcePort(getName()+"_"+name, width, false);
- ports.put(name, port);
- }
- return port;
- }
+ public Trigger testMask(Mask mask) { return new SimpleTrigger(mask.verilog(getVerilog())); }
}
public class SourcePort extends Port implements Value {
- 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); }
+ 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(getVerilog(), high, low); }
public Value getBits(Mask mask) { return getBits(mask.valmaskmax, mask.valmaskmin); }
- public Value invertBits() { return new SimpleValue("~("+getVerilogName()+")"); }
- public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
- public String getVerilogTrigger() { return " && " + getReq() + " && !"+getAck(); }
+ public Value invertBits() { return new SimpleValue("~("+getVerilog()+")",getWidth()); }
+ 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 testBit(int index, boolean value) {
- return "("+name+"["+index+"]=="+(value?1:0)+")";
- }
+ public String testBit(int index, boolean value) { return "("+name+"["+index+"]=="+(value?1:0)+")"; }
public String getDeclaration() {
StringBuffer sb = new StringBuffer();
if (external) {
- sb.append("input " + name +"_r;\n");
- sb.append("output " + name +"_a_;\n");
- if (width>0)
- sb.append("input ["+(width-1)+":0]" + name +";\n");
- else
- sb.append("input [0:0]" + name +";\n"); // waste a bit, I guess
+ sb.append("input " + name +"_r;\n");
+ sb.append("output " + name +"_a_;\n");
+ sb.append("input ["+Math.max(0,width-1)+":0]" + name +";\n");
} else {
- sb.append("wire " + name +"_r;\n");
- if (width>0)
- sb.append("wire ["+(width-1)+":0]" + name +";\n");
+ sb.append("wire " + name +"_r;\n");
+ sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
}
- if (!hasLatch) {
+ if (driven!=null) {
sb.append("wire " + name +"_a;\n");
} else {
- sb.append("reg " + name +"_a;\n");
- sb.append("initial " + name +"_a = 0;\n");
+ sb.append("reg " + name +"_a;\n");
+ sb.append("initial " + name +"_a = 0;\n");
}
return sb.toString();
}
- public String doReset() { return hasLatch ? name+"_a<=1;" : ""; }
+ public String getCleanup() { return driven==null ? "if (!"+getReq()+" && "+getAck()+") "+getAck()+"<=0;" : ""; }
+ public String getResetCode() { return driven==null ? name+"_a<=1;" : ""; }
public String getAssignments() {
StringBuffer sb = new StringBuffer();
if (external)
return sb.toString();
}
public void connect(SinkPort driven) {
- driven.driver = this;
+ if (driven.controlDriver!=null) throw new RuntimeException("driven net already has a driver");
+ if (driven.latchDriver!=null) throw new RuntimeException("driven net already has a driver");
+ if (this.driven!=null) throw new RuntimeException("driver already has a driven net");
+ this.driven = driven;
+ driven.controlDriver = this;
+ driven.latchDriver = this;
+ // FIXME
+ // if (getWidth() != driven.getWidth())
+ // throw new RuntimeException("width mismatch: " + getWidth() + " " + driven.getWidth());
}
}
- public class SinkPort extends Port {
- public SourcePort driver = null;
- public boolean forceNoLatch = false;
- public SinkPort driven = null;
- public Value latchDriver = null;
- public boolean noDriveLatches = false;
- public final String resetBehavior;
- public Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); }
+
+ public class SinkPort extends Port implements Assignable {
+ SourcePort controlDriver = null;
+ Value latchDriver = null;
+ public SinkPort(String name, int width, boolean external) { super(name, width, external); }
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; }
+ public String getVerilogTrigger() { return "!" + getReq() + " && !"+getAck(); }
public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; }
public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; }
+ public String getCleanup() { return controlDriver==null ? "if ("+getReq()+" && "+getAck()+") begin "+getReq()+"<=0; end" : ""; }
+ public Assignable getBits(Mask mask) { return new SimpleAssignable(name+"["+mask.valmaskmax+":"+mask.valmaskmin+"]"); }
+ public String getResetCode() { return controlDriver!=null ? "" : name+"_r<=0;"; }
+ public void connectControl(SourcePort controlDriver) {
+ if (this.controlDriver != null) throw new RuntimeException("attempt to connect control twice");
+ this.controlDriver = controlDriver;
+ }
+ public void connectValue(Value val) {
+ //if (latchDriver!=null) throw new RuntimeException("attempt to re-assign via connectValue()");
+ this.latchDriver = val;
+ // FIXME
+ //if (getWidth() != val.getWidth())
+ //throw new RuntimeException("width mismatch: " + getWidth() + " " + val.getWidth());
+ }
public String getDeclaration() {
StringBuffer sb = new StringBuffer();
if (external) {
- sb.append("output " + name +"_r_;\n");
- sb.append("input " + name +"_a;\n");
- if (width>0)
- sb.append("output ["+(width-1)+":0]" + name +"_;\n");
- else
- sb.append("output [0:0]" + name +"_;\n"); // waste a bit, I guess
+ sb.append("output " + name +"_r_;\n");
+ sb.append("input " + name +"_a;\n");
+ sb.append("output ["+Math.max(0,width-1)+":0]" + name +"_;\n");
} else {
sb.append("wire " + name +"_a;\n");
}
-
- if (forceNoLatch || latchDriver!=null) {
- sb.append("reg " + name +"_r;\n");
- sb.append("initial " + name +"_r = 0;\n");
- if (width>0)
- sb.append("wire ["+(width-1)+":0]" + name +";\n");
- } else if (!hasLatch) {
+ if (controlDriver!=null) {
sb.append("wire " + name +"_r;\n");
- if (width>0)
- sb.append("wire ["+(width-1)+":0]" + name +";\n");
+ sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
} else {
sb.append("reg " + name +"_r;\n");
sb.append("initial " + name +"_r = 0;\n");
- if (width>0) {
- sb.append("reg ["+(width-1)+":0]" + name +";\n");
- if (!"/*NORESET*/".equals(resetBehavior))
- sb.append("initial " + name +" = 0;\n");
- }
+ if (latchDriver!=null) sb.append("wire ["+Math.max(0,width-1)+":0]" + name +";\n");
+ else sb.append("reg ["+Math.max(0,width-1)+":0]" + name +";\n");
}
return sb.toString();
}
- public String doReset() {
- return (forceNoLatch||latchDriver!=null||width==0)
- ? name+"_r<=0;"
- : hasLatch
- ? (name+"_r<=0; "+("/*NORESET*/".equals(resetBehavior) ? "" : (name+"<=0;")))
- : "";
- }
public String getAssignments() {
StringBuffer sb = new StringBuffer();
if (external) {
sb.append("assign " + name +"_r_ = " + name + "_r;\n");
- if (width>0)
- sb.append("assign " + name +"_ = " + name + ";\n");
+ sb.append("assign " + name +"_ = " + name + ";\n");
}
- if (driven != null) {
- sb.append("assign " + driven.name +"_r = " + name + "_r;\n");
- sb.append("assign " + name +"_a = " + driven.name + "_a;\n");
- if (width>0)
- sb.append("assign " + driven.name +" = " + name + ";\n");
- }
- if (driver != null) {
- sb.append("assign " + name +"_r = " + driver.name + "_r;\n");
- sb.append("assign " + driver.name +"_a = " + name + "_a;\n");
- if (width>0 && !noDriveLatches && latchDriver==null)
- sb.append("assign " + name +" = " + driver.name + ";\n");
- }
- if (latchDriver != null) {
- if (width>0)
- sb.append("assign " + name +" = " + latchDriver.getVerilogName() + ";\n");
+ if (controlDriver != null) {
+ sb.append("assign " + name +"_r = " + controlDriver.name + "_r;\n");
+ sb.append("assign " + controlDriver.name +"_a = " + name + "_a;\n");
+ if (latchDriver==null)
+ sb.append("assign " + name +" = " + controlDriver.name + ";\n");
}
+ if (latchDriver != null)
+ sb.append("assign " + name +" = " + latchDriver.getVerilog() + ";\n");
return sb.toString();
}
- public void connect(SinkPort driven) {
- this.driven = driven;
- throw new RuntimeException();
+ }
+
+ // InstantiatedModule //////////////////////////////////////////////////////////////////////////////
+
+ public static class InstantiatedModule {
+ public final Module module;
+ public final Module thisModule;
+ public final int id;
+ public final HashMap<String,Port> ports = new HashMap<String,Port>();
+ public String getName() { return module.getName()+"_"+id; }
+ public InstantiatedModule(Module thisModule, Module module) {
+ this.thisModule = thisModule;
+ this.module = module;
+ this.id = thisModule.id++;
+ thisModule.instantiatedModules.add(this);
+ for(String s : module.portorder)
+ getPort(s);
+ }
+ public void dump(PrintWriter pw) {
+ pw.println(" " + module.getName() + " " + getName() + "(clk, rst ");
+ for(String s : module.portorder)
+ pw.println(", " + getPort(s).getSimpleInterface());
+ for(PercolatedPort pp : module.percolatedPorts)
+ pw.println(" , "+pp.name);
+ pw.println(" );");
+ }
+ public Port getPort(String name) {
+ return (module.ports.get(name) instanceof SinkPort) ? getOutputPort(name) : getInputPort(name);
+ }
+ public SinkPort getInputPort(String name) {
+ int width = module.getPort(name).getWidth();
+ SinkPort port = (SinkPort)ports.get(name);
+ if (port == null) {
+ port = thisModule.new SinkPort(getName()+"_"+name, width, false);
+ ports.put(name, port);
+ }
+ return port;
+ }
+ public SourcePort getOutputPort(String name) {
+ int width = module.getPort(name).getWidth();
+ SourcePort port = (SourcePort)ports.get(name);
+ if (port == null) {
+ port = thisModule.new SourcePort(getName()+"_"+name, width, false);
+ ports.put(name, port);
+ }
+ return port;
}
}
public void dump(PrintWriter pw, boolean fix) {
+ if (!fix) throw new RuntimeException();
boolean isRoot = name.equals("main");
pw.print("module "+name);
- if (isRoot) {
- pw.println("(clk_pin, rst_pin ");
- } else {
- pw.println("(clk, rst ");
- }
- for(String name : portorder) {
- Port p = ports.get(name);
- pw.println(" , " + p.getInterface());
- }
+ pw.println(isRoot ? "(clk_pin, rst_pin " : "(clk, rst ");
+ for(String name : portorder) pw.println(" , " + ports.get(name).getInterface());
for (InstantiatedModule im : this.instantiatedModules)
for(PercolatedPort pp : im.module.percolatedPorts)
if (!isRoot || (!pp.name.startsWith("root_in_") && !pp.name.startsWith("rst_")))
pw.println(" wire clk;");
pw.println(" wire clk_fb;");
pw.println(" wire clk_unbuffered;");
+ pw.println(" assign clk_unbuffered = clk_pin;");
+ //pw.println(" assign clk = clk_pin;");
+
pw.println(" BUFG GBUF_FOR_MUX_CLOCK (.I(clk_unbuffered), .O(clk));");
+ /*
pw.println(" DCM");
pw.println(" #(");
pw.println(" .CLKFX_MULTIPLY(4),");
pw.println(" .CLKFX (clk_unbuffered),");
pw.println(" .CLK0 (clk_fb)");
pw.println(" );");
+ */
pw.println(" wire rst;");
} else {
pw.println(" input clk;");
pw.println(" assign rst_in = rst_pin;");
}
- for(String name : ports.keySet()) {
- 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());
- }
- for(InstantiatedModule m : instantiatedModules) {
- m.dump(pw);
- }
- pw.println(precrap);
+ for(String name : ports.keySet()) pw.println(" " + ports.get(name).getDeclaration());
+ for(StateWire sw : statewires.values()) sw.dump(pw);
+ for(Latch l : latches.values()) l.dump(pw);
+ for(WireValue wv : wires.values()) wv.dump(pw);
+ for(String name : ports.keySet()) pw.println(" " + ports.get(name).getAssignments());
+ for(WireValue wv : wires.values()) pw.println(" " + wv.getAssignments());
+ for(InstantiatedModule m : instantiatedModules) m.dump(pw);
pw.println("always @(posedge clk) begin");
pw.println(" if (!rst) begin");
- for(Latch l : latches.values())
- pw.println(l.doReset());
- for(StateWire sw : statewires.values())
- pw.println(sw.doReset());
- for(Port p : ports.values())
- pw.println(p.doReset());
+ for(Latch l : latches.values()) pw.println(l.getResetCode());
+ for(StateWire sw : statewires.values()) pw.println(sw.getResetCode());
+ for(Port p : ports.values()) pw.println(p.getResetCode());
pw.println(" end else begin");
- for(Port p : ports.values()) {
- if (p instanceof SourcePort) {
- SourcePort ip = (SourcePort)p;
- if (ip.hasLatch)
- pw.println("if (!"+ip.getReq()+" && "+ip.getAck()+") "+ip.getAck()+"<=0;");
- } else {
- SinkPort op = (SinkPort)p;
- if (op.hasLatch)
- pw.println("if ("+op.getReq()+" && "+op.getAck()+") begin "+
- op.getReq()+"<=0; "+
- op.getResetBehavior()+" end");
- }
- }
+ for(Port p : ports.values()) pw.println(p.getCleanup());
for(Event a : events) a.dump(pw, fix);
pw.println(" begin end");
pw.println(" end");
pw.println(" end");
-
- pw.println(crap);
pw.println("endmodule");
}
Module.this.events.add(this);
this.triggers = triggers;
this.actions = actions;
- for(int i=0; i<triggers.length; i++)
- if (triggers[i] instanceof Port)
- ((Port)triggers[i]).hasLatch = true;
}
public void dump(PrintWriter pw, boolean fix) {
+ if (!fix) throw new RuntimeException();
pw.print("if (1");
for(Object o : triggers) {
- if (o instanceof Trigger) pw.print(((Trigger)o).getVerilogTrigger());
+ if (o instanceof Trigger) pw.print(" && " + ((Trigger)o).getVerilogTrigger());
else pw.print(" && " + o);
}
pw.println(") begin ");
private final String name;
private final boolean inbox;
private final boolean left;
+ private final boolean isDockless;
private final HashMap<String,ShipDescription.Constant> constants = new HashMap<String,ShipDescription.Constant>();
DockDescription(ShipDescription ship, String name, boolean left, boolean inbox) {
+ this(ship, name, left, inbox, false);
+ }
+ DockDescription(ShipDescription ship, String name, boolean left, boolean inbox, boolean isDockless) {
this.left = left;
this.ship = ship;
this.name = name;
this.inbox = inbox;
+ this.isDockless = isDockless;
}
public String getName() { return name; }
public boolean isInputDock() { return inbox; }
public boolean isOutputDock() { return !inbox; }
+ public boolean isDockless() { return isDockless; }
/** Indicates if this dock should be drawn on the "left hand side" of the ship for visual purposes */
boolean isLeft() { return left; }
public class ShipDescription implements Iterable<DockDescription> {
private String name;
- private LinkedHashMap<String,DockDescription> docks = new LinkedHashMap<String,DockDescription>();
- private HashMap<String,String> sections = new HashMap<String,String>();
- private HashMap<String,Constant> constants = new HashMap<String,Constant>();
+ private LinkedHashMap<String,DockDescription> docks = new LinkedHashMap<String,DockDescription>();
+ private LinkedHashMap<String,DockDescription> ports = new LinkedHashMap<String,DockDescription>();
+ private HashMap<String,String> sections = new HashMap<String,String>();
+ private HashMap<String,Constant> constants = new HashMap<String,Constant>();
public String getName() { return name; }
public String getSection(String sectionName) { return sections.get(sectionName); }
public DockDescription getDockDescription(String name) { return docks.get(name); }
public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
+ public Iterable<DockDescription> ports() {
+ return ports.values();
+ }
public final LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
String key = s.substring(0, s.indexOf(':')).trim();
boolean inbox = false;
+ boolean dockless = false;
key = key.replaceAll(" +", " ");
if (key.equals("data in")) { inbox = true; }
else if (key.equals("data out")) { inbox = false; }
else if (key.equals("in")) { inbox = true; }
+ else if (key.equals("dockless out")) { inbox = false; dockless = true; }
else if (key.equals("out")) { inbox = false; }
else if (key.startsWith("percolate")) {
key = s;
String dest = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1) : "";
p = docks.get(boxname);
if (p==null) {
- p = new DockDescription(this, boxname, !rightSide, inbox);
- docks.put(boxname, p);
+ p = new DockDescription(this, boxname, !rightSide, inbox, dockless);
+ ports.put(boxname, p);
+ if (!dockless) docks.put(boxname, p);
}
}
}
return "("+sb.toString()+")";
//return "(("+var+" & "+allmax+"'b"+Long.toString(mask,2)+")=="+allmax+"'b"+Long.toString(val,2)+")";
}
- public String verilogVal(String var) {
- //return "(("+var+" & "+allmax+"'b"+Long.toString(valmask,2)+") >> "+valmaskmin+")";
- return ""+var+"["+valmaskmax+":"+valmaskmin+"]";
- }
public long getval(long in) {
return (in & valmask) >>> valmaskmin;