From: adam Date: Wed, 25 Jun 2008 10:18:28 +0000 (+0100) Subject: total overhaul: fleetcode-1.0 api finished X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=f793208c02dc38ee6f3b1c548087157b5c3300db;p=fleet.git total overhaul: fleetcode-1.0 api finished --- diff --git a/src/edu/berkeley/fleet/Main.java b/src/edu/berkeley/fleet/Main.java index 74f89db..f7f21e3 100644 --- a/src/edu/berkeley/fleet/Main.java +++ b/src/edu/berkeley/fleet/Main.java @@ -2,8 +2,9 @@ package edu.berkeley.fleet; import edu.berkeley.sbp.util.ANSI; import edu.berkeley.fleet.api.*; import edu.berkeley.fleet.fpga.*; -import edu.berkeley.fleet.doc.*; import edu.berkeley.fleet.interpreter.*; +import edu.berkeley.fleet.two.*; +import edu.berkeley.fleet.util.*; import java.io.*; import java.util.*; @@ -36,7 +37,7 @@ public class Main { Fleet fleet; if ("fpga".equals(target)) { String bitfile = options.get("bitfile"); - fleet = bitfile == null ? new Fpga() : new Fpga(bitfile); + fleet = new Fpga(); } else if ("sim".equals(target) || "fleetsim".equals(target)) { fleet = (Fleet)Class.forName("com.sunlabs.fleetsim.fleet.FleetDescription").newInstance(); } else { @@ -48,40 +49,37 @@ public class Main { if (command.equals("run")) { InputStream is; - if (args.size()==0) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Reader r = new InputStreamReader(System.in); - edu.berkeley.fleet.assembler.Main.assemble(fleet, r, baos); - is = new ByteArrayInputStream(baos.toByteArray()); - } else { - String filename = args.get(0); - if (filename.endsWith(".fa") || filename.endsWith(".fleet")) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Reader r = new InputStreamReader(new FileInputStream(args.get(0))); - edu.berkeley.fleet.assembler.Main.assemble(fleet, r, baos); - is = new ByteArrayInputStream(baos.toByteArray()); - } else { - is = new FileInputStream(args.get(0)); - } - } - run(fleet, is); + String filename = args.get(0); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Reader r = new InputStreamReader(new FileInputStream(args.get(0))); + run(fleet, edu.berkeley.fleet.assembler.Main.assemble(fleet, r)); } else if (command.equals("expand")) { - fleet.expand(new ShipDescription(args.get(0), new BufferedReader(new InputStreamReader(new FileInputStream(args.get(0)))))); + String name = new File(args.get(0)).getName(); + if (name.endsWith(".ship")) + name = name.substring(0, name.length() - ".ship".length()); + if (fleet instanceof edu.berkeley.fleet.fpga.Fpga) { + ((edu.berkeley.fleet.fpga.Fpga)fleet).expand(new ShipDescription(name, new BufferedReader(new InputStreamReader(new FileInputStream(args.get(0)))))); + } else { + ((Interpreter)fleet).expand(new ShipDescription(name, new BufferedReader(new InputStreamReader(new FileInputStream(args.get(0)))))); + } } else if (command.equals("doc")) { - Doc.print(); + if (!new File(".tmp").exists()) + new File(".tmp").mkdirs(); + PrintWriter pw = new PrintWriter(new FileOutputStream(".tmp/FleetTwo.Manual.tex")); + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("doc/archman.tex"))); + for(String ss = br.readLine(); ss!=null; ss = br.readLine()) + pw.println(ss); + for(String f : new File("ships").list()) { + new ShipDescription(f, new BufferedReader(new InputStreamReader(new FileInputStream(new File("ships/"+f))))).printTeX(pw); + } + pw.println("\\end{document}"); + pw.close(); } else if (command.equals("test")) { for(int i=0; i expect = edu.berkeley.fleet.assembler.Parser.expect; String output = ""; @@ -111,7 +109,8 @@ public class Main { System.out.print("\r" + verdict + " " + ANSI.yellow(title) + ": " + output); if (failed) break; if (expect.size() == 0) break; - long l = fp.readWord(); + //if (now!=0) { System.err.println(); System.err.println(System.currentTimeMillis()-now); now=0;} + long l = unBitSet(fp.readWord()); long l2 = expect.remove(0); // FIXME, this is ugly and not size-independent @@ -156,17 +155,10 @@ public class Main { } } - public static void run(Fleet fleet, InputStream is) throws IOException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[1024]; + public static void run(Fleet fleet, Instruction[] instructions) throws IOException { + FleetProcess client = fleet.run(instructions); while(true) { - int numread = is.read(buf, 0, buf.length); - if (numread==-1) break; - baos.write(buf, 0, numread); - } - FleetProcess client = fleet.run(baos.toByteArray()); - while(true) { - long result = client.readWord(); + long result = unBitSet(client.readWord()); System.err.print(result); System.err.print(" 0x"); System.err.print(Long.toString(result, 16)); @@ -174,6 +166,17 @@ public class Main { } } + public static long unBitSet(BitVector bs) { + long val = 0; + for(int i=0; i<37; i++) { + if (bs.get(i)) + val |= (1L << i); + } + if ((val & (1L << 36)) != 0) + val = val | (0xffffffffffffffffL << 36); + return val; + } + static void usage() { System.err.println("........................................................................."); System.err.println("Fleet Framework UC Berkeley, Sun Labs / 2007"); diff --git a/src/edu/berkeley/fleet/api/BitVector.java b/src/edu/berkeley/fleet/api/BitVector.java new file mode 100644 index 0000000..e217e6c --- /dev/null +++ b/src/edu/berkeley/fleet/api/BitVector.java @@ -0,0 +1,45 @@ +package edu.berkeley.fleet.api; + +/** + * A sequence of bits with a fixed length. This class performs + * important error-checking not found in the Java BitSet and + * BigInteger classes. + */ +public class BitVector { + + private final boolean[] bits; + + public BitVector(int length) { + this.bits = new boolean[length]; + } + + /** copy the low-order bits of the argument into this BitVector; returns this */ + public BitVector set(long value) { + for(int i=0; i>> i) & 1L) != 0); + return this; + } + + public int length() { + return bits.length; + } + + public void set(int bit, boolean value) { + bits[bit] = value; + } + + public boolean get(int bit) { + return bits[bit]; + } + + public String toString() { + StringBuffer ret = new StringBuffer(); + ret.append(length()+""); + ret.append("'b"); + for(int i=length()-1; i>=0; i--) + ret.append(get(i) ? '1' : '0'); + return ret.toString(); + } +} + + diff --git a/src/edu/berkeley/fleet/api/Destination.java b/src/edu/berkeley/fleet/api/Destination.java index eeda1d2..238db4f 100644 --- a/src/edu/berkeley/fleet/api/Destination.java +++ b/src/edu/berkeley/fleet/api/Destination.java @@ -1,14 +1,21 @@ package edu.berkeley.fleet.api; +/** + * A physical destination on the switch fabric -- may have multiple + * paths to it from any particular source. + */ public abstract class Destination { - /** return the Ship to which this Pump belongs */ - public abstract Ship getShip(); + private final Dock dock; + + public Destination(Dock dock) { + this.dock = dock; + } + + /** Get the Dock to which this destination belongs, null if none. */ + public Dock getDock() { return dock; } + + /** subclasses must override this */ + public abstract String toString(); - /** - * this returns the third component of the name; that is in - * "ship.port.foo", it returns "foo", and in "ship.port" it - * returns "" - */ - public abstract String getDestinationName(); } diff --git a/src/edu/berkeley/fleet/api/Dock.java b/src/edu/berkeley/fleet/api/Dock.java new file mode 100644 index 0000000..c0d77af --- /dev/null +++ b/src/edu/berkeley/fleet/api/Dock.java @@ -0,0 +1,43 @@ +package edu.berkeley.fleet.api; +import java.util.*; + +/** A dock on a ship */ +public abstract class Dock { + + private final Ship ship; + + public Dock(Ship ship) { + this.ship = ship; + } + + /** return the Ship to which this Dock belongs */ + public Ship getShip() { return ship; } + + /** the descriptive name of this dock (relative to its ship) */ + public abstract String getName(); + + /** returns true if this is an input dock */ + public abstract boolean isInputDock(); + + /** returns true if this is an output dock */ + public abstract boolean isOutputDock(); + + /** returns the Path from this dock to dest, carrying the signal specified or none if null */ + public abstract Path getPath(Destination dest, BitVector signal); + + /** the data destination of this dock */ + public abstract Destination getDataDestination(); + + /** the instruction destination of this dock */ + public abstract Destination getInstructionDestination(); + + /** + * The maximum number of instructions we can put in the Dock + * instruction fifo, or Integer.MAX_VALUE if unbounded; note that + * this does not include the epilogue fifo -- that can be + * determined with getInstructionDestination().getFifoLength() + */ + public abstract int getInstructionFifoSize(); + + public String toString() { return getShip()+"."+getName(); } +} diff --git a/src/edu/berkeley/fleet/api/Fleet.java b/src/edu/berkeley/fleet/api/Fleet.java index 6391bf5..48651f0 100644 --- a/src/edu/berkeley/fleet/api/Fleet.java +++ b/src/edu/berkeley/fleet/api/Fleet.java @@ -1,35 +1,51 @@ package edu.berkeley.fleet.api; -import edu.berkeley.fleet.doc.*; import java.io.*; import java.util.*; +/** + * An instance of Fleet; each Fleet consists of a collection of + * Ships. + * + *

Note about instruction representation: it is very + * important to understand that the binary representation of an + * instruction includes a path from the dock which will + * dispatch the instruction to the dock which will + * execute the instruction. Therefore, an instruction cannot + * be converted to binary form without supplying a + * dispatching dock so the necessary path can be computed. + * Moreover: because a given string of bits uniquely describes + * a path only if given along with a starting point, instructions + * cannot be converted from binary format without knowing the + * dispatch dock from which they are meant to be dispatched. This + * is why the {@link readInstruction} and {@link writeInstruction} + * methods take a "dispatchFrom" argument. + */ public abstract class Fleet implements Iterable { - /** read a machine-formatted instruction from a file (into a Java object) */ - public abstract Instruction readInstruction(DataInputStream is) throws IOException; - - /** write a machine-formatted instruction to a file (from a Java object) */ - public abstract void writeInstruction(DataOutputStream os, Instruction instr) throws IOException; - - /** ships must be returned in the same order every time -- ordering may be significant */ public abstract Iterator iterator(); - /** if possible, run the given code and create a FleetProcess */ - public FleetProcess run(byte[] code) { - throw new RuntimeException("class " + this.getClass().getName() + " does not implement method run()"); - } + /** A ship is uniquely identified by its type (a string) and its ordinal; for example, Fifo[7]. */ + public abstract Ship getShip(String type, int ordinal); - /** extract the portion of ShipDescription which is specific to this fleet and generate any source code necessary */ - public void expand(ShipDescription sd) { - throw new RuntimeException("class " + this.getClass().getName() + " does not implement method expand()"); - } + /** the natural word width of this machine */ + public abstract int getWordWidth(); /** - * This interface marks Fleets which can create ships on the fly, like the fleeterpreter; - * if available, the parser will use this interface to create ships out of #ship definitions. + * Read a machine-formatted instruction from a file. + * @is The stream to read from. + * @dispatchFrom The dock from which the instructions being read are to be dispatched (required for decoding) */ - public static interface WithDynamicShips { - public Ship createShip(String shiptype, String shipname); - } + public abstract Instruction readInstruction(DataInputStream is, Dock dispatchFrom) throws IOException; -} \ No newline at end of file + /** + * Write a machine-formatted instruction to a file. + * @os The stream to write to. + * @dispatchFrom The dock from which the instruction being written is to be dispatched (required for encoding) + */ + public abstract void writeInstruction(DataOutputStream os, Dock dispatchFrom, Instruction instr) throws IOException; + + /** If supported, run the given code and create a FleetProcess to interact with it. */ + public FleetProcess run(Instruction[] program) { + throw new RuntimeException("class " + this.getClass().getName() + " does not implement method run()"); + } +} diff --git a/src/edu/berkeley/fleet/api/FleetProcess.java b/src/edu/berkeley/fleet/api/FleetProcess.java index 096c29e..ef9297c 100644 --- a/src/edu/berkeley/fleet/api/FleetProcess.java +++ b/src/edu/berkeley/fleet/api/FleetProcess.java @@ -2,18 +2,31 @@ package edu.berkeley.fleet.api; import java.io.*; import java.util.*; -/** represents a running "slave" fleet with a debug connection */ +/** + * Represents a running "slave" fleet with debugging + * facilities controlled by the "master" JVM. + * + *

Each Fleet which supports this API must include: + *

  • The ability to dispatch instructions from the master, "on + * the fly". + *
  • A "debug.in" dock such that any words delivered there + * are sent back to the master. + *
+ */ public abstract class FleetProcess { private boolean terminated = false; - /** dumps an instruction into the fetch unit */ - public abstract void invokeInstruction(Instruction i); + /** dispatch an instruction */ + public abstract void dispatchInstruction(Instruction i); - /** reads a word back from the debug port */ - public abstract long readWord(); + /** the dock used to read back data from the slave */ + public abstract Dock getDebugInputDock(); - /** subclasses may be assured that this will be called exactly once */ + /** returns the next word delivered at the dock specified by getDebugInputDock() */ + public abstract BitVector readWord(); + + /** Terminate the process; subclasses may be assured that this will be called exactly once. */ protected abstract void _terminate(); public final synchronized void terminate() { @@ -22,13 +35,6 @@ public abstract class FleetProcess { _terminate(); } - public final boolean isTerminated() { - return terminated; - } - - public synchronized void finalize() { - if (!terminated) - terminate(); - } - + public final boolean isTerminated() { return terminated; } + public synchronized void finalize() { terminate(); } } diff --git a/src/edu/berkeley/fleet/api/Instruction.java b/src/edu/berkeley/fleet/api/Instruction.java index 290fcac..f889393 100644 --- a/src/edu/berkeley/fleet/api/Instruction.java +++ b/src/edu/berkeley/fleet/api/Instruction.java @@ -1,268 +1,320 @@ package edu.berkeley.fleet.api; +import java.util.*; +/** a Fleet instruction; includes execution location but not full dispatch path */ public abstract class Instruction { - public final Pump pump; - public Instruction(Pump pump) { this.pump = pump; } - public String toString() { return pump+": "; } + /** the dock which is to execute this instruction */ + public final Dock dock; - public boolean isLooping() { return true; } - public boolean isRepeating() { return false; } - public boolean isSK() { return false; } - public boolean isDL() { return false; } + /** true if the instruction is an outer-looping instruction */ + public final boolean looping; - public static class Clog extends Instruction { - public Clog(Pump pump) { super(pump); } - public String toString() { return super.toString() + "clog;"; } - public boolean isLooping() { return false; } - } + /** the instruction's predicate */ + public final Predicate predicate; - public static class UnClog extends Instruction { - public UnClog(Pump pump) { super(pump); } - public String toString() { return super.toString() + "unclog;"; } + Instruction(Dock dock, boolean looping, Predicate predicate) { + if (dock==null) throw new RuntimeException("dock may not be null"); + if (predicate==null) throw new RuntimeException("predicate may not be null"); + this.dock = dock; + this.looping = looping; + this.predicate = predicate; } - public static class Massacre extends Instruction { - public Massacre(Pump pump) { super(pump); } + public String toString() { + String s = predicate.toString(); + if (s.length()>0) s = "["+s+"] "; + return s+dock+": "; } - public static class Kill extends Instruction { - public final int count; - public Kill(Pump pump, int count) { super(pump); this.count = count; } - public String toString() { return super.toString() + "kill"+(count==1?"":(" "+count))+";"; } - } + /** + * A set instruction. + * + * Note that immediates are supplied as Java long values + * because they are actual integers with two's complement + * sign-extension semantics. This is in contrast to most other + * immediate values in the API which are raw bit sequences of + * fixed length -- these are represented by instances of + * BitVector. + */ + public static class Set extends Instruction { - public static class PredicatedInstruction extends Instruction { - public static final int P_ALWAYS = 0x0001; - public static final int P_IF_A = 0x0002; - public static final int P_IF_B = 0x0003; - public static final int P_IF_Z = 0x0004; - - public final int predicate; - public final boolean dl; - public boolean isDL() { return dl; } - - public PredicatedInstruction(Pump pump, boolean dl, int predicate) { - super(pump); - this.predicate = predicate; - this.dl = dl; - } - public String toString() { - String dlx = dl ? "[dl] " : ""; - switch(predicate) { - case P_ALWAYS: return dlx+ super.toString(); - case P_IF_A: return dlx+"[a] "+super.toString(); - case P_IF_B: return dlx+"[b] "+super.toString(); - case P_IF_Z: return dlx+"[z] "+super.toString(); + /** the destination (latch to be set) */ + public final SetDest dest; + + /** the source (what will be put in the dest latch) */ + public final SetSource source; + + /** if source is Immediate, this is the immediate value; an integer */ + public final long immediate; + + /** if source is ImmediatePath, this is the immediate path */ + public final Path path; + + /** if dest is Flags, this is the truth table to update flag "a" */ + public final FlagFunction newFlagA; + + /** if dest is Flags, this is the truth table to update flag "b" */ + public final FlagFunction newFlagB; + + /** basic constructor */ + public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, SetSource source) { + super(dock, looping, predicate); + OUTER: switch(dest) { + case InnerLoopCounter: + switch(source) { + case Infinity: case DataLatch: case Immediate: break OUTER; + default: break; + } + case OuterLoopCounter: + switch(source) { + case Decrement: case DataLatch: case Immediate: break OUTER; + default: break; + } + case DataLatch: + if (source==SetSource.Immediate) break; + default: throw new RuntimeException("cannot set " + dest + " to " + source); } - throw new Error(); + this.source = source; + this.dest = dest; + this.immediate = 0; + this.path = null; + this.newFlagA = null; + this.newFlagB = null; } - } - public static class SetFlags extends PredicatedInstruction { - public static final int FLAG_Z = 0x0001; - public static final int FLAG_NOT_Z = 0x0002; - public static final int FLAG_S = 0x0004; - public static final int FLAG_NOT_S = 0x0008; - public static final int FLAG_B = 0x0010; - public static final int FLAG_NOT_B = 0x0020; - public static final int FLAG_A = 0x0040; - public static final int FLAG_NOT_A = 0x0080; - - public final int flag_a; - public final int flag_b; - public SetFlags(Pump pump, boolean dl, int predicate, int flag_a, int flag_b) { - super(pump, dl, predicate); - this.flag_a = flag_a; - this.flag_b = flag_b; + /** constructor for set instructions with immediates */ + public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, long immediate) { + super(dock, looping, predicate); + if (dest!=SetDest.InnerLoopCounter && dest!=SetDest.OuterLoopCounter && dest!=SetDest.DataLatch) + throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate"); + this.source = SetSource.Immediate; + this.dest = dest; + this.immediate = immediate; + this.path = null; + this.newFlagA = null; + this.newFlagB = null; } - public SetFlags(Pump pump, int flag_a, int flag_b) { this(pump, false, P_ALWAYS, flag_a, flag_b); } - - public boolean isLooping() { return true; } - private String printFlag(int flag) { - if (flag==0) return "0"; - if ((flag & (FLAG_Z | FLAG_NOT_Z)) == (FLAG_Z | FLAG_NOT_Z)) return "1"; - if ((flag & (FLAG_B | FLAG_NOT_B)) == (FLAG_B | FLAG_NOT_B)) return "1"; - if ((flag & (FLAG_A | FLAG_NOT_A)) == (FLAG_A | FLAG_NOT_A)) return "1"; - if ((flag & (FLAG_S | FLAG_NOT_S)) == (FLAG_S | FLAG_NOT_S)) return "1"; - String ret = ""; - if ((flag & FLAG_A) != 0) ret += (ret.length()>=0?"|":"") + "a"; - if ((flag & FLAG_NOT_A) != 0) ret += (ret.length()>=0?"|":"") + "!a"; - if ((flag & FLAG_B) != 0) ret += (ret.length()>=0?"|":"") + "b"; - if ((flag & FLAG_NOT_B) != 0) ret += (ret.length()>=0?"|":"") + "!b"; - if ((flag & FLAG_S) != 0) ret += (ret.length()>=0?"|":"") + "s"; - if ((flag & FLAG_NOT_S) != 0) ret += (ret.length()>=0?"|":"") + "!s"; - if ((flag & FLAG_Z) != 0) ret += (ret.length()>=0?"|":"") + "z"; - if ((flag & FLAG_NOT_Z) != 0) ret += (ret.length()>=0?"|":"") + "!z"; - return ret; + + /** constructor for set instructions with immediate paths */ + public Set(Dock dock, boolean looping, Predicate predicate, SetDest dest, Path path) { + super(dock, looping, predicate); + if (dest!=SetDest.TAPL) + throw new RuntimeException("a set instruction with dest="+dest+" may not take an immediate path"); + this.source = SetSource.ImmediatePath; + this.dest = dest; + this.immediate = 0; + this.path = path; + this.newFlagA = null; + this.newFlagB = null; } - public String toString() { - return super.toString() + " setflags a=" + printFlag(flag_a) + ", b=" + printFlag(flag_b); + + /** constructor for set flags instructions */ + public Set(Dock dock, boolean looping, Predicate predicate, FlagFunction newFlagA, FlagFunction newFlagB) { + super(dock, looping, predicate); + this.source = SetSource.Immediate; + this.dest = SetDest.Flags; + this.immediate = 0; + this.path = null; + this.newFlagA = newFlagA; + this.newFlagB = newFlagB; } - } - public static class DecrLoop extends PredicatedInstruction { - public DecrLoop(Pump pump) { super(pump, true, P_ALWAYS); } - public DecrLoop(Pump pump, boolean dl, int predicate) { super(pump, dl, predicate); } - public boolean isDL() { return true; } - public boolean isLooping() { return true; } - } + /** possible sources for the Set instruction */ + public static enum SetSource { + Infinity, DataLatch, Immediate, ImmediatePath, Decrement; + } + /** possible destinations for the Set instruction */ + public static enum SetDest { + InnerLoopCounter, OuterLoopCounter, TAPL, Flags, DataLatch; + } - public static class Counter extends PredicatedInstruction { - public static final int DATA_LATCH = -1; - public static final int REPEAT_COUNTER = -2; - public static final int LOOP_COUNTER = -3; - public static final int STANDING = -3; - public final int source; - public final int dest; - public Counter(Pump pump, int source, int dest) { this(pump, false, P_ALWAYS, source, dest); } - public Counter(Pump pump, boolean dl, int predicate, int source, int dest) { - super(pump, dl, predicate); - this.source = source; - this.dest = dest; + /** + * (Immutable) a truth table describing how to update a flag + * based on the value of other flags; it is the logical OR of + * a set of flag predicates. This class is immutable; all + * methods that alter the function return a new object. + */ + public static class FlagFunction implements Iterable { + + /** the function that always assigns zero */ + public static final FlagFunction ZERO = new FlagFunction(); + + /** the function that always assigns one */ + public static final FlagFunction ONE = ZERO.add(Predicate.FlagA).add(Predicate.NotFlagA); + + private final java.util.Set predicates; + + public Iterator iterator() { return predicates.iterator(); } + + private FlagFunction() { this(Collections.EMPTY_SET); } + private FlagFunction(java.util.Set set) { this.predicates = Collections.unmodifiableSet(set); } + + /** returns the function which is the logical OR of this function and ff */ + public FlagFunction add(FlagFunction ff) { + FlagFunction ret = this; + for(Predicate p : ff) ret = ret.add(p); + return ret; + } + + /** returns the function which is the logical OR of this function and p */ + public FlagFunction add(Predicate p) { + HashSet h = new HashSet(); + h.addAll(predicates); + switch(p) { + case FlagA: case NotFlagA: + case FlagB: case NotFlagB: + case FlagC: case NotFlagC: + break; + default: + throw new RuntimeException("invalid predicate in FlagFunction: " + p); + } + h.add(p); + return new FlagFunction(h); + } + + /** remove p from the set of terms which this function is the logical OR of */ + public FlagFunction remove(Predicate p) { + HashSet h = new HashSet(); + h.addAll(predicates); + h.remove(p); + return new FlagFunction(h); + } + + public String toString() { + if (predicates.isEmpty()) return "0"; + if (predicates.contains(Predicate.FlagA) && predicates.contains(Predicate.NotFlagA)) return "1"; + if (predicates.contains(Predicate.FlagB) && predicates.contains(Predicate.NotFlagB)) return "1"; + if (predicates.contains(Predicate.FlagC) && predicates.contains(Predicate.NotFlagC)) return "1"; + StringBuffer ret = new StringBuffer(); + boolean empty = true; + for(Predicate p : new Predicate[] { + Predicate.FlagA, Predicate.NotFlagA, + Predicate.FlagB, Predicate.NotFlagB, + Predicate.FlagC, Predicate.NotFlagC }) + if (predicates.contains(p)) { + if (!empty) ret.append("| "); + ret.append(p); + empty = false; + } + return ret.toString(); + } } + public String toString() { - if (source==LOOP_COUNTER && dest==DATA_LATCH) return "take loop counter;"; - StringBuffer ret = new StringBuffer(); - ret.append("load "); switch(dest) { - case LOOP_COUNTER: ret.append("loop"); break; - case REPEAT_COUNTER: ret.append("repeat"); break; - default: throw new RuntimeException("invalid"); - } - ret.append(" counter"); - if (source == STANDING) - ret.append(" with *"); - else if (source >= 0) { - ret.append(" with " + source); - } else if (source!=DATA_LATCH) { - throw new RuntimeException("invalid"); + case InnerLoopCounter: + switch(source) { + case Infinity: return super.toString()+"set ilc=*"; + case DataLatch: return super.toString()+"set ilc=data"; + case Immediate: return super.toString()+"set ilc="+immediate; + } + case OuterLoopCounter: + switch(source) { + case Decrement: return super.toString()+"set olc--"; + case DataLatch: return super.toString()+"set olc=data"; + case Immediate: return super.toString()+"set olc="+immediate; + } + case TAPL: return super.toString()+"set tapl="+path; + case Flags: return super.toString()+"set flags a="+newFlagA+" b="+newFlagB; + case DataLatch: return super.toString()+"set data="+immediate; } - ret.append(";"); - return ret.toString(); + throw new Error("impossible"); } - public boolean isLooping() { return true; } } - public static class Move extends PredicatedInstruction { - public final Destination dest; + /** shifts an immediate into the low-order bits of the data latch */ + public static class Shift extends Instruction { + public final BitVector immediate; + public Shift(Dock dock, boolean looping, Predicate predicate, BitVector immediate) { + super(dock, looping, predicate); + this.immediate = immediate; + } + public String toString() { return super.toString()+"shift "+immediate; } + } + /** all communication is performed with this instruction */ + public static class Move extends Instruction { + + /** if true, this instruction is vulnerable to torpedoes */ + public final boolean interruptible; + + /** if non-null, the path to load into the path latch */ + public final Path path; + + /** if true, a token will be consumed before execution */ public final boolean tokenIn; + + /** if true, data will be consumed before execution */ public final boolean dataIn; - public final boolean latch; - public final boolean dataOutDest; + + /** if true, the data consumed will be copied into the data latch */ + public final boolean latchData; + + /** if true, the data consumed will be copied into the path latch */ + public final boolean latchPath; + + /** if true, the value in the data latch will be transmitted (to the location in the path latch if at an output dock) */ public final boolean dataOut; + + /** if true, the a token will be transmitted to the location in the path latch */ public final boolean tokenOut; - public final boolean requeue; - public final boolean ignoreUntilLast; - - /** count=0 denotes a standing move */ - public Move(Pump pump, - boolean dl, - int predicate, - Destination dest, + + public Move(Dock dock, + boolean looping, + Predicate predicate, + boolean interruptible, + Path path, boolean tokenIn, boolean dataIn, - boolean latch, - boolean dataOutDest, + boolean latchData, + boolean latchPath, boolean dataOut, - boolean tokenOut, - boolean requeue, - boolean ignoreUntilLast) { - super(pump, dl, predicate); - this.dest = dest; + boolean tokenOut + ) { + super(dock, looping, predicate); + this.path = path; this.tokenIn = tokenIn; this.dataIn = dataIn; - this.latch = latch; - this.dataOutDest = dataOutDest; + this.latchData = latchData; + this.latchPath = latchPath; this.dataOut = dataOut; this.tokenOut = tokenOut; - this.requeue = requeue; - this.ignoreUntilLast = ignoreUntilLast; - if (pump.isInbox() && tokenIn && dataIn) - throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an inbox: " + this); - if (pump.isOutbox() && tokenOut && dataOut) - throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an outbox: " + this); - if (latch && !dataIn) - throw new RuntimeException("cannot have latch bit set without dataIn bit: " + this); + this.interruptible = interruptible; + if (dock != null && dock.isInputDock() && tokenIn && dataIn) + throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an input dock: " + this); + if (dock != null && dock.isOutputDock() && tokenOut && dataOut) + throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an output dock: " + this); + if (latchData && !dataIn) + throw new RuntimeException("cannot have latchData bit set without dataIn bit: " + this); + if (latchPath && !dataIn) + throw new RuntimeException("cannot have latchPath bit set without dataIn bit: " + this); + if (latchPath && path!=null) + throw new RuntimeException("cannot have latchPath and a non-null path: " + this); } public String toString() { - // FIXME - String ret = super.toString(); - boolean needcomma = false; - if (tokenIn) { ret += (needcomma ? ", " : "") + "wait"; needcomma = true; } - if (dataIn && latch) { - if (pump.isInbox()) - ret += (needcomma ? ", " : "") + "receive"; - else - ret += (needcomma ? ", " : "") + "take"; - needcomma = true; - } - if (dataIn && !latch) { ret += (needcomma ? ", " : "") + "dismiss"; needcomma = true; } - if (dataOut) { - if (pump.isInbox() || dest==null) - ret += (needcomma ? ", " : "") + "deliver"; - else - ret += (needcomma ? ", " : "") + "sendto "+dest; - needcomma = true; + StringBuffer ret = new StringBuffer(); + if (tokenIn) ret.append(", wait"); + if (dataIn) { + if (latchPath) ret.append(dock.isInputDock() ? ", collect path" : ", recv path"); + if (latchData) ret.append(dock.isInputDock() ? ", collect" : ", recv"); + if (!latchPath && !latchData) ret.append(", discard"); } - if (tokenOut) { ret += (needcomma ? ", " : "") + "notify "+dest; needcomma = true; } - return ret; - } - - public boolean isLooping() { return true; } - public boolean isRepeating() { return true; } - } - - public static class HalfLiteral extends PredicatedInstruction { - public final long literal; - public final boolean high; - public HalfLiteral(Pump pump, boolean dl, int predicate, long literal, int count, boolean high) { - super(pump, dl, predicate); - this.literal = literal; - this.high = high; + if (dataOut && dock.isInputDock()) ret.append(", deliver"); + if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send" : "sendto " + path); + if (tokenOut) ret.append(path==null ? ", token" : "tokento " + path); + String s = ret.toString(); + s = s.equals("") ? "nop" : s.substring(2); + if (interruptible) s = "[i] " + s; + return super.toString()+s; } - public boolean isRequeueing() { return true; } - public boolean isLooping() { return true; } } - public static class Literal extends PredicatedInstruction { - public final long literal; - public Literal(Pump pump, boolean dl, int predicate, long literal) { - super(pump, dl, predicate); - this.literal = literal; - } - public boolean isLooping() { return true; } - public boolean isRequeueing() { return true; } - public static boolean canRepresent(long literal) { - long il = literal; - long allones = ~(-1L << 37); - il = literal = literal & allones; - if (((il & ~(-1L << 19)) & allones) == 0) return true; - else if (((il | ~(-1L << 19)) & allones) == allones) return true; - else if (((il & (-1L << 19)) & allones) == 0) return true; - else if (((il | (-1L << 19)) & allones) == allones) return true; - return false; - } - } - - - public static class CodeBagDescriptor extends PredicatedInstruction { - // address of CBD, relative to address that this instruction was loaded from - public final long offset; - public final long size; - public CodeBagDescriptor(Pump pump, long offset, long size) { this(pump, false, P_ALWAYS, offset, size); } - public CodeBagDescriptor(Pump pump, boolean dl, int predicate, long offset, long size) { - super(pump, dl, predicate); - this.offset = offset; - this.size = size; - } - public String toString() { - String off = ""+offset; - if (offset > 0) off = "+"+off; - return "(CBD @"+off+"+"+size+"): sendto " + pump; - } + /** marks the end of a loop; closes the hatch */ + public static class Tail extends Instruction { + public Tail(Dock dock) { super(dock, false, Predicate.IgnoreOLC); } + public String toString() { return super.toString() + "tail;"; } } } diff --git a/src/edu/berkeley/fleet/api/Path.java b/src/edu/berkeley/fleet/api/Path.java new file mode 100644 index 0000000..5de20fb --- /dev/null +++ b/src/edu/berkeley/fleet/api/Path.java @@ -0,0 +1,29 @@ +package edu.berkeley.fleet.api; +import java.util.*; + +/** + * Represents a path through the switch fabric, from a Dock (source) + * to a Destination, plus an optional "signal" value. + */ +public abstract class Path { + + /** The start of the path. */ + public abstract Dock getSource(); + + /** The end of the path. */ + public abstract Destination getDestination(); + + /** The number of units of buffering along this path. */ + public abstract int getBufferingAmount(); + + /** A metric, in unspecified units, of the latency along this path; less is better. */ + public abstract int getLatencyMetric(); + + /** An additional quantity of bits to be transmitted along with a packet, or null if none. */ + public abstract BitVector getSignal(); + + public String toString() { + return getSource() + "->" + getDestination() + ((getSignal()==null||getSignal().length()==0)?"":(":"+getSignal())); + } + +} diff --git a/src/edu/berkeley/fleet/api/Predicate.java b/src/edu/berkeley/fleet/api/Predicate.java new file mode 100644 index 0000000..5392807 --- /dev/null +++ b/src/edu/berkeley/fleet/api/Predicate.java @@ -0,0 +1,19 @@ +package edu.berkeley.fleet.api; + +/** possible predicate field values */ +public enum Predicate { + Default, FlagA, NotFlagA, FlagB, NotFlagB, FlagC, NotFlagC, IgnoreOLC; + public String toString() { + switch(this) { + case Default: return ""; + case FlagA: return "a"; + case FlagB: return "b"; + case FlagC: return "c"; + case NotFlagA: return "!a"; + case NotFlagB: return "!b"; + case NotFlagC: return "!c"; + case IgnoreOLC: return "+"; + default: throw new Error("unknown predicate " + this); + } + } +} diff --git a/src/edu/berkeley/fleet/api/Pump.java b/src/edu/berkeley/fleet/api/Pump.java deleted file mode 100644 index a5e04ff..0000000 --- a/src/edu/berkeley/fleet/api/Pump.java +++ /dev/null @@ -1,34 +0,0 @@ -package edu.berkeley.fleet.api; -import java.util.*; - -public abstract class Pump { - - public Pump() { } - - /** the descriptive name of this pump (relative to its ship) */ - public abstract String getName(); - - /** return the Ship to which this Pump belongs */ - public abstract Ship getShip(); - - /** the maximum number of instructions we can put in the Pump instruction fifo, - * or Integer.MAX_VALUE if unbounded */ - public abstract int getInstructionFifoLength(); - - /** returns true if this is an inbox */ - public abstract boolean isInbox(); - - /** returns true if this is an outbox */ - public abstract boolean isOutbox(); - - /** get all destinations associated with this Pump; default implementation: just itself */ - public abstract Iterable getDestinations(); - - /** default implementation: the empty string */ - public String getDestinationName() { return ""; } - - /** return the Pump which is the destination of this Box's shortcut (if any) */ - public Pump getShortcut() { return null; } - - public abstract long resolveLiteral(String literal); -} diff --git a/src/edu/berkeley/fleet/api/Ship.java b/src/edu/berkeley/fleet/api/Ship.java index 0f207da..11e0f60 100644 --- a/src/edu/berkeley/fleet/api/Ship.java +++ b/src/edu/berkeley/fleet/api/Ship.java @@ -1,36 +1,28 @@ package edu.berkeley.fleet.api; -import java.io.*; import java.util.*; -public abstract class Ship { +/** A ship in a Fleet; each ship consists of a collection of Docks */ +public abstract class Ship implements Iterable { + + private final Fleet fleet; + + public Ship(Fleet fleet) { + this.fleet = fleet; + } /** return the Fleet that this Ship belongs to */ - public abstract Fleet getFleet(); + public Fleet getFleet() { return fleet; } - /** returns the type of the ship ("Fetch", "ALU", etc) */ + /** returns the type of the ship ("Fetch", "Alu", etc) */ public abstract String getType(); - /** return all pumps which feed this ship; order is NOT significant */ - public abstract Iterable getPumps(); - - public Pump getPump(String s) { - for(Pump b : getPumps()) - if (b.getName().equals(s)) - return b; - throw new RuntimeException("unknown port \""+getType()+"."+s+"\""); - } + public abstract Iterator iterator(); - public int getOrdinal() { - int ord = 0; - for(Ship s : getFleet()) { - if (s==this) return ord; - if (s.getType() != null && s.getType().equals(getType())) ord++; - } - throw new RuntimeException("inconsistency: Ship does not belong to its own Fleet!"); - } + /** returns the dock on this ship having name "name" */ + public abstract Dock getDock(String name); + + /** the docks of a given type are numbered; this returns the ordinal number of this dock */ + public abstract int getOrdinal(); public String toString() { return getType() + "[" + getOrdinal() + "]"; } - public long resolveLiteral(String literal) { - throw new RuntimeException("unknown literal \""+literal+"\" on ship "+this); - } } diff --git a/src/edu/berkeley/fleet/api/package.html b/src/edu/berkeley/fleet/api/package.html new file mode 100644 index 0000000..30815b1 --- /dev/null +++ b/src/edu/berkeley/fleet/api/package.html @@ -0,0 +1,11 @@ + +

+API for the FleetCode; see the class {@link edu.berkeley.fleet.api.Fleet} for a starting point and drill down from there. +

+ +

+Note: all Instruction objects and their constituent parts +(Path, Destination, etc) are immutable, +like java.lang.String. +

+ diff --git a/src/edu/berkeley/fleet/assembler/Main.java b/src/edu/berkeley/fleet/assembler/Main.java index 0b98b42..24c45cd 100644 --- a/src/edu/berkeley/fleet/assembler/Main.java +++ b/src/edu/berkeley/fleet/assembler/Main.java @@ -8,8 +8,8 @@ import java.util.*; public class Main { /** parse the assembly code on r, encode it for fleet, and write a binary on out */ - public static void assemble(Fleet fleet, Reader r, OutputStream out) throws Exception { - new Parser(fleet).parse(r, out); + public static Instruction[] assemble(Fleet fleet, Reader r) throws Exception { + return new Parser(fleet).parse(r); } -} \ No newline at end of file +} diff --git a/src/edu/berkeley/fleet/assembler/Parser.java b/src/edu/berkeley/fleet/assembler/Parser.java index 2cc226e..9359422 100644 --- a/src/edu/berkeley/fleet/assembler/Parser.java +++ b/src/edu/berkeley/fleet/assembler/Parser.java @@ -6,15 +6,29 @@ import edu.berkeley.sbp.misc.*; import edu.berkeley.sbp.meta.*; import edu.berkeley.sbp.util.*; import static edu.berkeley.fleet.util.BitManipulations.*; -import static edu.berkeley.fleet.api.Instruction.SetFlags.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.api.Instruction.Set; +import static edu.berkeley.fleet.api.Instruction.*; +import static edu.berkeley.fleet.api.Instruction.Set.*; +import static edu.berkeley.fleet.api.Predicate.*; +import edu.berkeley.fleet.two.*; +import edu.berkeley.fleet.fpga.*; +import edu.berkeley.fleet.interpreter.*; import java.util.*; import java.io.*; + /** * @author Adam Megacz */ public class Parser { + private static final BitVector SIGNAL_ZERO = new BitVector(1); + private static final BitVector SIGNAL_ONE = new BitVector(1); + static { + SIGNAL_ONE.set(0,true); + } + Parser(Fleet fleet) { expect = new ArrayList(); this.fleet = fleet; @@ -50,57 +64,61 @@ public class Parser { return grammar; } - Tree parse(Reader r) throws Exception { - return new CharParser(getGrammar()).parse(new CharInput(r)).expand1(); + // FIXME: this ought to be cached via serialization, I think + private static CharParser cp = null; + Tree parseIt(Reader r) throws Exception { + if (cp==null) + cp = new CharParser(getGrammar()); + CharInput ci = new CharInput(r); + Forest f = cp.parse(ci); + return f.expand1(); } - public void parse(Reader r, OutputStream out) throws Exception { + public Instruction[] parse(Reader r) throws Exception { // this needs to be "code bag zero" CodeBag baseCodeBag = new CodeBag(); CodeBag rootCodeBag = new CodeBag(); skip = false; - baseCodeBag.add(new Instruction.CodeBagDescriptor(null, rootCodeBag.getFakeAddress(), 1)); - walk((Tree)parse(r), rootCodeBag); - if (fleet instanceof edu.berkeley.fleet.fpga.Fpga) - ((edu.berkeley.fleet.fpga.Fpga)fleet).dumpFabric(true); + Dock dock = null; + if (fleet instanceof Fpga) { + dock = ((Fpga)fleet).getUniversalSource(); + } else { + dock = ((Interpreter)fleet).getUniversalSource(); + } + baseCodeBag.add(new Set(dock, false, IgnoreOLC, SetDest.DataLatch, (rootCodeBag.getFakeAddress())), true); + Tree parsed = (Tree)parseIt(r); + walk(parsed, rootCodeBag); // map from arbitrary identifiers to actual addresses int[] codeBagMap = new int[codeBags.size()]; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(baos); int count = 0; for(int i=0; i ret = new ArrayList(); for(int i=0; i t) { - if (!"Pump".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null; + Path path(Dock dock, Tree t) { + if (!"Dock".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null; + t = t.child(0); String shipName = name(t.child(0)); String portName = name(t.child(1)); String subPort = t.size()<3 ? null : name(t.child(2)); Ship ship = shipMap.get(shipName); if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\""); Destination ret = null; - Pump bb = null; - for(Pump b : ship.getPumps()) + Dock bb = null; + for(Dock b : ship) if (b.getName().equals(portName)) { bb = b; } if (bb==null) throw new RuntimeException("no such pump \""+portName+"\""); if (subPort==null) subPort=""; - for(Destination d : bb.getDestinations()) - if (d.getDestinationName().equals(subPort)) - return d; - if (ret==null) - throw new RuntimeException("no such pump \""+portName+"\" on ships of type \""+ship.getType()+"\""); - return ret; + if (":i".equals(t.head())) return dock.getPath(bb.getInstructionDestination(),SIGNAL_ZERO); + if (":1".equals(t.head())) return dock.getPath(bb.getDataDestination(),SIGNAL_ONE); + if (":0".equals(t.head())) return dock.getPath(bb.getDataDestination(),SIGNAL_ZERO); + return dock.getPath(bb.getDataDestination(),SIGNAL_ZERO); } - Pump pump(Tree t) { - if (!"Pump".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) + Dock dock(Tree t) { + if (!"Dock".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) throw new RuntimeException(t+""); String shipName = name(t.child(0)); String portName = name(t.child(1)); Ship ship = shipMap.get(shipName); if (ship==null) throw new RuntimeException("no such ship \""+shipName+"\""); - Pump bb = null; - for(Pump b : ship.getPumps()) + Dock bb = null; + for(Dock b : ship) if (b.getName().equals(portName)) return b; throw new RuntimeException("no such pump \""+portName+"\""); @@ -234,30 +251,47 @@ public class Parser { break; } } - Pump chosenport = chosenship.getPump(portName); + if (chosenship==null) throw new RuntimeException("no ships of type " + shipType); + Dock chosenport = chosenship.getDock(portName); Tree specs = t.child(2); long literal = 0; for(int i=0; i t) { - int ret = 0; + private static long resolveLiteral(Dock dd, String s) { + long val = 0; + long ret = 0; + boolean hasval = false; + if (s.indexOf('=') != -1) { + val = Long.parseLong(s.substring(s.indexOf('=')+1)); + s = s.substring(0, s.indexOf('=')); + hasval = true; + } + ShipDescription.Constant c = ((FleetTwoDock)dd).getConstant(s); + if (c==null) throw new RuntimeException("no constant " + s + " on dock " + dd); + ret |= c.setbits; + ret &= ~c.clearbits; + if (hasval) + ret |= ((~(0xffffffffffffffffL << c.numberWidth)) & val) << c.numberOffset; + return ret; + } + + private static FlagFunction parseFlags(Tree t) { + FlagFunction ret = FlagFunction.ZERO; for(int i=0; i statement : tq.child(0)) fillCodeBag(statement, cb2); - cb.add(new Instruction.CodeBagDescriptor(pump, dl, predicate, cb2.getFakeAddress(), 0)); + cb.add(new Set(dock, looping, predicate, SetDest.DataLatch, (cb2.getFakeAddress())), true); continue OUTER; } else if (tt.child(0).head().equals("Name")) { String refname = name(tt.child(0)); CodeBag cb2 = getCodeBag(refname); - cb.add(new Instruction.CodeBagDescriptor(pump, dl, predicate, cb2.getFakeAddress(), 0)); + cb.add(new Set(dock, looping, predicate, SetDest.DataLatch, (cb2.getFakeAddress())), true); continue OUTER; } else if (tt.child(0).head().equals("[")) { literal = parseSSL(tt.child(0)); @@ -345,12 +378,15 @@ public class Parser { count = 0; } - if (Instruction.Literal.canRepresent(literal)) { - cb.add(new Instruction.Literal(pump, dl, predicate, literal)); + + if (InstructionEncoder.isSmallEnoughToFit(literal)) { + cb.add(new Set(dock, looping, predicate, SetDest.DataLatch, (literal))); } else { - cb.add(new Instruction.HalfLiteral(pump, dl, predicate, getField(36, 19, literal), count, true)); - cb.add(new Instruction.HalfLiteral(pump, dl, predicate, getField(18, 0, literal), count, false)); + // FIXME bitwidth hardwired! + cb.add(new Shift(dock, looping, predicate, new BitVector(37).set(getField(36, 19, literal)))); + cb.add(new Shift(dock, looping, predicate, new BitVector(37).set(getField(18, 0, literal)))); } + continue; } Tree ttx = null; @@ -365,7 +401,7 @@ public class Parser { } tt = tt.child(0); if (tt.head().equals("[*]")) { - cb.add(new Instruction.Counter(pump, dl, predicate, Instruction.Counter.STANDING, Instruction.Counter.REPEAT_COUNTER)); + cb.add(new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.Infinity)); //count = 0; requeue = false; } else if (tt.head().equals("int")) { @@ -377,31 +413,29 @@ public class Parser { boolean latch = false; boolean dataOut = false; boolean tokenOut = false; - boolean dataOutDest = false; + boolean dispatch = false; boolean localLiteral = false; boolean ignoreUntilLast = false; long literal = 0; - Destination dest = null; + Path path = null; for(int i=0; i { public long address = -1; public final String name; + private HashSet isCBD = new HashSet(); public CodeBag() { codeBags.add(this); this.name = "root"; } public CodeBag(String name) { codeBags.add(this); codeBagsByName.put(name, this); this.name = name; } public long getFakeAddress() { return codeBags.indexOf(this); } public boolean equals(Object o) { return this==o; } + public void add(Instruction i, boolean isCBD) { + if (isCBD) this.isCBD.add(size()); + add(i); + } } // hideous hack @@ -431,4 +470,11 @@ public class Parser { if (negative) val = -1L * val; return val; } + /** + * This interface marks Fleets which can create ships on the fly, like the fleeterpreter; + * if available, the parser will use this interface to create ships out of #ship definitions. + */ + public static interface FleetWithDynamicShips { + public Ship createShip(String shiptype, String shipname); + } } diff --git a/src/edu/berkeley/fleet/assembler/fleet.g b/src/edu/berkeley/fleet/assembler/fleet.g index 1d6a60b..e560fa8 100644 --- a/src/edu/berkeley/fleet/assembler/fleet.g +++ b/src/edu/berkeley/fleet/assembler/fleet.g @@ -9,24 +9,24 @@ Program:: = Directives CodeBagBody /ws Directives:: = Directive */ ws CodeBagBody:: = (Fiber | CodeBagDef) */ ws CodeBagDef:: = CodeBagName ":" "{" CodeBagBody "}" /ws -Fiber:: = Pump ":" Instructions /ws +Fiber:: = Dock ":" Instructions /ws -// FIXME: should not have predicates on clog/unclog/kill/massacre +// FIXME: should not have predicates on tail/untail/kill/massacre Instructions:: = Instruction +/ ws -Instruction:: = DL Predicate InstructionX -DL = "" | ^"[dl]" ws -Predicate = "" | ^"[a]" ws | ^"[b]" ws | ^"[z]" ws -InstructionX = ^"unclog" ";" /ws - | ^"clog" ";" /ws - | ^"massacre" ";" /ws - | ^"kill" ";" /ws +Instruction:: = (Tags:: Tag*) InstructionX +Tag = ^"[a]" ws | ^"[b]" ws | ^"[c]" ws + | ^"[!a]" ws | ^"[!b]" ws | ^"[!c]" ws + | ^"[+]" ws + | ^"[I]" ws + | ^"[L]" ws +InstructionX = ^"tail" ";" /ws | "take" ^"loop" "counter" ";" /ws | ^"load" (^"loop"|^"repeat") ws "counter" ";" /ws | "load" (^"loop"|^"repeat") ws "counter" ^"with" int ";" /ws | "load" (^"loop"|^"repeat") ws "counter" "with" ^"*" ";" /ws + | "load" ^"tapl" "with" Destination ";" /ws | ^"decrement" "loop" "counter" ";" /ws | ^"setflags" "a" "=" Flags "," "b" "=" Flags ";" /ws - | ^"kill" int ";" /ws | ^"literal" Literal RequeueCount ";" /ws | RepeatCount Commands RequeueCount ^";" /ws RepeatCount = "" | ^"[*]" | "[" int "]" @@ -38,19 +38,19 @@ Flag = ^"0" | ^"1" | ^"a" | ^"b" - | ^"s" - | ^"z" + | ^"c" | ^"!a" | ^"!b" - | ^"!s" - | ^"!z" + | ^"!c" Commands:: = Command +/ (ws "," ws) Command = ^"wait" | ^"nop" | ^"discard" | ^"recieve" + | ^"recv" | ^"take" + | ^"collect" | ^"deliver" | ^"send" | ^"sendto" Destination /ws @@ -58,19 +58,22 @@ Command = ^"wait" | ^"notifyLast" Destination /ws Literal = int - | ShipType "." PortName ^"[" Constants "]" + | ShipType "." DockName ^"[" Constants "]" | CodeBagName | "{" CodeBagBody "}" /ws -Pump:: = ShipName "." PortName -Destination:: = ShipName "." PortName +Dock:: = ShipName "." DockName +Destination:: = (ShipName ^"." DockName) + | (ShipName "." DockName ^":i") + | (ShipName "." DockName ^":0") + | (ShipName "." DockName ^":1") Constants:: = Constant +/ "," Constant:: = [a-zA-Z0-9=_\-]++ CodeBagName = UpcaseWord ShipType = UpcaseWord ShipName = DowncaseWord -PortName = DowncaseWord +DockName = DowncaseWord Word = UpcaseWord | DowncaseWord UpcaseWord = Name:: [A-Z] ("":: [A-Za-z0-9_]**) DowncaseWord = Name:: [a-z] ("":: [A-Za-z0-9_]**) diff --git a/src/edu/berkeley/fleet/doc/Constant.java b/src/edu/berkeley/fleet/doc/Constant.java deleted file mode 100644 index f6d04a0..0000000 --- a/src/edu/berkeley/fleet/doc/Constant.java +++ /dev/null @@ -1,36 +0,0 @@ -package edu.berkeley.fleet.doc; - -import java.io.*; -import java.util.*; - -public class Constant { - - long setbits = 0; - long clearbits = 0; - boolean signExtend = false; - int numberOffset = 0; - int numberWidth = 0; - - public Constant(String s) { - if (s.startsWith("0x")) { - setbits = Long.parseLong(s.substring(2), 16); - clearbits = ~setbits; - } else if (s.length() == 37) { - for(int i=36; i>=0; i--) { - char c = s.charAt(36-i); - switch(c) { - case '0': clearbits |= (1< { - - public String getName() { return name; } - public boolean isInbox() { return inbox; } - public boolean isOutbox() { return !inbox; } - public boolean isLeft() { return left; } - public boolean tokensOnly() { return tokenOnly; } - public String getShortcut() { return shortcut; } - public Iterator iterator() { return destinations.iterator(); } - - // private ////////////////////////////////////////////////////////////////////////////// - - private final ShipDescription ship; - private final String shortcut; - private final String name; - private final boolean inbox; - private final boolean tokenOnly; - private final boolean left; - private ArrayList destinations = new ArrayList(); - - // FIXME - public HashMap constants = new HashMap(); - - PumpDescription(ShipDescription ship, String name, boolean tokenOnly, boolean left, boolean inbox) { - this(ship, name, tokenOnly, inbox, left, null); - } - PumpDescription(ShipDescription ship, String name, boolean tokenOnly, boolean left, boolean inbox, String shortcut) { - this.left = left; - this.ship = ship; - this.name = name; - this.inbox = inbox; - this.tokenOnly = tokenOnly; - this.shortcut = shortcut; - ship.add(this); - } - - void addDest(String dest) { destinations.add(dest); } - - public Constant getConstant(String name) { - Constant ret = constants.get(name); - if (ret == null) ret = ship.getConstant(name); - return ret; - } - - public long resolveLiteral(String s) { - long val = 0; - long ret = 0; - boolean hasval = false; - if (s.indexOf('=') != -1) { - val = Long.parseLong(s.substring(s.indexOf('=')+1)); - s = s.substring(0, s.indexOf('=')); - hasval = true; - } - Constant c = getConstant(s); - if (c==null) throw new RuntimeException("no constant " + s + " on pump " + this); - ret |= c.setbits; - ret &= ~c.clearbits; - if (hasval) - ret |= ((~(0xffffffffffffffffL << c.numberWidth)) & val) << c.numberOffset; - return ret; - } -} diff --git a/src/edu/berkeley/fleet/doc/ShipDescription.java b/src/edu/berkeley/fleet/doc/ShipDescription.java deleted file mode 100644 index 4a4c467..0000000 --- a/src/edu/berkeley/fleet/doc/ShipDescription.java +++ /dev/null @@ -1,118 +0,0 @@ -package edu.berkeley.fleet.doc; - -import java.io.*; -import java.util.*; - -/** the Java representation of a .ship file */ -public class ShipDescription implements Iterable { - - public String getName() { return name; } - public String getSection(String sectionName) { return sections.get(sectionName); } - public Iterator iterator() { return pumps.iterator(); } - - public ShipDescription(String name, BufferedReader r) throws IOException { - if (name.endsWith(".ship")) - name = name.substring(0, name.length() - ".ship".length()); - while(name.indexOf('/') != -1) name = name.substring(name.indexOf('/')+1); - this.name = name; - String sectionName = null; - StringBuffer sb = new StringBuffer(); - while(true) { - String s = r.readLine(); - if (s==null || s.startsWith("==")) { - if (sectionName != null) sections.put(sectionName, sb.toString()); - if (s==null) break; - sb = new StringBuffer(); - sectionName = s.trim(); - while(sectionName.startsWith("=")) - sectionName = sectionName.substring(1); - while(sectionName.endsWith("=")) - sectionName = sectionName.substring(0, sectionName.length()-1); - sectionName = sectionName.trim().toLowerCase(); - continue; - } - sb.append(s+"\n"); - } - for(String s : sections.keySet()) - processSection(s); - } - - // private ////////////////////////////////////////////////////////////////////////////// - - private String name; - private String texDocumentation; - - // must keep proper ordering for FPGA (FIXME: should alphabetize when synthesizing) - private ArrayList pumps = new ArrayList(); - - private HashMap sections = new HashMap(); - - // FIXME - public HashMap constants = new HashMap(); - - public Constant getConstant(String name) { - return constants.get(name); - } - - private void processSection(String section) throws IOException { - if (section.equals("")) { - BufferedReader br = new BufferedReader(new StringReader(sections.get(section))); - for(String s = br.readLine(); s != null; s = br.readLine()) { - if (s.trim().length()==0) continue; - String key = s.substring(0, s.indexOf(':')).trim(); - String val = s.substring(s.indexOf(':')+1).trim(); - if (key.toLowerCase().equals("ship")) - name = val.trim(); - } - } else if (section.equals("constants")) { - BufferedReader br = new BufferedReader(new StringReader(sections.get(section))); - for(String s = br.readLine(); s != null; s = br.readLine()) { - if (s.indexOf(':')==-1) continue; - String key = s.substring(0, s.indexOf(':')).trim(); - if (key.startsWith("constant")) { - String constname = key.substring("constant".length()+1).trim(); - String val = s.substring(s.indexOf(':')+1).trim(); - constants.put(constname, new Constant(val)); - } - } - } else if (section.equals("ports")) { - BufferedReader br = new BufferedReader(new StringReader(sections.get(section))); - boolean rightSide = false; - PumpDescription p = null; - for(String s = br.readLine(); s != null; s = br.readLine()) { - if (s.trim().length()==0) { rightSide = true; continue; } - - String key = s.substring(0, s.indexOf(':')).trim(); - boolean tokenOnly = false; - boolean inbox = false; - key = key.replaceAll(" +", " "); - if (key.equals("token in")) { tokenOnly = true; inbox = true; } - else if (key.equals("token out")) { tokenOnly = true; inbox = false; } - else if (key.equals("data in")) { tokenOnly = false; inbox = true; } - else if (key.equals("data out")) { tokenOnly = false; inbox = false; } - else if (key.equals("in")) { tokenOnly = false; inbox = true; } - else if (key.equals("out")) { tokenOnly = false; inbox = false; } - else if (key.startsWith("constant")) { - String constname = key.substring("constant".length()+1).trim(); - String val = s.substring(s.indexOf(':')+1).trim(); - p.constants.put(constname, new Constant(val)); - continue; - } else if (key.startsWith("shortcut to")) { - continue; - } - else throw new RuntimeException("unknown port type: \""+key+"\""); - - p = null; - String val = s.substring(s.indexOf(':')+1).trim(); - String boxname = val.indexOf('.') != -1 ? val.substring(0, val.indexOf('.')) : val; - String dest = val.indexOf('.') != -1 ? val.substring(val.indexOf('.')+1) : ""; - for (PumpDescription b : pumps) - if (b.getName().equals(boxname)) { p = b; break; } - if (p==null) p = new PumpDescription(this, boxname, tokenOnly, inbox, !rightSide); - p.addDest(dest); - } - } - } - - void add(PumpDescription b) { pumps.add(b); } -} \ No newline at end of file diff --git a/src/edu/berkeley/fleet/fpga/Client.java b/src/edu/berkeley/fleet/fpga/Client.java index 0ff6da1..e3cc39f 100644 --- a/src/edu/berkeley/fleet/fpga/Client.java +++ b/src/edu/berkeley/fleet/fpga/Client.java @@ -1,15 +1,20 @@ package edu.berkeley.fleet.fpga; +import static edu.berkeley.fleet.util.BitManipulations.*; import edu.berkeley.fleet.api.*; import java.io.*; import java.net.*; import java.util.*; import java.util.concurrent.*; +import static edu.berkeley.fleet.api.Instruction.Set.*; +import static edu.berkeley.fleet.api.Predicate.*; +import static edu.berkeley.fleet.api.Instruction.*; + public class Client extends FleetProcess { private Socket s; - private BlockingQueue queue = new LinkedBlockingQueue(); + private BlockingQueue queue = new LinkedBlockingQueue(); public void invokeInstruction(Instruction i) { throw new RuntimeException("not implemented"); @@ -21,11 +26,14 @@ public class Client extends FleetProcess { return val; } - public long readWord() { + public Dock getDebugInputDock() { + throw new RuntimeException(); + } + public BitVector readWord() { if (isTerminated()) throw new RuntimeException("this fleet has been terminated"); try { - return signExtend(queue.take()); + return queue.take(); } catch (InterruptedException e) { throw new RuntimeException(e); } } @@ -35,24 +43,95 @@ public class Client extends FleetProcess { } catch (Exception e) { e.printStackTrace(); } } - public Client(String bitfile, byte[] program) throws IOException { + public Client(String bitfile, byte[] program) throws Exception { s = new Socket(InetAddress.getByName("goliath.megacz.com"), 3133); - OutputStream os = s.getOutputStream(); + OutputStream os = new BufferedOutputStream(s.getOutputStream()); PrintWriter pw = new PrintWriter(new OutputStreamWriter(os)); pw.print(Server.pass_string+" "+bitfile+"\n"); pw.flush(); - int numinstrs = (program.length / 6); - os.write((numinstrs >> (5*8)) & 0xff); - os.write((numinstrs >> (4*8)) & 0xff); - os.write((numinstrs >> (3*8)) & 0xff); - os.write((numinstrs >> (2*8)) & 0xff); - os.write((numinstrs >> (1*8)) & 0xff); - os.write((numinstrs >> (0*8)) & 0xff); + + Fpga fpga = new Fpga(); + ByteArrayOutputStream newp = new ByteArrayOutputStream(); + DataOutputStream newpd = new DataOutputStream(newp); + long startcbd = 0; + + Dock inAddrWrite = null; + Dock inDataWrite = null; + Dock inCBD = null; + Dock out = null; + Dock debugIn = null; + Dock ihorn = null; + + for(Ship ship : fpga) { + if ("Memory".equals(ship.getType()) && ship.getOrdinal()==0) { + inAddrWrite = ship.getDock("inAddrWrite"); + inDataWrite = ship.getDock("inDataWrite"); + inCBD = ship.getDock("inCBD"); + out = ship.getDock("out"); + ihorn = ship.getDock("outIhorn"); + } + if ("Debug".equals(ship.getType()) && ship.getOrdinal()==0) { + debugIn = ship.getDock("in"); + } + } + + for(int i=0; i> 6) & ~(-1L << 10); + long size = (lit >> 0) & ~(-1L << 6); + startcbd = (offset << 6) | size; + size = 0; + offset = 0; + inst = new Instruction.Shift(fpga.getUniversalSource(), false, IgnoreOLC, new BitVector(fpga.getWordWidth()).set(0)); + } else { + if (fpga.writeInstruction(fpga.getUniversalSource(), inst) != lit) + throw new RuntimeException("no match: " + inst + " @"+(i/6)+"\n"+Long.toString(lit,16)+ + "\n"+Long.toString(fpga.writeInstruction(fpga.getUniversalSource(), inst),16)); + } + //fpga.writeInstruction(newpd, fpga.getUniversalSource(), inst); + } + + for(int i=0; i> i) & 1L)!=0); + queue.put(bs); } } catch (SocketException e) { } catch (Exception e) { throw new RuntimeException(e); @@ -75,7 +157,7 @@ public class Client extends FleetProcess { } }.start(); } - + /* public static void main(String[] args) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; @@ -93,4 +175,10 @@ public class Client extends FleetProcess { System.err.println(); } } -} \ No newline at end of file + */ + public void dispatchInstruction(Instruction i) { throw new RuntimeException(); } + private static Move discard(Dock dock) { return new Move(dock, false, IgnoreOLC, false, null, false, true, false, false, false, false); } + private static Move deliver(Dock dock) { return new Move(dock, false, IgnoreOLC, false, null, false, false, false, false, true, false); } + private static Move wait(Dock dock) { return new Move(dock, false, IgnoreOLC, false, null, true, false, false, false, false, false); } + private static Move sendto(Dock dock, Path path) { return new Move(dock, false, IgnoreOLC, false, path, false, false, false, false, true, false); } +} diff --git a/src/edu/berkeley/fleet/fpga/FabricElement.java b/src/edu/berkeley/fleet/fpga/FabricElement.java new file mode 100644 index 0000000..2893d20 --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/FabricElement.java @@ -0,0 +1,25 @@ +package edu.berkeley.fleet.fpga; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; +import static edu.berkeley.fleet.verilog.Verilog.*; + + +public interface FabricElement { + + public FpgaPath getPath(FabricElement dest, BitVector signal); + + public void addInput(FabricElement in, Module.Port inPort); + public void addOutput(FabricElement out, Module.Port outPort); + + public Module.Port getOutputPort(); + public Module.Port getInputPort(); +} diff --git a/src/edu/berkeley/fleet/fpga/FifoModule.java b/src/edu/berkeley/fleet/fpga/FifoModule.java new file mode 100644 index 0000000..0367c86 --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/FifoModule.java @@ -0,0 +1,34 @@ +package edu.berkeley.fleet.fpga; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; +import static edu.berkeley.fleet.verilog.Verilog.*; + +public class FifoModule extends Module { + public FifoModule(int len) { + super("fifo"+len); + Module.SourcePort in = createInputPort("in", WIDTH_PACKET); + Module.SinkPort out = createOutputPort("out", WIDTH_PACKET, ""); + Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len]; + if (len==0) { + new Event(new Object[] { in, out }, + new Action[] { in, out, new AssignAction(out, in) }); + } else { + Module fifo0 = new FifoModule(0); + for(int i=0; i<=len; i++) { + if (i shiplist = new ArrayList(); - public HashMap ships = new HashMap(); - public Iterator iterator() { return (Iterator)(Object)shiplist.iterator(); } +public class Fpga extends Fleet { - private String bitfile; + public Ship getShip(String type, int ordinal) { + for(Ship s : this) + if (s.getType().equals(type)) + if (ordinal-- < 0) + return s; + return null; + } - public static void main(String[] s) throws Exception { - new Fpga().dumpFabric(false); + public int getWordWidth() { return 37; } + private static final BitVector SIGNAL_ZERO = new BitVector(1); + private static final BitVector SIGNAL_ONE = new BitVector(1); + static { + SIGNAL_ONE.set(0,true); } - public Fpga() { this("gaspified.bit"); } - public Fpga(String bitfile) { - this.bitfile = bitfile; - createShip("Debug", "debug"); - createShip("Memory", "memory"); - createShip("Memory", "memory2"); // need this to avoid a bug + public Module top; + public FabricElement top_horn; - createShip("Fifo", "fifo1"); - createShip("Fifo", "fifo2"); - createShip("Alu2", "alu2a"); - createShip("BitFifo", "bitfifo"); - createShip("Rotator", "rotator"); - // above is the minimal ship set needed to run the regression suite, excluding "ships" tests - createShip("Alu1", "alu1"); - createShip("Lut3", "lut3"); - createShip("Alu3", "alu3"); + public LinkedHashMap ships = new LinkedHashMap(); + public Iterator iterator() { return (Iterator)(Object)ships.values().iterator(); } - /* - createShip("Stack", "Stack"); - createShip("Fifo", "fifo3"); - createShip("Choice", "Choice"); - */ - // above is the minimal ship set needed to run the regression suite, including "ships" tests - - // below are extra bonus ships - /* - createShip("Alu2", "alu2b"); - createShip("Alu2", "alu2c"); - createShip("Alu2", "alu2d"); - createShip("Fifo", "fifo4"); - createShip("Memory", "Memory"); - createShip("Choice", "Choice"); - createShip("Choice", "Choice"); - createShip("Choice", "Choice"); - */ - dumpFabric(true); - } + public static void main(String[] s) throws Exception { + String prefix = s[0]; - public Ship createShip(String type, String name) { - try { - ShipDescription sd = new ShipDescription(name, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship")))); - FpgaShip ship = new FpgaShip(this, name, type, sd); - ships.put(name, ship); - shiplist.add(ship); - return ship; - } catch (IOException e) { throw new RuntimeException(e); } + new FunnelModule().dump(prefix); + new HornModule().dump(prefix); + + new FifoModule(0).dump(prefix); + new FifoModule(4).dump(prefix); + new FifoModule(8).dump(prefix); + new FpgaDock.DockModule(false).dump(prefix); + new FpgaDock.DockModule(true).dump(prefix); + + Module top = new Module("root"); + new Fpga(top).top.dump(prefix); } - public FleetProcess run(final byte[] instructions) { + public FleetProcess run(Instruction[] instructions) { try { - return new Client(bitfile, instructions); - } catch (IOException e) { throw new RuntimeException(e); } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + for(Instruction i : instructions) + writeInstruction(dos, getUniversalSource(), i); + dos.flush(); + return new Client("none", baos.toByteArray()); + } catch (Exception e) { throw new RuntimeException(e); } } - public void dumpFabric(boolean quiet) { - // FIXME: this is really ugly: the order of port declarations in - // the XXXShip.java file must match the order in the .balsa file! - - ArrayList instructionports = new ArrayList(); - for(FpgaShip ship : shiplist) - for(Pump port : ship.getPumps()) - if (!((FpgaPump)port).special()) - instructionports.add(port); - FabricTree instructions = - new FabricTree((FpgaPump[])instructionports.toArray(new FpgaPump[0]), - "ihorn", - "instruction"); - - ArrayList inputports = new ArrayList(); - for(FpgaShip ship : shiplist) - for(Pump port : ship.getPumps()) - if (!((FpgaPump)port).special()) - inputports.add(port); - FabricTree inputs = - new FabricTree((FpgaPump[])inputports.toArray(new FpgaPump[0]), - "horn", - "dest"); - - ArrayList outputports = new ArrayList(); - for(FpgaShip ship : shiplist) - for(Pump port : ship.getPumps()) - if (!((FpgaPump)port).special() || ((FpgaPump)port).dhorn()) - outputports.add(port); - FabricTree outputs = - new FabricTree((FpgaPump[])outputports.toArray(new FpgaPump[0]), - "funnel", - "source"); - - ArrayList ihornports = new ArrayList(); - for(FpgaShip ship : shiplist) - for(Pump port : ship.getPumps()) - if (((FpgaPump)port).ihorn()) - ihornports.add(port); - FabricTree ihorns = - new FabricTree((FpgaPump[])ihornports.toArray(new FpgaPump[0]), - "funnel", - "ihorn"); - - if (quiet) return; - System.out.println("`include \"macros.v\""); - System.out.println("module fabric(clk, rst, data_Memory0_command_r, data_Memory0_command_a, data_Memory0_command,"); - System.out.println(" data_Debug0_out_r, data_Debug0_out_a, data_Debug0_out);"); - System.out.println(" input clk;"); - System.out.println(" input rst;"); - System.out.println(" input data_Memory0_command_r;"); - System.out.println(" output data_Memory0_command_a;"); - System.out.println(" output data_Debug0_out_r;"); - System.out.println(" input data_Debug0_out_a;"); - System.out.println(" output [(`PACKET_WIDTH-1):0] data_Debug0_out;"); - System.out.println(" input [(`PACKET_WIDTH-1):0] data_Memory0_command;"); - //System.out.println(" wire [(`INSTRUCTION_WIDTH-1):0] data_Memory0_ihorn;"); - //System.out.println(" wire [(`PACKET_WIDTH-1):0] data_Memory0_dhorn;"); - System.out.println(); - - System.out.println(); - - instructions.dumpChannels(true); - outputs.dumpChannels(true); - inputs.dumpChannels(true); - ihorns.dumpChannels(true); - for(FpgaShip ship : shiplist) - for(Pump port : ship.getPumps()) - if (!((FpgaPump)port).special() || ((FpgaPump)port).dhorn()) - System.out.println(" wire [(`PACKET_WIDTH-1):0] data_" - +getUniqueName(ship)+"_"+port.getName()+";"); - - System.out.println("wire [(`PACKET_WIDTH-1):0] ihornleft;"); - - System.out.println(""); - instructions.dumpChannels(false); - System.out.println(""); - outputs.dumpChannels(false); - System.out.println(""); - inputs.dumpChannels(false); - System.out.println(""); - ihorns.dumpChannels(false); - System.out.println(""); - for(FpgaShip ship : shiplist) { - System.out.print(ship.getType().toLowerCase()); - System.out.print(" "); - System.out.print("krunk"+(krunk++)); - System.out.print("(clk, rst, "); - boolean first = true; - for(Pump port : ship.getPumps()) { - if (!first) System.out.print(", "); - first = false; - String prefix = "data_"; - if (((FpgaPump)port).ihorn()) prefix = "ihorn_"; - if (((FpgaPump)port).dhorn()) prefix = "source_"; - System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_r, "); - System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()+"_a, "); - System.out.print(prefix+getUniqueName(port.getShip())+"_"+port.getName()); - System.out.print(" "); - } - System.out.println(");"); - - for(Pump port : ship.getPumps()) { - if (((FpgaPump)port).special()) continue; - if (((FpgaPump)port).inbox) { - System.out.print("inbox"); - } else { - System.out.print("outbox"); - } - System.out.print(" krunk"+(krunk++)+"(clk, rst, "); - System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, "); - System.out.print("instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, "); - System.out.print("`packet_data(instruction_"+getUniqueName(port.getShip())+"_"+port.getName()+"), "); - System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, "); - System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, "); - System.out.print("dest_"+getUniqueName(port.getShip())+"_"+port.getName()+", "); - System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, "); - System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, "); - System.out.print("source_"+getUniqueName(port.getShip())+"_"+port.getName()+", "); - System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_r, "); - System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()+"_a, "); - System.out.print("data_"+getUniqueName(port.getShip())+"_"+port.getName()); - System.out.print(");"); - System.out.println(); - } - - } + // Setup ////////////////////////////////////////////////////////////////////////////// - System.out.println("funnel ihornfun(clk, rst, "+ - " ihornleft_r, ihornleft_a, ihornleft,"+ - " ihorn_r, ihorn_a, ihorn,"+ - " source_r, source_a, source);"); - System.out.println("horn tophorn(clk, rst, "+ - " ihornleft_r, ihornleft_a, ihornleft,"+ - " instruction_r, instruction_a, instruction,"+ - " dest_r, dest_a, dest);"); - /* - System.out.println("assign instruction_r = ihorn_r;"); - System.out.println("assign ihorn_a = instruction_a;"); - System.out.println("assign instruction = ihorn;"); - System.out.println("assign dest_r = source_r;"); - System.out.println("assign source_a = dest_a;"); - System.out.println("assign dest = source;"); - */ - System.out.println("endmodule"); + public Ship createShip(String type, String name) throws IOException { + ShipDescription sd = new ShipDescription(type, new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+type+".ship")))); + FpgaShip ship = new FpgaShip(this, sd); + ships.put(name, ship); + return ship; } - private static class FabricTree { - int master_idx = 1; - String prefix; - Node root; - public void dumpChannels(boolean decl) { root.dumpChannels(0, decl); } - public FabricTree(FpgaPump[] ports, String component, String prefix) { - this.prefix = prefix; - root = (Node)mkNode("", component, ports, 0, ports.length, 0, 0); - } - private Object mkNode(String name, String component, FpgaPump[] ports, - int start, int end, int addr, int bits) { - if (end-start == 0) return null; - if (end-start == 1) { - FpgaPump p = ports[start]; - if (prefix.equals("instruction")) { - p.instr_addr = (addr<<1); - p.instr_bits = bits+1; - } else if (prefix.equals("dest")) { - p.addr = (addr << 1) | 1; - p.bits = bits+1; - if (bits >= 11) - throw new RuntimeException("too many pumps!"); - int count = 0; - for(Destination d : p.getDestinations()) { - if (!(d instanceof FpgaPump.VirtualPort)) continue; - FpgaPump.VirtualPort vp = (FpgaPump.VirtualPort)d; - vp.addr = p.addr | (count << bits); - count++; - } - } - return p; - } - int len = end-start; - int count = 0; - int count2 = 0; - int breakpt = 0; - if (end-start <= 2) { - breakpt = (start+end)/2; - } else { - for(int i=start; istart && count2 >= count/2) break; - } - } - return new Node(name, - component, - mkNode(name+"_0", component, ports, start, breakpt, addr, bits+1), - mkNode(name+"_1", component, ports, breakpt, end, addr | (1 << bits), bits+1), - addr, - bits); + public Fpga() throws Exception { this(new Module("root")); } + public Fpga(Module top) throws Exception { + this.top = top; + debugShip = createShip("Debug", "debug"); + createShip("Memory", "memory"); + createShip("Fifo", "fifo1"); + createShip("Fifo", "fifo2"); + createShip("Alu2", "alu2a"); + createShip("Rotator", "rotator"); + //createShip("Alu1", "alu1"); + createShip("Lut3", "lut3"); + createShip("Alu3", "alu3"); + + Module fifostage = new FifoModule(0); + Module fifo4 = new FifoModule(4); + Module fifo8 = new FifoModule(8); + Module horn = new HornModule(); + Module funnel = new FunnelModule(); + Module outbox = new FpgaDock.DockModule(false); + Module inbox = new FpgaDock.DockModule(true); + + Module.SinkPort debug_in = top.createWirePort("debug_in", WIDTH_PACKET); + Module.SourcePort debug_out = null; + for(FpgaShip ship : (Iterable)(Object)this) { + if (ship.getType().toLowerCase().equals("debug")) + debug_out = ship.getVerilogModule().getOutputPort("debug_out"); } - private String describe(String prefix, Object o) { - if (o==null) return null; - if (o instanceof FpgaPump) { - FpgaPump p = (FpgaPump)o; - return prefix+"_"+getUniqueName(p.getShip())+"_"+p.getName(); - } - if (o instanceof Node) { - return ((Node)o).describe(prefix); + + Module.SourcePort in = top.createInputPort("in", 8); + Module.SinkPort out = top.createOutputPort("out", 8, ""); + Module.Latch temp_in = top.new Latch("temp", WIDTH_PACKET) { public String doReset() { return name+"=0;"; } }; + Module.Latch count = top.new Latch("count", 8); + Module.Latch count_out = top.new Latch("count_out", 8); + top.new Event(new Object[] { in, debug_in }, + new Object[] { new SimpleAction(temp_in.getVerilogName()+" = ("+temp_in.getVerilogName()+" << 8) | in;"), + new SimpleAction("if (count >= 5) begin"+ + " count <= 0; "+ + " `packet_token("+debug_in.getVerilogName()+") <= 0;"+ + " `packet_data("+debug_in.getVerilogName()+") <= "+temp_in.getVerilogName()+";"+ + " `packet_dest("+debug_in.getVerilogName()+") <= `instruction_dest("+temp_in.getVerilogName()+");"+ + " "+debug_in.getVerilogName()+"_r <= 1; "+ + "end else count <= count+1; "), + in + }); + top.new Event(new Object[] { out, debug_out }, + new Object[] { new SimpleAction(out.getVerilogName()+" <= ("+debug_out.getVerilogName()+">> (count_out*8));"), + new SimpleAction("if (count_out >= 5) begin "+ + "count_out <= 0; "+debug_out.getVerilogName()+"_a <= 1; end"+ + " else count_out <= count_out+1; "), + out }); + + ArrayList sources = new ArrayList(); + ArrayList dests = new ArrayList(); + for(FpgaShip ship : (Iterable)(Object)this) { + if (ship.getType().toLowerCase().equals("debug")) + debug_out = ship.getVerilogModule().getOutputPort("debug_out"); + for(Dock port : ship) { + sources.add(((FpgaDock)port)); + dests.add(port.getInstructionDestination()); + dests.add(port.getDataDestination()); } - return null; } - private class Node { - Object left; - Object right; - String name; - String component; - int addr; - int bits; - public Node(String name, String component, Object left, Object right, int addr, int bits) { - this.left = left; - this.right = right; - this.name = name; - this.component = component; - this.addr = addr; - this.bits = bits; - } - public void dumpChannels(int indentamount, boolean decl) { - String indent = ""; - for(int i=0; i it) { - int ret = 0; - for(Destination d : it) - ret++; - return ret; - } + + // Expand ////////////////////////////////////////////////////////////////////////////// public void expand(ShipDescription sd) { try { @@ -372,32 +174,25 @@ public class Fpga extends Fleet { FileOutputStream out = new FileOutputStream(outf); PrintWriter pw = new PrintWriter(out); - boolean auto = - !"debug".equals(filename) && - !"execute".equals(filename) && - !"memory".equals(filename) && - !"fifo".equals(filename); + boolean auto = !"debug".equals(filename); if (auto) { pw.println("`include \"macros.v\""); pw.println(); - pw.print("`define reset "); - for(PumpDescription bb : sd) { - String bb_name = bb.getName(); - if (bb.isInbox()) { - pw.print(bb_name+"_a <= 1; "); - } else { - pw.print(bb_name+"_r <= 0; "); + pw.print("`define reset "); + for(DockDescription bb : sd) { + String bb_name = bb.getName(); + if (bb.isInputDock()) pw.print(bb_name+"_a <= 1; "); + else pw.print(bb_name+"_r <= 0; "); } - } - pw.println(); + pw.println(); pw.println("module " + filename + "( clk, rst "); - for(PumpDescription bb : sd) { + for(DockDescription bb : sd) { String bb_name = bb.getName(); pw.print(" "); - if (bb.isInbox()) { + if (bb.isInputDock()) { pw.print(", " + bb_name+"_r"); pw.print(", " + bb_name+"_a_"); pw.print(", " + bb_name+"_d"); @@ -412,15 +207,15 @@ public class Fpga extends Fleet { pw.println(); pw.println(" input clk;"); pw.println(" input rst;"); - for(PumpDescription bb : sd) { + for(DockDescription bb : sd) { String bb_name = bb.getName(); pw.print(" "); - if (bb.isInbox()) { + if (bb.isInputDock()) { pw.println("`input(" + bb_name+"_r, "+ bb_name+"_a, "+ bb_name+"_a_, "+ - "[(`PACKET_WIDTH-1):0],"+ + "[("+WIDTH_WORD+"-1):0],"+ bb_name+"_d)" ); } else { @@ -428,14 +223,15 @@ public class Fpga extends Fleet { bb_name+"_r, "+ bb_name+"_r_, "+ bb_name+"_a, "+ - "[(`PACKET_WIDTH-1):0],"+ + "[("+WIDTH_WORD+"-1):0],"+ bb_name+"_d_)" ); - pw.println("`defreg(" + - bb_name+"_d_, "+ - "[(`PACKET_WIDTH-1):0],"+ - bb_name+"_d)" - ); + if (!bb_name.equals("out") || !"memory".equals(filename)) + pw.println("`defreg(" + + bb_name+"_d_, "+ + "[("+WIDTH_WORD+"-1):0],"+ + bb_name+"_d)" + ); } pw.println(); } @@ -451,33 +247,39 @@ public class Fpga extends Fleet { } catch (Exception e) { throw new RuntimeException(e); } } - public int computeOffset(int origin, int target) { return (target - origin)/6; } - public int computeTarget(int origin, int offset) { return origin + (offset*6); } - private FpgaInstructionEncoder iie = new FpgaInstructionEncoder(); - public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); } - public Instruction readInstruction(long instr) { return iie.readInstruction(instr); } - public long writeInstruction(Instruction d) { return writeInstruction(d); } - public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); } + public Instruction readInstruction(DataInputStream is, Dock dispatchFrom) throws IOException { return iie.readInstruction(dispatchFrom, is); } + public Instruction readInstruction(Dock dispatchFrom, long instr) { return iie.readInstruction(dispatchFrom, instr); } + public long writeInstruction(Dock dispatchFrom, Instruction d) { return iie.writeInstruction(dispatchFrom, d); } + public void writeInstruction(DataOutputStream os, Dock dispatchFrom, Instruction d) throws IOException { iie.writeInstruction(os, dispatchFrom, d); } + + private Ship debugShip; + + public Dock getUniversalSource() { return debugShip.getDock("in"); } private class FpgaInstructionEncoder extends InstructionEncoder { - public long getDestAddr(Destination box) { return ((FpgaPump.VirtualPort)box).addr; } - public long getBoxInstAddr(Pump box) { return ((FpgaPump)box).instr_addr; } - public Destination getDestByAddr(long dest) { + public Dock getUniversalSource() { return debugShip.getDock("in"); } + public long getDestAddr(Path path) { + return ((FpgaPath)path).toLong(); + } + public Path getPathByAddr(Dock source, long dest) { for(Ship ship : Fpga.this) - for(Pump bb : ship.getPumps()) - for(Destination d : bb.getDestinations()) - if (getDestAddr(d)==dest) - return d; + for(Dock bb : ship) { + for(Destination d : new Destination[] { bb.getInstructionDestination(), bb.getDataDestination() }) { + for(BitVector signal : new BitVector[] { SIGNAL_ZERO, SIGNAL_ONE }) { + FpgaPath p = (FpgaPath)source.getPath(d, signal); + if (p.toLong() == dest) return p; + } + } + } return null; } - public Pump getBoxByInstAddr(long dest) { + public Dock getBoxByInstAddr(long dest) { for(Ship ship : Fpga.this) - for(Pump bb : ship.getPumps()) - if (((FpgaPump)bb).instr_addr == dest) + for(Dock bb : ship) + if (((FpgaDestination)((FpgaDock)bb).getInstructionDestination()).getAddr() == dest) return bb; return null; } } - -} \ No newline at end of file +} diff --git a/src/edu/berkeley/fleet/fpga/FpgaDestination.java b/src/edu/berkeley/fleet/fpga/FpgaDestination.java new file mode 100644 index 0000000..a57910c --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/FpgaDestination.java @@ -0,0 +1,47 @@ +package edu.berkeley.fleet.fpga; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; +import static edu.berkeley.fleet.verilog.Verilog.*; +import edu.berkeley.fleet.api.*; +import static edu.berkeley.fleet.verilog.Verilog.*; +import edu.berkeley.fleet.api.Dock; +import java.util.*; + + +public class FpgaDestination extends Destination implements FabricElement { + private Module.Port port; + private FpgaDock dock; + + public FpgaDestination(FpgaDock dock, Module.Port port, boolean isInstructionDestination) { + super(dock); + this.port = port; + this.dock = dock; + } + + public Module.Port getOutputPort() { throw new RuntimeException(); } + 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) { + if (dest==this) return FpgaPath.emptyPath(this, signal); + return null; + } + public void addInput(FabricElement in, Module.Port inPort) { + inPort.connect((Module.SinkPort)port); + } + public String toString() { + return dock.toString(); + } +} diff --git a/src/edu/berkeley/fleet/fpga/FpgaDock.java b/src/edu/berkeley/fleet/fpga/FpgaDock.java new file mode 100644 index 0000000..259409d --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/FpgaDock.java @@ -0,0 +1,328 @@ +package edu.berkeley.fleet.fpga; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; +import static edu.berkeley.fleet.verilog.Verilog.*; +import edu.berkeley.fleet.api.*; +import static edu.berkeley.fleet.verilog.Verilog.*; +import edu.berkeley.fleet.api.Dock; +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 = 8; + + private FpgaDestination dataDestination; + private FpgaDestination instructionDestination; + + private Module.InstantiatedModule instance; + + public Module.InstantiatedModule getInstance() { return instance; } + + public Destination getDataDestination() { return dataDestination; } + public Destination getInstructionDestination() { return instructionDestination; } + public int getInstructionFifoSize() { return INSTRUCTION_FIFO_SIZE; } + + FpgaDock(FpgaShip ship, DockDescription bbd) { + super(ship, bbd); + this.instance = new Module.InstantiatedModule(((Fpga)ship.getFleet()).top, new DockModule(isInputDock())); + this.dataDestination = new FpgaDestination(this, this.instance.getInputPort("fabric_in"), false); + this.instructionDestination = new FpgaDestination(this, this.instance.getInputPort("instruction"), true); + Module.InstantiatedModule shipm = ship.getVerilogModule(); + if (isInputDock()) { + instance.getOutputPort("ship").connect(shipm.getInputPort(getName())); + } else { + shipm.getOutputPort(getName()).connect(instance.getInputPort("ship")); + } + } + + + // FabricElement methods ////////////////////////////////////////////////////////////////////////////// + + private FabricElement upstream; + public Module.Port 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 void addInput(FabricElement in, Module.Port inPort) { throw new RuntimeException(); } + public void addOutput(FabricElement out, Module.Port outPort) { + this.upstream = out; + instance.getOutputPort("fabric_out").connect((Module.SinkPort)outPort); + } + + public static class DockModule extends Module { + + public DockModule(boolean inbox) { + super(inbox ? "inbox" : "outbox"); + Module fifo4 = new FifoModule(4); + Module fifo8 = new FifoModule(8); + Module fifo = fifo8; + Module ififo_m = new FifoModule(INSTRUCTION_FIFO_SIZE); + Module efifo_m = fifo4; + Module.SourcePort instruction = createInputPort("instruction", WIDTH_PACKET); + instruction.hasLatch = true; + + Module.SourcePort fabric_in = createInputPort("fabric_in", WIDTH_PACKET); + Module.SinkPort fabric_out = createOutputPort("fabric_out", WIDTH_PACKET, ""); + Module.InstantiatedModule dfifo = new Module.InstantiatedModule(this, fifo); + fabric_in.connect(dfifo.getInputPort("in")); + + Module.SourcePort dfifo_out = dfifo.getOutputPort("out"); + Module.SourcePort ship_out = null; + if (!inbox) { + ship_out = createInputPort("ship", WIDTH_WORD); + ship_out.hasLatch = true; + } + + Module.SinkPort ship_in = null; + if (inbox) { + ship_in = createOutputPort("ship", WIDTH_PACKET, ""); + ship_in.hasLatch = true; + } + + Module.Latch ondeck = new Latch("ondeck", WIDTH_WORD); + Module.Latch repeat_counter = new Latch("repeat_counter", SET_ILC_FROM_IMMEDIATE.valmaskwidth+1, 1); + Module.Latch loop_counter = new Latch("loop_counter", SET_OLC_FROM_IMMEDIATE.valmaskwidth, 1); + Module.Latch tapl = new Latch("tapl", SET_TAPL_FROM_IMMEDIATE.valmaskwidth); + Module.Latch flag_a = new Latch("flag_a", 1); + Module.Latch flag_b = new Latch("flag_b", 1); + Module.Latch flag_c = new Latch("flag_c", 1); + Module.StateWire ondeckFull = new StateWire("ondeck_full"); + Module.StateWire newMayProceed = new StateWire("newmayproceed", true); + Module.StateWire doRepeat = new StateWire("dorepeat", false); + + Module.StateWire isHatchOpen = new StateWire("hatch", true); + + 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 = new Module.InstantiatedModule(this, ififo_m); + Module.SinkPort ififo_in = ififo.getInputPort("in"); + Module.SourcePort ififo_out = ififo.getOutputPort("out"); + + Module.InstantiatedModule efifo = new Module.InstantiatedModule(this, efifo_m); + Module.SinkPort efifo_in = efifo.getInputPort("in"); + Module.SourcePort efifo_out = efifo.getOutputPort("out"); + efifo_in.hasLatch = true; + + addPreCrap("wire [(`DATAWIDTH-1):0] data_latch_output;"); + addPreCrap("wire [(`DATAWIDTH-1):0] data_latch_input;"); + addPreCrap("assign data_latch_output = " + + (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+";"); + addPreCrap("assign data_latch_input = " + + (inbox ? "`packet_data("+data_in.getName()+")" : data_in.getName())+";"); + Assignable data_latch = new SimpleAssignable(inbox ? data_out.getName() : + "`packet_data("+data_out.getName()+")"); + String data_latch_input = "data_latch_input"; + + // Open the Hatch + new Event(new Object[] { "loop_counter==0" }, + new Action[] { isHatchOpen.doFill() }); + + // Torpedo Arrival + new Event(new Object[] { instruction, + PACKET_TOKEN.verilogVal("instruction"), + ondeckFull.isFull(), + token_out, + I.verilog("ondeck"), + }, + new Action[] { instruction, + ondeckFull.doDrain(), + newMayProceed.doFill(), + new AssignAction(loop_counter, "0"), + new AssignAction(repeat_counter, "1"), + new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"), "1"), + new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"), "tapl"), + token_out, + isHatchOpen.doFill(), + }); + // Non-Torpedo Arrival + new Event(new Object[] { instruction, + efifo_in, + "!("+PACKET_TOKEN.verilogVal("instruction")+")" + }, + new Action[] { + efifo_in, + instruction, + new AssignAction(efifo_in, instruction) + }); + + // Tail + new Event(new Object[] { efifo_out, TAIL.verilog("`packet_data("+efifo_out.getName()+")") }, + new Action[] { efifo_out, isHatchOpen.doDrain() } ); + // Enqueue + new Event(new Object[] { efifo_out, + ififo_in, + "!("+TAIL.verilog("`packet_data("+efifo_out.getName()+")")+")", + isHatchOpen.isFull() }, + new Action[] { efifo_out, ififo_in, new AssignAction(ififo_in, "`packet_data("+efifo_out.getName()+")") } ); + + // New + new Event(new Object[] { ififo_out, + ondeckFull.isEmpty(), + newMayProceed.isFull(), + }, + new Action[] { ififo_out, + ondeckFull.doFill(), + newMayProceed.doDrain(), + new AssignAction(ondeck, ififo_out) + } + ); + + // RepeatExecute + new Event(new Object[] { doRepeat.isFull() }, + new Action[] { doRepeat.doDrain(), ondeckFull.doFill(), + new AssignAction(repeat_counter, + "repeat_counter==`magic_standing_value?`magic_standing_value:(repeat_counter-1)") + }); + + // Execute + new Event( + new Object[] { ondeckFull.isFull(), + data_out, + token_out, + ififo_in, + "(!`predicate_met(ondeck) || "+OS.verilog("ondeck")+" || !hatch)", + new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_datain(ondeck))", data_in), + new ConditionalTrigger("(`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck))", token_in) + }, + new Action[] { ondeckFull.doDrain(), + new ConditionalAction("`done_executing(ondeck)", newMayProceed.doFill()), + new ConditionalAction("`done_executing(ondeck) && `instruction_is_normal(ondeck)", + new AssignAction(repeat_counter, "1")), + new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", ififo_in), + new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", new AssignAction(ififo_in, ondeck)), + new ConditionalAction("!`done_executing(ondeck)", doRepeat.doFill()), + + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_data_to_loop(ondeck)", + new AssignAction(loop_counter, "data_latch_output")), + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_immediate_to_loop(ondeck)", + new AssignAction(loop_counter, "`instruction_loop_count_immediate(ondeck)")), + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_decr_loop(ondeck)", + new AssignAction(loop_counter, "loop_counter==0 ? 0 : (loop_counter-1)")), + + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_data_to_repeat(ondeck)", + new AssignAction(repeat_counter, "data_latch_output")), + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_immediate_to_repeat(ondeck)", + new AssignAction(repeat_counter, "`instruction_repeat_count_immediate(ondeck)")), + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_load_standing_to_repeat(ondeck)", + new AssignAction(repeat_counter, "`magic_standing_value")), + new ConditionalAction("`predicate_met(ondeck) &&"+SHIFT.verilog("ondeck"), + new AssignAction(data_latch, + "({ data_latch_output["+(WIDTH_WORD-1-19)+":0], 19'b0 } | "+ + SHIFT.verilogVal("ondeck")+")")), + new ConditionalAction("`predicate_met(ondeck) && "+SET_IMMEDIATE.verilog("ondeck"), + new AssignAction(data_latch, + "{ {"+(WIDTH_WORD-InstructionEncoder.DataLatch_WIDTH)+ + "{"+SET_IMMEDIATE_EXTEND.verilogVal("ondeck")+"}}, "+ + SET_IMMEDIATE.verilogVal("ondeck")+" }")), + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)", + new AssignAction(flag_a, "`new_flag_a(ondeck)")), + new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)", + new AssignAction(flag_b, "`new_flag_b(ondeck)")), + (inbox + ? new ConditionalAction("`predicate_met(ondeck) && "+ + "(`instruction_bit_datain(ondeck) || `instruction_bit_tokenin(ondeck))", + new AssignAction(flag_c, PACKET_SIGNAL.verilogVal(dfifo_out.getName()))) + : new ConditionalAction("`predicate_met(ondeck) && "+ + "(!`instruction_bit_datain(ondeck) && `instruction_bit_tokenin(ondeck))", + new AssignAction(flag_c, PACKET_SIGNAL.verilogVal(dfifo_out.getName()))) + /* FIXME: C-flag-from-ship */ + ), + new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_datain(ondeck)", data_in), + new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_dataout(ondeck)", data_out), + new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck)", token_in), + new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenout(ondeck)", token_out), + new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenout(ondeck)", + new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"), + "1")), + new ConditionalAction("`predicate_met(ondeck) && !`instruction_bit_tokenout(ondeck)", + new AssignAction(new SimpleAssignable("`packet_token("+token_out.getName()+")"), + "0")), + new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_latch(ondeck)", + new AssignAction(data_latch, data_latch_input)), + new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_data(ondeck)", + new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"), + DISPATCH_PATH.verilogVal(data_latch_input))), + new ConditionalAction("`predicate_met(ondeck) && "+SET_TAPL_FROM_IMMEDIATE.verilog("ondeck"), + new AssignAction(tapl, SET_TAPL_FROM_IMMEDIATE.verilogVal("ondeck"))), + new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_immediate(ondeck)", + new AssignAction(new SimpleAssignable("`packet_signal_and_dest("+token_out.getName()+")"), + "`instruction_path_immediate(ondeck)")), + } + ); + } + + public void dump(PrintWriter pw, boolean fix) { + + pw.println("`define packet_signal_and_dest(p) { "+PACKET_SIGNAL.verilogVal("p")+", "+PACKET_DEST.verilogVal("p")+" }"); + pw.println("`define instruction_is_load_data_to_repeat(i) "+SET_ILC_FROM_DATA_LATCH.verilog("i")); + pw.println("`define instruction_is_load_data_to_loop(i) "+SET_OLC_FROM_DATA_LATCH.verilog("i")); + pw.println("`define instruction_is_load_immediate_to_repeat(i) "+SET_ILC_FROM_IMMEDIATE.verilog("i")); + pw.println("`define instruction_is_load_immediate_to_loop(i) "+SET_OLC_FROM_IMMEDIATE.verilog("i")); + pw.println("`define instruction_is_load_standing_to_repeat(i) "+SET_ILC_FROM_INFINITY.verilog("i")); + pw.println("`define instruction_repeat_count_immediate(i) "+SET_ILC_FROM_IMMEDIATE.verilogVal("i")); + pw.println("`define instruction_loop_count_immediate(i) "+SET_OLC_FROM_IMMEDIATE.verilogVal("i")); + + pw.println("`define instruction_path_immediate(i) "+PATH_IMMEDIATE.verilogVal("i")); + pw.println("`define instruction_path_from_immediate(i) "+PATH_IMMEDIATE.verilog("i")); + pw.println("`define instruction_path_from_data(i) "+PATH_DATA.verilog("i")); + + pw.println("`define instruction_is_tail(i) "+TAIL.verilog("i")); + pw.println("`define instruction_is_normal(i) "+MOVE.verilog("i")); + pw.println("`define instruction_is_setflags(i) "+SET_FLAGS.verilog("i")); + pw.println("`define instruction_is_set(i) "+SET.verilog("i")); + + pw.println("`define instruction_is_decr_loop(i) "+SET_OLC_FROM_OLC_MINUS_ONE.verilog("i")); + + pw.println("`define instruction_bit_tokenout(i) (`instruction_is_normal(i) && "+TO.verilog("i")+")"); + pw.println("`define instruction_bit_dataout(i) (`instruction_is_normal(i) && "+DO.verilog("i")+")"); + pw.println("`define instruction_bit_latch(i) (`instruction_is_normal(i) && "+DC.verilog("i")+")"); + pw.println("`define instruction_bit_datain(i) (`instruction_is_normal(i) && "+DI.verilog("i")+")"); + pw.println("`define instruction_bit_tokenin(i) (`instruction_is_normal(i) && "+TI.verilog("i")+")"); + pw.println("`define should_requeue(i) (loop_counter > 0 && !("+OS.verilog("i")+"))"); + pw.println("`define predicate_met(i) ("+ + "("+ + "!`instruction_is_normal(i) || repeat_counter>0"+ + ") && ("+ + " " + P_A.verilog("i")+" ? flag_a "+ + ":" + P_B.verilog("i")+" ? flag_b "+ + ":" + P_C.verilog("i")+" ? flag_c "+ + ":" + P_NOT_A.verilog("i")+" ? !flag_a "+ + ":" + P_NOT_B.verilog("i")+" ? !flag_b "+ + ":" + P_NOT_C.verilog("i")+" ? !flag_c "+ + ":" + P_OLC.verilog("i")+" ? (loop_counter>0) "+ + ": 1"+ + ")"+ + ")"); + pw.println("`define new_flag(x) ("+ + "( ((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" + + ")"); + pw.println("`define new_flag_a(i) `new_flag("+SET_FLAGS_A.verilogVal("i")+")"); + pw.println("`define new_flag_b(i) `new_flag("+SET_FLAGS_B.verilogVal("i")+")"); + pw.println("`define done_executing(i) (repeat_counter==0 || repeat_counter==1 || !`instruction_is_normal(i))"); + + pw.println("`define magic_standing_value (1<<"+SET_ILC_FROM_IMMEDIATE.valmaskwidth+")"); + + super.dump(pw,fix); + } + } +} diff --git a/src/edu/berkeley/fleet/fpga/FpgaPath.java b/src/edu/berkeley/fleet/fpga/FpgaPath.java new file mode 100644 index 0000000..d265803 --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/FpgaPath.java @@ -0,0 +1,80 @@ +package edu.berkeley.fleet.fpga; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; +import static edu.berkeley.fleet.verilog.Verilog.*; + + +public class FpgaPath extends Path { + + private boolean[] path; + private FpgaDestination dest; + public final BitVector signal; + + public Dock getSource() { throw new RuntimeException("not implemented"); } + public Destination getDestination() { return dest; } + + private FpgaPath(boolean[] path, FpgaDestination dest, BitVector signal) { + this.signal = signal; + this.path = path; + this.dest = dest; + } + + public long toLong() { + long ret = 0; + for(int i=0; i0) ret.append('_'); + ret.append(path[i] ? "1" : "0"); + } + return ret.toString()+(signal==null?"":(":"+signal)); + } + + public FpgaPath prepend(boolean b) { + boolean[] newpath = new boolean[path.length+1]; + System.arraycopy(path, 0, newpath, 1, path.length); + newpath[0] = b; + return new FpgaPath(newpath, dest, signal); + } + public FpgaPath append(boolean b, FpgaDestination newdest) { + boolean[] newpath = new boolean[path.length+1]; + System.arraycopy(path, 0, newpath, 0, path.length); + newpath[newpath.length-1] = b; + return new FpgaPath(newpath, newdest, signal); + } + + public int getBufferingAmount() { + throw new RuntimeException("not implemented"); + } + + public int getLatencyMetric() { + return 0; + } + + public static FpgaPath emptyPath(FpgaDestination dest, BitVector signal) { + return new FpgaPath(new boolean[0], dest, signal); + } + + public BitVector getSignal() { return null; } + +} diff --git a/src/edu/berkeley/fleet/fpga/FpgaPump.java b/src/edu/berkeley/fleet/fpga/FpgaPump.java deleted file mode 100644 index 0346b8d..0000000 --- a/src/edu/berkeley/fleet/fpga/FpgaPump.java +++ /dev/null @@ -1,105 +0,0 @@ -package edu.berkeley.fleet.fpga; -import edu.berkeley.fleet.doc.*; -import edu.berkeley.fleet.api.*; -import edu.berkeley.fleet.api.*; -import edu.berkeley.fleet.api.Pump; -import java.util.*; - -/** anything that has a destination address on the switch fabric */ -public class FpgaPump extends Pump { - - private final String name; - private final FpgaShip ship; - private Destination[] ports; - - public Iterable getDestinations() { - ArrayList ret = new ArrayList(); - for(Destination d : ports) ret.add(d); - return ret; - } - private static int default_addr; - private static int default_instr_addr; - - public int bits; - public int addr = (default_addr++); - public int instr_bits; - public int instr_addr = (default_instr_addr++); - private final PumpDescription bbd; - protected boolean special = false; - protected boolean ihorn = false; - protected boolean dhorn = false; - void service() { } - public boolean special() { return special; } - public boolean ihorn() { return ihorn; } - public boolean dhorn() { return dhorn; } - public boolean inbox; - public boolean isInbox() { return inbox; } - public boolean isOutbox() { return !inbox; } - public long resolveLiteral(String literal) { - return bbd.resolveLiteral(literal); - } - public FpgaPump(PumpDescription bbd, boolean inbox, FpgaShip ship, String name) { - this(bbd, inbox, ship, name, false, false, false); - } - public FpgaPump(PumpDescription bbd, boolean inbox, FpgaShip ship, String name, boolean special) { - this(bbd, inbox, ship, name, special, false, false); - } - public FpgaPump(PumpDescription bbd, boolean inbox, FpgaShip ship, String name, boolean special, boolean ihorn, boolean dhorn) { - this.bbd = bbd; - this.inbox = inbox; - this.special = special; - this.dhorn = dhorn; - this.ihorn = ihorn; - this.ship = ship; - this.name = name; - String[] ports = new String[] { "" }; - this.ports = new Destination[ports.length]; - for(int i=0; i ports = new LinkedHashMap(); + /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */ - public FpgaShip(Fpga fleet, String name, String type, ShipDescription sd) { - this.fleet = fleet; this.type = type; - for(PumpDescription sdbb : sd) { - FpgaPump sbb = new FpgaPump(sdbb, sdbb.isInbox(), this, sdbb.getName()); - for(String port : sdbb) { - if (port.equals("")) continue; - sbb.addDestination(port); - } - } - if (type.equals("Debug")) { - new FpgaPump(null, false, this, "out", true); - - } else if (type.equals("Execute")) { - new FpgaPump(null, false, this, "ihorn", true, true, false); - new FpgaPump(null, false, this, "dhorn", true, false, true); - - } else if (type.equals("Memory")) { - new FpgaPump(null, true, this, "command", true); - new FpgaPump(null, false, this, "ihorn", true, true, false); - new FpgaPump(null, false, this, "dhorn", true, false, true); + 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(), WIDTH_WORD); + else module.createOutputPort(sdbb.getName(), WIDTH_WORD, ""); + ports.put(sdbb.getName(), new FpgaDock(this, sdbb)); } + if (getType().toLowerCase().equals("debug")) + module.createOutputPort("debug_out", WIDTH_WORD, ""); } - private Fpga fleet; - private String type; - - public long resolveLiteral(String s) { - if (s.equals("NEG")) return 0; - if (s.equals("INC")) return 1; - if (s.equals("DEC")) return 2; - if (s.equals("ABS")) return 3; - if (s.equals("ADD")) return 0; - if (s.equals("SUB")) return 1; - if (s.equals("MAX")) return 2; - if (s.equals("MIN")) return 3; - return super.resolveLiteral(s); - } - - // this is dumb, the fpga fleet currently requires these in declaration-order; it shouldn't - private ArrayList portlist = new ArrayList(); - private HashMap ports = new HashMap(); - - public Iterable getPumps() { return (Iterable)(Object)portlist; } - public String getType() { return type; } - public Fleet getFleet() { return fleet; } - public Fpga getSlipway() { return fleet; } - - void addPump(String name, FpgaPump port) { ports.put(name, port); portlist.add(port); } + public Iterator iterator() { return (Iterator)(Object)ports.values().iterator(); } + public Module.InstantiatedModule getVerilogModule() { return instance; } } diff --git a/src/edu/berkeley/fleet/fpga/FunnelModule.java b/src/edu/berkeley/fleet/fpga/FunnelModule.java new file mode 100644 index 0000000..4646cb7 --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/FunnelModule.java @@ -0,0 +1,61 @@ +package edu.berkeley.fleet.fpga; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; +import static edu.berkeley.fleet.verilog.Verilog.*; + + +public class FunnelModule extends Module { + + public FunnelModule() { + super("funnel"); + Module.SinkPort outp = createOutputPort("out", WIDTH_PACKET, ""); + Module.SourcePort in1p = createInputPort("in1", WIDTH_PACKET); + Module.SourcePort in2p = createInputPort("in2", WIDTH_PACKET); + new Event(new Object[] { in1p, outp }, + new Action[] { in1p, outp, + new AssignAction(outp, in1p) }); + new Event(new Object[] { in2p, outp }, + new Action[] { in2p, outp, + new AssignAction(outp, in2p) }); + } + + public static class FunnelInstance extends Module.InstantiatedModule implements FabricElement { + private FabricElement in1 = null; + private FabricElement in2 = null; + public FabricElement out = null; + public Module.Port getOutputPort() { return getOutputPort("out"); } + public Module.Port getInputPort() { throw new RuntimeException("funnel has multiple inputs"); } + public FunnelInstance(Module thisModule, Module.Port p1, Module.Port p2) { + super(thisModule, new FunnelModule()); + p1.connect(this.getInputPort("in1")); + p2.connect(this.getInputPort("in2")); + } + public FunnelInstance(Module thisModule, FabricElement in1, FabricElement in2) { + super(thisModule, new FunnelModule()); + this.in1 = in1; + this.in2 = in2; + in1.addOutput(this, this.getInputPort("in1")); + in2.addOutput(this, this.getInputPort("in2")); + } + public void addOutput(FabricElement out, Module.Port outPort) { + this.out = out; + getOutputPort("out").connect((Module.SinkPort)outPort); + } + 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) { + return out.getPath(dest, signal); + } + } + +} diff --git a/src/edu/berkeley/fleet/fpga/Generator.java b/src/edu/berkeley/fleet/fpga/Generator.java deleted file mode 100644 index 9556247..0000000 --- a/src/edu/berkeley/fleet/fpga/Generator.java +++ /dev/null @@ -1,917 +0,0 @@ -// note: got rid of funnel "fairness" code -package edu.berkeley.fleet.fpga; -import edu.berkeley.fleet.doc.*; -import edu.berkeley.fleet.api.*; -import edu.berkeley.fleet.ies44.*; -import edu.berkeley.fleet.*; -import java.lang.reflect.*; -import edu.berkeley.sbp.chr.*; -import edu.berkeley.sbp.misc.*; -import edu.berkeley.sbp.meta.*; -import edu.berkeley.sbp.util.*; -import java.util.*; -import java.io.*; -import static edu.berkeley.fleet.ies44.InstructionEncoder.*; - -public class Generator { - - public static final int WIDTH_PACKET = WIDTH_WORD + WIDTH_ADDR; - - 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 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(); - public void addCrap(String s) { crap.append(s); crap.append('\n'); } - public void addPreCrap(String s) { precrap.append(s); precrap.append('\n'); } - - public Module(String name) { - this.name = name; - } - - 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 getOutputPort(String name) { - SinkPort ret = (SinkPort)ports.get(name); - if (ret==null) throw new RuntimeException(); - return ret; - } - - 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 String doReset() { return name+"<="+(initiallyFull?"1":"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 String doReset() { return name+"<=0;"; } - public void dump(PrintWriter pw) { - pw.println(" reg ["+(width-1)+":0] "+name+";"); - pw.println(" initial "+name+"=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 external; - public Port(String name, int width, boolean external) { - this.width = width; - this.name = name; - this.external = external; - ports.put(name, this); - 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(); - public abstract String getSimpleInterface(); - public abstract String getDeclaration(); - public abstract String getAssignments(); - } - - private class InstantiatedModule { - public final Module module; - public final int id; - private final HashMap ports = new HashMap(); - public String getName() { return module.getName()+"_"+id; } - public InstantiatedModule(Module module) { - this.module = module; - this.id = Module.this.id++; - 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()); - 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 = 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 = new SourcePort(getName()+"_"+name, width, false); - ports.put(name, port); - } - return 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() { - StringBuffer sb = new StringBuffer(); - if (external) { - sb.append("input " + name +"_r;\n"); - sb.append("output " + name +"_a_;\n"); - sb.append("input ["+(width-1)+":0]" + name +";\n"); - } else { - sb.append("wire " + name +"_r;\n"); - sb.append("wire ["+(width-1)+":0]" + name +";\n"); - } - if (!hasLatch) { - sb.append("wire " + name +"_a;\n"); - } else { - sb.append("reg " + name +"_a;\n"); - sb.append("initial " + name +"_a = 0;\n"); - } - return sb.toString(); - } - public String getAssignments() { - StringBuffer sb = new StringBuffer(); - 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"); - sb.append("assign " + driven.name +" = " + name + ";\n"); - } - return sb.toString(); - } - public void connect(SinkPort driven) { - this.driven = driven; - } - } - 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; } - public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; } - public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; } - public String getDeclaration() { - StringBuffer sb = new StringBuffer(); - if (external) { - sb.append("output " + name +"_r_;\n"); - sb.append("input " + name +"_a;\n"); - sb.append("output ["+(width-1)+":0]" + name +"_;\n"); - } else { - sb.append("wire " + name +"_a;\n"); - } - if (!hasLatch) { - sb.append("wire " + name +"_r;\n"); - sb.append("wire ["+(width-1)+":0]" + name +";\n"); - } else { - sb.append("reg " + name +"_r;\n"); - sb.append("initial " + name +"_r = 0;\n"); - sb.append("reg ["+(width-1)+":0]" + name +";\n"); - sb.append("initial " + name +" = 0;\n"); - } - return sb.toString(); - } - public String getAssignments() { - StringBuffer sb = new StringBuffer(); - if (external) { - sb.append("assign " + name +"_r_ = " + name + "_r;\n"); - sb.append("assign " + name +"_ = " + name + ";\n"); - } - return sb.toString(); - } - } - - public void dump(PrintWriter pw, boolean fix) { - pw.println("`include \"macros.v\""); - pw.println("module "+name+"(clk, rst "); - for(String name : portorder) { - Port p = ports.get(name); - pw.println(" , " + p.getInterface()); - } - pw.println(" );"); - pw.println(); - pw.println(" input clk;"); - pw.println(" input rst;"); - 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); - 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()) { - if (p instanceof SourcePort) { - SourcePort ip = (SourcePort)p; - if (ip.hasLatch) - pw.println(ip.getAck()+" <=1;"); - } else { - SinkPort op = (SinkPort)p; - if (op.hasLatch) - pw.println(op.getReq()+" <=0;"); - } - } - 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(Event a : events) a.dump(pw, fix); - pw.println(" begin end"); - pw.println(" end"); - pw.println(" end"); - - pw.println(crap); - pw.println("endmodule"); - } - - private class Event { - private Object[] triggers; - private Object[] actions; - 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= 5) begin count <= 0; "+fabric_in.getName()+"_r <= 1; end else count <= count+1; "), - in - }); - root.new Event(new Object[] { out, fabric_out }, - new Object[] { new SimpleAction(out.getName()+" <= ("+fabric_out.getName()+">> (count_out*8));"), - new SimpleAction("if (count_out >= 5) begin count_out <= 0; "+fabric_out.getName()+"_a <= 1; end else count_out <= count_out+1; "), - out }); - PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); - root.dump(pw, true); - pw.flush(); - return root; - } - - private static Module mkfunnel(String name, String prefix) throws Exception { - Module funnel = new Module(name); - Module.SinkPort out = funnel.createOutputPort("out", WIDTH_PACKET, ""); - Module.SourcePort in1 = funnel.createInputPort("in1", WIDTH_PACKET); - Module.SourcePort in2 = funnel.createInputPort("in2", WIDTH_PACKET); - funnel.new Event(new Object[] { in1, out }, - new Action[] { in1, out, - new AssignAction(out, in1) }); - funnel.new Event(new Object[] { in2, out }, - new Action[] { in2, out, - new AssignAction(out, in2) }); - PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); - funnel.dump(pw, true); - pw.flush(); - return funnel; - } - - private static Module mkfifo(String name, int len, Module instance, String prefix) throws Exception { - Module fifo = new Module(name); - Module.SourcePort in = fifo.createInputPort("in", WIDTH_PACKET); - Module.SinkPort out = fifo.createOutputPort("out", WIDTH_PACKET, ""); - Module.InstantiatedModule[] stages = new Module.InstantiatedModule[len]; - if (len==0) { - fifo.new Event(new Object[] { in, out }, - new Action[] { in, out, new AssignAction(out, in) }); - } else for(int i=0; i<=len; i++) { - if (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 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, true); - pw.flush(); - } - - private static Module mkBox(String name, boolean inbox, String prefix, Module fifo, Module ififo_m) throws Exception { - Module box = new Module(name); - Module.SourcePort instr = box.createInputPort("instr", WIDTH_WORD); - Module.SourcePort fabric_in = box.createInputPort("fabric_in", WIDTH_PACKET); - Module.SinkPort fabric_out = box.createOutputPort("fabric_out", WIDTH_PACKET, ""); - 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", WIDTH_WORD); - ship_out.hasLatch = true; - } - - Module.SinkPort ship_in = null; - if (inbox) { - ship_in = box.createOutputPort("ship", WIDTH_PACKET, ""); - ship_in.hasLatch = true; - } - - Module.Latch ondeck = box.new Latch("ondeck", WIDTH_WORD); - Module.Latch repcount = box.new Latch("repcount", WIDTH_COUNTER_LITERAL+1); - Module.Latch repcount2 = box.new Latch("repcount2", WIDTH_COUNTER_LITERAL+1); - Module.Latch repeat_counter = box.new Latch("repeat_counter", WIDTH_COUNTER_LITERAL+1); - Module.Latch loop_counter = box.new Latch("loop_counter", WIDTH_COUNTER_LITERAL); - Module.Latch flag_a = box.new Latch("flag_a", 1); - Module.Latch flag_b = box.new Latch("flag_b", 1); - 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 isClogged = box.new StateWire("clogged", false); - Module.StateWire isMassacreing = box.new StateWire("massacreing", 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(ififo_m); - Module.SinkPort ififo_in = ififo.getInputPort("in"); - Module.SourcePort ififo_out = ififo.getOutputPort("out"); - - - // Massacre (when enqueued) - box.new Event( - new Object[] { ififo_out, "!`instruction_is_massacre("+ififo_out.getName()+")", isMassacreing.isFull() }, - new Action[] { ififo_out } - ); - box.new Event( - new Object[] { ififo_out, "`instruction_is_massacre("+ififo_out.getName()+")", isMassacreing.isFull() }, - new Action[] { ififo_out, isMassacreing.doDrain(), newMayProceed.doFill() } - ); - box.new Event( - new Object[] { instr, ififo_in, "`instruction_is_massacre(instr)", isMassacreing.isEmpty() }, - new Action[] { instr, ififo_in, - new AssignAction(ififo_in, instr), - isMassacreing.doFill(), - ondeckFull.doDrain(), - newMayProceed.doDrain(), - new AssignAction(repeat_counter, "0"), - new AssignAction(repcount2, "0"), - new AssignAction(repcount, "0"), - new AssignAction(loop_counter, "0"), - } - ); - - // Clog (must be first) - box.new Event( - new Object[] { ififo_out, newMayProceed.isFull(), "`instruction_is_clog("+ififo_out.getName()+")", isMassacreing.isEmpty() }, - new Action[] { ififo_out, isClogged.doFill(), newMayProceed.doDrain() } - ); - - // UnClog - box.new Event( - new Object[] { instr, isClogged.isFull(), "`instruction_is_unclog(instr)", isMassacreing.isEmpty() }, - new Action[] { instr, isClogged.doDrain(), newMayProceed.doFill() } - ); - - // First Kill - box.new Event( - new Object[] { instr, - "`instruction_is_kill(instr)", - "!`instruction_is_unclog(instr)", - ondeckFull.isFull(), - isMassacreing.isEmpty() - }, - new Action[] { instr, - ondeckFull.doDrain(), - new AssignAction(repeat_counter, "1"), - new AssignAction(repcount2, "1"), - newMayProceed.doFill() - }); - - - // Enqueue - box.new Event( - new Object[] { instr, - ififo_in, - "!`instruction_is_kill(instr) && !`instruction_is_unclog(instr) && !`instruction_is_massacre(instr)", - isMassacreing.isEmpty() - }, - new Action[] { instr, ififo_in, new AssignAction(ififo_in, instr) } - ); - - // New - box.new Event( - new Object[] { ififo_out, - ondeckFull.isEmpty(), - newMayProceed.isFull(), - "!`instruction_is_clog("+ififo_out.getName()+")", - "!`instruction_is_kill(instr)", - isMassacreing.isEmpty() }, - new Action[] { ififo_out, - ondeckFull.doFill(), - newMayProceed.doDrain(), - new AssignAction(ondeck, ififo_out), - new ConditionalAction("`instruction_is_normal("+ififo_out.getName()+")", - new AssignAction(repcount2, "(repeat_counter==0?1:repeat_counter)")), - new ConditionalAction("`instruction_is_normal("+ififo_out.getName()+")", - new AssignAction(repeat_counter, "1")), - } - ); - - // RepeatExecute - box.new Event( - new Object[] { doRepeat.isFull() }, - new Action[] { doRepeat.doDrain(), - ondeckFull.doFill(), - new AssignAction(repcount2, repcount) - } - ); - - box.addPreCrap("wire [(`DATAWIDTH-1):0] data_latch_output;"); - box.addPreCrap("assign data_latch_output = " + (inbox ? data_out.getName() : "`packet_data("+data_out.getName()+")")+";"); - - 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(), - isMassacreing.isEmpty(), - ififo_in, - "!`instruction_is_kill(instr)", - "`instruction_is_load_loop_to_data(ondeck)" - }, - new Action[] { ondeckFull.doDrain(), - newMayProceed.doFill(), - new AssignAction(data_latch, loop_counter), - new AssignAction(ififo_in, ondeck), - new ConditionalAction("`should_requeue(ondeck)", ififo_in) - } - ); - box.new Event(new Object[] { ondeckFull.isFull(), - isMassacreing.isEmpty(), - ififo_in, - "!`instruction_is_kill(instr)", - "`instruction_is_load_data_to_loop(ondeck)" - }, - new Action[] { ondeckFull.doDrain(), - newMayProceed.doFill(), - new AssignAction(loop_counter, "data_latch_output"), - new AssignAction(ififo_in, ondeck), - new ConditionalAction("`should_requeue(ondeck)", ififo_in) - } - ); - box.new Event(new Object[] { ondeckFull.isFull(), - isMassacreing.isEmpty(), - ififo_in, - "!`instruction_is_kill(instr)", - "`instruction_is_load_literal_to_loop(ondeck)" - }, - new Action[] { ondeckFull.doDrain(), - newMayProceed.doFill(), - new AssignAction(loop_counter, "`instruction_loop_count_literal(ondeck)"), - new AssignAction(ififo_in, ondeck), - new ConditionalAction("`should_requeue(ondeck)", ififo_in) - } - ); - box.new Event(new Object[] { ondeckFull.isFull(), - isMassacreing.isEmpty(), - ififo_in, - "!`instruction_is_kill(instr)", - "`instruction_is_load_data_to_repeat(ondeck)" - }, - new Action[] { ondeckFull.doDrain(), - newMayProceed.doFill(), - new AssignAction(repeat_counter, "data_latch_output"), - new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)), - new ConditionalAction("`should_requeue(ondeck)", ififo_in) - } - ); - box.new Event(new Object[] { ondeckFull.isFull(), - isMassacreing.isEmpty(), - ififo_in, - "!`instruction_is_kill(instr)", - "`instruction_is_load_literal_to_repeat(ondeck)" - }, - new Action[] { ondeckFull.doDrain(), - newMayProceed.doFill(), - new AssignAction(repeat_counter, "`instruction_repeat_count_literal(ondeck)"), - new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)), - new ConditionalAction("`should_requeue(ondeck)", ififo_in) - } - ); - box.new Event(new Object[] { ondeckFull.isFull(), - isMassacreing.isEmpty(), - ififo_in, - "!`instruction_is_kill(instr)", - "`instruction_is_load_standing_to_repeat(ondeck)" - }, - new Action[] { ondeckFull.doDrain(), - newMayProceed.doFill(), - new AssignAction(repeat_counter, "`magic_standing_value"), - new ConditionalAction("`should_requeue(ondeck)", new AssignAction(ififo_in, ondeck)), - new ConditionalAction("`should_requeue(ondeck)", ififo_in) - } - ); - - - box.new Event( - new Object[] { ondeckFull.isFull(), - isMassacreing.isEmpty(), - data_out, - token_out, - ififo_in, - "!`instruction_is_kill(instr)", - "(`instruction_is_normal(ondeck) || `instruction_is_literal_hi(ondeck) || `instruction_is_setflags(ondeck) || "+ - " `instruction_is_literal_lo(ondeck) || `instruction_is_literal(ondeck))", - new ConditionalTrigger("`instruction_bit_datain(ondeck)", data_in), - new ConditionalTrigger("`instruction_bit_tokenin(ondeck)", token_in) - }, - new Action[] { ondeckFull.doDrain(), - new ConditionalAction("`done_executing(ondeck)", newMayProceed.doFill()), - new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", ififo_in), - new ConditionalAction("`should_requeue(ondeck) && `done_executing(ondeck)", new AssignAction(ififo_in, ondeck)), - new ConditionalAction("repcount2>1 || repcount2==`magic_standing_value", doRepeat.doFill()), - new ConditionalAction("repcount2!=`magic_standing_value", new AssignAction(repcount, "repcount2-1")), - new ConditionalAction("repcount2==`magic_standing_value", new AssignAction(repcount, "`magic_standing_value")), - new ConditionalAction("`predicate_met(ondeck) && `instruction_is_literal(ondeck)", - new AssignAction(data_latch, "`instruction_literal(ondeck)")), - new ConditionalAction("`predicate_met(ondeck) && `instruction_is_literal_hi(ondeck)", - new AssignAction(data_latch, "`instruction_literal_hi(ondeck,data_latch_output)")), - new ConditionalAction("`predicate_met(ondeck) && `instruction_is_literal_lo(ondeck)", - new AssignAction(data_latch, "`instruction_literal_lo(ondeck,data_latch_output)")), - new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)", - new AssignAction(flag_a, "`new_flag_a(ondeck)")), - new ConditionalAction("`predicate_met(ondeck) && `instruction_is_setflags(ondeck)", - new AssignAction(flag_b, "`new_flag_b(ondeck)")), - new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_datain(ondeck)", data_in), - new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_dataout(ondeck)", data_out), - new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenin(ondeck)", token_in), - new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_tokenout(ondeck)", token_out), - new ConditionalAction("`predicate_met(ondeck) && `instruction_bit_latch(ondeck)", - new AssignAction(data_latch, data_latch_input)), - new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_data(ondeck)", - new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"), - PUMP_NAME.verilogVal(data_latch_input))), - new ConditionalAction("`predicate_met(ondeck) && `instruction_path_from_literal(ondeck)", - new AssignAction(new SimpleAssignable("`packet_dest("+token_out.getName()+")"), - "`instruction_path_literal(ondeck)")), - } - ); - box.new Event(new Object[] { ondeckFull.isFull(), - isMassacreing.isEmpty(), - ififo_in, - "!`instruction_is_kill(instr)", - "`instruction_is_decr_loop(ondeck)" - }, - new Action[] { new AssignAction(loop_counter, "loop_counter==0 ? 0 : (loop_counter-1)") - } - ); - - PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); - - pw.println("`define instruction_is_load_loop_to_data(i) "+TAKE_LOOP.verilog("i")); - pw.println("`define instruction_is_load_data_to_repeat(i) "+REPEAT_FROM_DATA.verilog("i")); - pw.println("`define instruction_is_load_data_to_loop(i) "+LOOP_FROM_DATA.verilog("i")); - pw.println("`define instruction_is_load_literal_to_repeat(i) "+REPEAT_FROM_LITERAL.verilog("i")); - pw.println("`define instruction_is_load_literal_to_loop(i) "+LOOP_FROM_LITERAL.verilog("i")); - pw.println("`define instruction_is_load_standing_to_repeat(i) "+REPEAT_FROM_STANDING.verilog("i")); - pw.println("`define instruction_repeat_count_literal(i) "+REPEAT_FROM_LITERAL.verilogVal("i")); - pw.println("`define instruction_loop_count_literal(i) "+LOOP_FROM_LITERAL.verilogVal("i")); - - pw.println("`define instruction_path_literal(i) "+PATH_LITERAL.verilogVal("i")); - pw.println("`define instruction_path_from_literal(i) "+PATH_LITERAL.verilog("i")); - pw.println("`define instruction_path_from_data(i) "+PATH_DATA.verilog("i")); - - pw.println("`define instruction_is_literal_hi(i) "+LITERAL_HI.verilog("i")); - pw.println("`define instruction_is_literal_lo(i) "+LITERAL_LO.verilog("i")); - pw.println("`define instruction_is_literal(i) "+LITERAL.verilog("i")); - pw.println("`define instruction_is_kill(i) "+KILL.verilog("i")); - pw.println("`define instruction_is_unclog(i) "+UNCLOG.verilog("i")); - pw.println("`define instruction_is_clog(i) "+CLOG.verilog("i")); - pw.println("`define instruction_is_massacre(i) "+MASSACRE.verilog("i")); - pw.println("`define instruction_is_normal(i) "+MOVE.verilog("i")); - pw.println("`define instruction_is_setflags(i) "+FLAGS.verilog("i")); - - pw.println("`define instruction_is_decr_loop(i) "+DL.verilog("i")); - - pw.println("`define instruction_bit_tokenout(i) (`instruction_is_normal(i) && "+TO.verilog("i")+")"); - pw.println("`define instruction_bit_dataout(i) (`instruction_is_normal(i) && "+DO.verilog("i")+")"); - pw.println("`define instruction_bit_latch(i) (`instruction_is_normal(i) && "+DC.verilog("i")+")"); - pw.println("`define instruction_bit_datain(i) (`instruction_is_normal(i) && "+DI.verilog("i")+")"); - pw.println("`define instruction_bit_tokenin(i) (`instruction_is_normal(i) && "+TI.verilog("i")+")"); - pw.println("`define should_requeue(i) (loop_counter > 0)"); - pw.println("`define flag_a flag_a"); - pw.println("`define flag_b flag_b"); - pw.println("`define flag_z (loop_counter==0 ? 1 : 0)"); - pw.println("`define flag_s (data_latch_output["+(WIDTH_WORD-1)+"])"); - pw.println("`define predicate_met(i) 1"); - /* - pw.println("`define predicate_met(i) ("+ - " " + P_A.verilog("i")+" ? `flag_a "+ - ":" + P_B.verilog("i")+" ? `flag_b "+ - ":" + P_Z.verilog("i")+" ? `flag_z "+ - ": 1"+ - ")"); - */ - pw.println("`define new_flag(x) ("+ - "( ((x >> 0) & 1) & !`flag_z) |" + - "( ((x >> 1) & 1) & `flag_z) |" + - "( ((x >> 2) & 1) & !`flag_s) |" + - "( ((x >> 3) & 1) & `flag_s) |" + - "( ((x >> 4) & 1) & !`flag_b) |" + - "( ((x >> 5) & 1) & `flag_b) |" + - "( ((x >> 6) & 1) & !`flag_a) |" + - "( ((x >> 7) & 1) & `flag_a) | 0" + - ")"); - pw.println("`define new_flag_a(i) `new_flag("+FLAGS_A.verilogVal("i")+")"); - pw.println("`define new_flag_b(i) `new_flag("+FLAGS_B.verilogVal("i")+")"); - pw.println("`define done_executing(i) (repcount2==0 || repcount2==1)"); - - pw.println("`define magic_standing_value (1<<"+WIDTH_COUNTER_LITERAL+")"); - - pw.println("`define instruction_literal_hi(i,d) { (i[17:0]), (d[18:0]) }"); - pw.println("`define instruction_literal_lo(i,d) { (d[36:19]), (i[18:0]) }"); - - pw.println("`define instruction_literal_sel(i) " + LITERAL_SEL.verilogVal("i")); - pw.println("`define instruction_literal(i) " + - "("+ - " `instruction_literal_sel(i) == 0 ? { (i[17:0]), {19{1'b0}} } "+ - ": `instruction_literal_sel(i) == 1 ? { (i[17:0]), {19{1'b1}} } "+ - ": `instruction_literal_sel(i) == 2 ? { {18{1'b0}}, (i[18:0]) } "+ - ": { {18{1'b1}}, (i[18:0]) } "+ - ")" - ); - - - box.dump(pw, true); - pw.flush(); - return box; - } - -} - - - - diff --git a/src/edu/berkeley/fleet/fpga/HornModule.java b/src/edu/berkeley/fleet/fpga/HornModule.java new file mode 100644 index 0000000..df380ed --- /dev/null +++ b/src/edu/berkeley/fleet/fpga/HornModule.java @@ -0,0 +1,76 @@ +package edu.berkeley.fleet.fpga; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; +import static edu.berkeley.fleet.verilog.Verilog.*; + + +public class HornModule extends Module { + + public HornModule() { + this(PACKET_DEST.width-1, + PACKET_DEST.valmaskmax, + PACKET_DEST.valmaskmin, + 0); + } + private HornModule(int top, + int top_of_addr_field, + int bot_of_addr_field, + int bot) { + super("horn"); + Module.SourcePort in = createInputPort("in", WIDTH_PACKET); + Module.SinkPort out0 = createOutputPort("out0", WIDTH_PACKET, ""); + Module.SinkPort out1 = createOutputPort("out1", WIDTH_PACKET, ""); + Module.Latch out = new Module.Latch("out", WIDTH_PACKET); + out0.forceNoLatch = true; + out1.forceNoLatch = true; + addCrap("assign out0 = out;"); + addCrap("assign out1 = out;"); + String shifted_packet = "{ "; + if (top_of_addr_field < top) shifted_packet += " in["+top+":"+(top_of_addr_field+1)+"], "; + shifted_packet += " (in["+(top_of_addr_field)+":"+bot_of_addr_field+"] >> 1) "; + if (bot_of_addr_field > 0) shifted_packet += ", in["+(bot_of_addr_field-1)+":0] "; + shifted_packet += " }"; + new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==0)" }, + new Action[] { in, out0, new AssignAction(out, shifted_packet) }); + new Event(new Object[] { in, out0, out1, "(in["+bot_of_addr_field+"]==1)" }, + new Action[] { in, out1, new AssignAction(out, shifted_packet) }); + } + + 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 Module.Port getOutputPort() { throw new RuntimeException("horn has multiple outputs"); } + public Module.Port getInputPort() { return getInputPort("in"); } + public HornInstance(Module thisModule, FabricElement out0, FabricElement out1) { + super(thisModule, new HornModule()); + this.out0 = out0; + this.out1 = out1; + out0.addInput(this, getOutputPort("out0")); + out1.addInput(this, getOutputPort("out1")); + } + public void addOutput(FabricElement out, Module.Port outPort) { throw new RuntimeException(); } + public FpgaPath getPath(FabricElement 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); + if (path1 != null) path1 = path1.prepend(true); + if (path0==null) return path1; + if (path1==null) return path0; + if (path0.getLatencyMetric() < path1.getLatencyMetric()) return path0; + // FIXME: choke if latency metrics equal? + // FIXME: determinism of path-search? + return path1; + } + } + +} diff --git a/src/edu/berkeley/fleet/fpga/Server.java b/src/edu/berkeley/fleet/fpga/Server.java index ba311f1..fb9049d 100644 --- a/src/edu/berkeley/fleet/fpga/Server.java +++ b/src/edu/berkeley/fleet/fpga/Server.java @@ -5,7 +5,10 @@ import java.io.*; import java.net.*; import java.util.*; +// FIXME: accept connections, but stall, during programming public class Server { + static boolean sign = false; + static long jarFileTime = 0; static long bitFileTime = 0; @@ -55,6 +58,7 @@ public class Server { while(true) { try { Socket s = ss.accept(); + System.out.println("accept!"); new Handler(s).start(); } catch (Exception e) { e.printStackTrace(); @@ -63,7 +67,6 @@ public class Server { } public static String pass_string = "password=security_is_for_wimps "; - static class Handler extends Thread { private Socket socket; boolean closed = false; @@ -75,7 +78,7 @@ public class Server { this.sp = new RXTXPort("/dev/ttyS0"); sp.setInputBufferSize(0); sp.setOutputBufferSize(0); - sp.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + sp.setSerialPortParams(38400, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); sp.setFlowControlMode(sp.FLOWCONTROL_RTSCTS_IN | sp.FLOWCONTROL_RTSCTS_OUT); try { _run(); @@ -87,7 +90,7 @@ public class Server { } public void _run() { try { - final InputStream is = socket.getInputStream(); + final InputStream is = new BufferedInputStream(socket.getInputStream()); byte[] buf = new byte[1024]; StringBuffer sb = new StringBuffer(); while(true) { @@ -98,31 +101,29 @@ public class Server { } System.err.println("login string: " + sb.toString()); if (!sb.toString().startsWith(pass_string)) return; - - //try { Thread.sleep(500); } catch(Exception e) { } - final OutputStream os = socket.getOutputStream(); - - System.out.println("sending breaks"); - for(int i=0; i<2; i++) { - sp.sendBreak(100); - Thread.sleep(100); - } - System.out.println("done sending breaks"); + final OutputStream os = new BufferedOutputStream(socket.getOutputStream()); + System.err.println("sending breaks..."); + sp.sendBreak(100); final OutputStream fos = sp.getOutputStream(); - final InputStream fis = sp.getInputStream(); + final InputStream fis = new BufferedInputStream(sp.getInputStream()); + sign = false; System.err.println("sending instructions..."); new Thread() { public void run() { try { - byte[] buf = new byte[1024]; while(true) { - int numread = is.read(buf, 0, buf.length); - if (numread == -1) break; - fos.write(buf, 0, numread); - fos.flush(); + int r = is.read(); + if (r == -1) break; + fos.write(r); + if (!sign) { + fos.flush(); + Thread.sleep(100); + sign = true; + } } + fos.flush(); } catch (Exception e) { throw new RuntimeException(e); } finally { System.err.println("closing..."); @@ -132,22 +133,12 @@ public class Server { } }.start(); - /* - int last = 0; - for(int j=0; j<3; j++) - while(true) { - int i = fis.read(); - if (i==-1) return; - System.out.println("leader byte: 0x" + Integer.toString(i, 16) + " '"+((char)i)+"'"); - if (((char)last) == 'o' && ((char)i) == 'k') break; - last = i; - } - */ System.err.println("reading back..."); while(true) { long result = 0; int val = 0; + boolean hit=false; for(int i=0; i<6; i++) { int k = 0; while(!closed && fis.available()==0) { @@ -157,14 +148,18 @@ public class Server { System.err.println("sleep"); k = 0; } + if (k==10) os.flush(); Thread.sleep(10); } - if (closed) return; + if (closed) { os.flush(); return; } val = fis.read(); + if (!sign) { + System.err.println("leader byte: 0x" + Integer.toString(val, 16) + " '"+((char)val)+"'"); + continue; + } if (val==-1) break; System.err.println("byte: 0x"+Integer.toString(val & 0xff, 16)); os.write((byte)val); - os.flush(); result |= ((long)val) << (i * 8); } if (val==-1) break; @@ -173,6 +168,7 @@ public class Server { System.err.print(Long.toString(result, 16)); System.err.println(); } + os.flush(); System.err.println("done."); } catch (Exception e) { throw new RuntimeException(e); @@ -188,4 +184,4 @@ public class Server { } } -} \ No newline at end of file +} diff --git a/src/edu/berkeley/fleet/fpga/main.v b/src/edu/berkeley/fleet/fpga/main.v index 371f27c..548a633 100644 --- a/src/edu/berkeley/fleet/fpga/main.v +++ b/src/edu/berkeley/fleet/fpga/main.v @@ -44,7 +44,8 @@ module main wire sio_ce; wire sio_ce_x4; - sasc_brg sasc_brg(clk, ser_rst, 10, 217, sio_ce, sio_ce_x4); + //sasc_brg sasc_brg(clk, ser_rst, 10, 217, sio_ce, sio_ce_x4); + sasc_brg sasc_brg(clk, ser_rst, 8, 65, sio_ce, sio_ce_x4); sasc_top sasc_top(clk, ser_rst, fpga_0_RS232_Uart_1_sin_pin, fpga_0_RS232_Uart_1_sout_pin, @@ -79,8 +80,12 @@ module main wire [7:0] root_in_d; wire [7:0] root_out_d; - - root my_root(clk, rst && !break, + /* + * There is some very weird timing thing going on here; we need to + * hold reset low for more than one clock in order for it to propagate + * all the way to the docks. + */ + root my_root(clk, rst && !break_o, root_in_r, root_in_a, root_in_d, root_out_r, root_out_a, root_out_d); /* @@ -100,7 +105,7 @@ module main if (break) begin root_out_a_reg = 0; data_to_host_write_enable_reg <= 0; -/* + end else if (break_done) begin data_to_host_write_enable_reg <= 1; data_to_host_r <= 111; @@ -109,7 +114,7 @@ module main data_to_host_write_enable_reg <= 1; data_to_host_r <= 107; send_k <= 0; -*/ + end else if (root_out_r && !root_out_a_reg && !data_to_host_full) begin data_to_host_write_enable_reg <= 1; diff --git a/src/edu/berkeley/fleet/fpga/main.xst b/src/edu/berkeley/fleet/fpga/main.xst index 2b62de5..9fa27f3 100644 --- a/src/edu/berkeley/fleet/fpga/main.xst +++ b/src/edu/berkeley/fleet/fpga/main.xst @@ -1,4 +1,4 @@ set -tmpdir ./tmp set -xsthdpdir ./xst run --ifn main.prj -ifmt mixed -ofn main -ofmt NGC -p xc4vfx60 -top main -opt_mode Speed -opt_level 1 -iuc NO -lso main.lso -keep_hierarchy NO -rtlview Yes -glob_opt AllClockNets -read_cores YES -write_timing_constraints NO -cross_clock_analysis NO -hierarchy_separator / -bus_delimiter <> -case maintain -slice_utilization_ratio 100 -verilog2001 YES -fsm_extract Yes -fsm_encoding Auto -safe_implementation No -fsm_style lut -ram_extract Yes -ram_style Auto -rom_extract Yes -mux_style Auto -decoder_extract YES -priority_extract YES -shreg_extract YES -shift_extract YES -xor_collapse YES -rom_style Auto -mux_extract YES -resource_sharing YES -mult_style auto -iobuf YES -max_fanout 500 -bufg 1 -register_duplication YES -register_balancing No -slice_packing Yes -optimize_primitives Yes -tristate2logic Yes -use_clock_enable Yes -use_sync_set Yes -use_sync_reset Yes -iob auto -equivalent_register_removal YES -slice_utilization_ratio_maxmargin 5 +-ifn main.prj -ifmt mixed -ofn main -ofmt NGC -p xc4vfx60 -top main -opt_mode Area -opt_level 1 -iuc NO -lso main.lso -keep_hierarchy NO -rtlview Yes -glob_opt AllClockNets -read_cores YES -write_timing_constraints NO -cross_clock_analysis NO -hierarchy_separator / -bus_delimiter <> -case maintain -slice_utilization_ratio 100 -verilog2001 YES -fsm_extract Yes -fsm_encoding Auto -safe_implementation No -fsm_style lut -ram_extract Yes -ram_style Auto -rom_extract Yes -mux_style Auto -decoder_extract YES -priority_extract YES -shreg_extract YES -shift_extract YES -xor_collapse YES -rom_style Auto -mux_extract YES -resource_sharing YES -mult_style auto -iobuf YES -max_fanout 500 -bufg 1 -register_duplication YES -register_balancing No -slice_packing Yes -optimize_primitives Yes -tristate2logic Yes -use_clock_enable Yes -use_sync_set Yes -use_sync_reset Yes -iob auto -equivalent_register_removal YES -slice_utilization_ratio_maxmargin 5 diff --git a/src/edu/berkeley/fleet/gasp/Verilog.java b/src/edu/berkeley/fleet/gasp/Verilog.java new file mode 100644 index 0000000..073d2b0 --- /dev/null +++ b/src/edu/berkeley/fleet/gasp/Verilog.java @@ -0,0 +1,463 @@ +package edu.berkeley.fleet.verilog; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.*; +import java.lang.reflect.*; +import edu.berkeley.sbp.chr.*; +import edu.berkeley.sbp.misc.*; +import edu.berkeley.sbp.meta.*; +import edu.berkeley.sbp.util.*; +import java.util.*; +import java.io.*; +import static edu.berkeley.fleet.ies44.InstructionEncoder.*; + +public class Verilog { + + 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); } + 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 { + public String condition; + public 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 { + 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 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 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(); } + } + + 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; } + } + + public static class Module { + public void dump(String prefix) throws IOException { + PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/bitfields.v"))); + pw.println("`define DATAWIDTH "+WIDTH_WORD); + pw.println("`define CODEBAG_SIZE_BITS "+CBD_SIZE.valmaskwidth); + pw.println("`define INSTRUCTION_WIDTH "+WIDTH_WORD); + pw.println("`define packet_token(p) "+PACKET_TOKEN.verilogVal("p")); + pw.println("`define packet_data(p) "+PACKET_DATA.verilogVal("p")); + pw.println("`define packet_dest(p) "+PACKET_DEST.verilogVal("p")); + pw.println("`define instruction_dest(p) "+DISPATCH_PATH.verilogVal("p")); + pw.flush(); + pw.close(); + pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(prefix+"/"+name+".v"))); + dump(pw, true); + pw.flush(); + } + public int id = 0; + public final String name; + public String getName() { return name; } + public Port getPort(String name) { return ports.get(name); } + + public HashSet instantiatedModules = new HashSet(); + public final ArrayList events = new ArrayList(); + + // FIXME: always-alphabetical convention? + public final HashMap ports = new HashMap(); + public final ArrayList portorder = new ArrayList(); + public final HashMap statewires = new HashMap(); + public final HashMap latches = new HashMap(); + + 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 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; + } + + 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 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 final long initial; + public Latch(String name, int width) { this(name, width, 0); } + public Latch(String name, int width, long initial) { + this.width = width; + 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 Assignable getAssignableBits(int high, int low) { return new SimpleValue(getVerilogName(), high, low); } + public String doReset() { return name+"<="+initial+";"; } + public void dump(PrintWriter pw) { + pw.println(" reg ["+(width-1)+":0] "+name+";"); + pw.println(" initial "+name+"="+initial+";"); + } + } + + public abstract class Port implements Action, Assignable, Trigger { + public abstract String doReset(); + public final String name; + public String getName() { return name; } + public final int width; + public int getWidth() { return width; } + public boolean hasLatch = false; + public boolean external; + public Port(String name, int width, boolean external) { + this.width = width; + this.name = name; + this.external = external; + ports.put(name, this); + 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(); + public abstract String getSimpleInterface(); + public abstract String getDeclaration(); + public abstract String getAssignments(); + public abstract void connect(SinkPort driven); + } + + public static class InstantiatedModule { + public final Module module; + public final Module thisModule; + public final int id; + public final HashMap ports = new HashMap(); + 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()); + 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 class SourcePort extends Port implements Value { + public 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() { + StringBuffer sb = new StringBuffer(); + if (external) { + sb.append("input " + name +"_r;\n"); + sb.append("output " + name +"_a_;\n"); + sb.append("input ["+(width-1)+":0]" + name +";\n"); + } else { + sb.append("wire " + name +"_r;\n"); + sb.append("wire ["+(width-1)+":0]" + name +";\n"); + } + if (!hasLatch) { + sb.append("wire " + name +"_a;\n"); + } else { + 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 getAssignments() { + StringBuffer sb = new StringBuffer(); + 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"); + sb.append("assign " + driven.name +" = " + name + ";\n"); + } + return sb.toString(); + } + public void connect(SinkPort driven) { + this.driven = driven; + } + } + public class SinkPort extends Port { + public boolean forceNoLatch = false; + public SinkPort driven = null; + 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; } + public String getInterface() { return name+"_r_, "+name+"_a, "+name+"_"; } + public String getSimpleInterface() { return name+"_r, "+name+"_a, "+name; } + public String getDeclaration() { + StringBuffer sb = new StringBuffer(); + if (external) { + sb.append("output " + name +"_r_;\n"); + sb.append("input " + name +"_a;\n"); + sb.append("output ["+(width-1)+":0]" + name +"_;\n"); + } else { + sb.append("wire " + name +"_a;\n"); + } + + if (forceNoLatch) { + sb.append("reg " + name +"_r;\n"); + sb.append("initial " + name +"_r = 0;\n"); + sb.append("wire ["+(width-1)+":0]" + name +";\n"); + } else if (!hasLatch) { + sb.append("wire " + name +"_r;\n"); + sb.append("wire ["+(width-1)+":0]" + name +";\n"); + } else { + sb.append("reg " + name +"_r;\n"); + sb.append("initial " + name +"_r = 0;\n"); + sb.append("reg ["+(width-1)+":0]" + name +";\n"); + sb.append("initial " + name +" = 0;\n"); + } + return sb.toString(); + } + public String doReset() { + return forceNoLatch + ? name+"_r<=0;" + : hasLatch + ? (name+"_r<=0; "+name+"<=0;") + : ""; + } + public String getAssignments() { + StringBuffer sb = new StringBuffer(); + if (external) { + sb.append("assign " + name +"_r_ = " + name + "_r;\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"); + sb.append("assign " + driven.name +" = " + name + ";\n"); + } + return sb.toString(); + } + public void connect(SinkPort driven) { + this.driven = driven; + } + } + + public void dump(PrintWriter pw, boolean fix) { + pw.println("`include \"macros.v\""); + pw.println("module "+name+"(clk, rst "); + for(String name : portorder) { + Port p = ports.get(name); + pw.println(" , " + p.getInterface()); + } + pw.println(" );"); + pw.println(); + pw.println(" input clk;"); + pw.println(" input rst;"); + 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); + 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()); + 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(Event a : events) a.dump(pw, fix); + pw.println(" begin end"); + pw.println(" end"); + pw.println(" end"); + + pw.println(crap); + pw.println("endmodule"); + } + + public class Event { + public Object[] triggers; + public Object[] actions; + 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=0; i--) - os.write(getIntField(i*8+7, i*8, instr)); - } + os.write(BitManipulations.getIntField(i*8+7, i*8, instr)); + } -} \ No newline at end of file + private static long flagFunctionToLong(FlagFunction ff) { + long ret = 0; + for(Predicate p : ff) + switch(p) { + case FlagA : ret = SET_FLAGS_VALUE_A .set(ret); break; + case NotFlagA : ret = SET_FLAGS_VALUE_NOT_A.set(ret); break; + case FlagB : ret = SET_FLAGS_VALUE_B .set(ret); break; + case NotFlagB : ret = SET_FLAGS_VALUE_NOT_B.set(ret); break; + case FlagC : ret = SET_FLAGS_VALUE_C .set(ret); break; + case NotFlagC : ret = SET_FLAGS_VALUE_NOT_C.set(ret); break; + default: throw new RuntimeException(); + } + return ret; + } +} diff --git a/src/edu/berkeley/fleet/interpreter/Inbox.java b/src/edu/berkeley/fleet/interpreter/Inbox.java index 4fe5cb5..6d2f8ad 100644 --- a/src/edu/berkeley/fleet/interpreter/Inbox.java +++ b/src/edu/berkeley/fleet/interpreter/Inbox.java @@ -2,10 +2,11 @@ package edu.berkeley.fleet.interpreter; import edu.berkeley.sbp.util.ANSI; import edu.berkeley.fleet.api.*; import static edu.berkeley.fleet.util.BitManipulations.*; +import edu.berkeley.fleet.two.*; import java.util.*; /** this is a generic inbox which stores <32-bit items (tokens or data) */ -public class Inbox extends InstructionPump { +public class Inbox extends InstructionDock { public boolean dataReadyForShip() { return itemReadyForShip; } public Packet removePacketForShip() { remove(); return register; } @@ -25,11 +26,8 @@ public class Inbox extends InstructionPump { /** if an ack token is pending, this is where it should be sent once the item is accepted */ private Packet bufferedAck = null; - public boolean isInbox() { return true; } - public boolean isOutbox() { return false; } - - public Inbox(InterpreterShip ship, String name) { super(ship, name, new String[] { "" }); } - public Inbox(InterpreterShip ship, String name, String[] ports) { super(ship, name, ports); } + public Inbox(InterpreterShip ship, DockDescription dd) { super(ship, new String[] { "" }, dd); } + public Inbox(InterpreterShip ship, String[] ports, DockDescription dd) { super(ship, ports, dd); } public void addDataFromFabric(Packet packet) { itemsFromFabric.add(packet); } private void remove() { @@ -54,6 +52,7 @@ public class Inbox extends InstructionPump { // if no instruction waiting, do nothing if (instruction_ == null) return false; + /* if (instruction_ instanceof Instruction.Literal) { register = new Packet(getInterpreter(), null, ((Instruction.Literal)instruction_).literal, null); return true; @@ -67,6 +66,7 @@ public class Inbox extends InstructionPump { register = new Packet(getInterpreter(), null, val, null); return true; } + */ Instruction.Move instruction = (Instruction.Move)instruction_; // check firing conditions @@ -78,7 +78,7 @@ public class Inbox extends InstructionPump { // consume inbound data+token if (instruction.dataIn) { - if (instruction.latch) { + if (instruction.latchData) { register = itemsFromFabric.remove(); } else { itemsFromFabric.remove(); @@ -91,12 +91,12 @@ public class Inbox extends InstructionPump { // and make note of the fact that we need to send an ack (if requested) if (instruction.tokenOut) - bufferedAck = new Packet(getInterpreter(), this, 0, (InterpreterDestination)instruction.dest); + bufferedAck = new Packet(getInterpreter(), this, 0, (InterpreterDestination)(Object)instruction.path); } else if (instruction.tokenOut) { // if dataOut is not set, we can send the data immediately - new Packet(getInterpreter(), this, 0, (InterpreterDestination)instruction.dest).send(); + new Packet(getInterpreter(), this, 0, (InterpreterDestination)(Object)instruction.path).send(); } return true; } diff --git a/src/edu/berkeley/fleet/interpreter/InstructionPump.java b/src/edu/berkeley/fleet/interpreter/InstructionDock.java similarity index 69% rename from src/edu/berkeley/fleet/interpreter/InstructionPump.java rename to src/edu/berkeley/fleet/interpreter/InstructionDock.java index 7058ae4..8bd6a7d 100644 --- a/src/edu/berkeley/fleet/interpreter/InstructionPump.java +++ b/src/edu/berkeley/fleet/interpreter/InstructionDock.java @@ -1,18 +1,20 @@ package edu.berkeley.fleet.interpreter; import edu.berkeley.sbp.util.ANSI; +import edu.berkeley.fleet.two.*; import edu.berkeley.fleet.api.*; -import edu.berkeley.fleet.doc.*; import edu.berkeley.fleet.api.Instruction; +import static edu.berkeley.fleet.api.Predicate.*; import java.util.*; /** anything that has a source (instruction horn) address on the switch fabric */ -abstract class InstructionPump extends InterpreterPump { +abstract class InstructionDock extends InterpreterDock { - public int clogged = 0; + public int tailged = 0; public boolean flag_a = false; public boolean flag_b = false; + public boolean flag_c = false; /** the currently executing instruction */ private Instruction executing = null; @@ -23,8 +25,8 @@ abstract class InstructionPump extends InterpreterPump { public int loopCounter = 0; private int repeatCounter = 1; - InstructionPump(InterpreterShip ship, String name, String[] ports) { - super(ship, name, ports); + InstructionDock(InterpreterShip ship, String[] ports, DockDescription bbd) { + super(ship, ports, bbd); } public void massacre() { @@ -65,35 +67,33 @@ abstract class InstructionPump extends InterpreterPump { protected abstract long peekDataLatch(); protected final void service() { - if (clogged > 0) return; + /* + if (tailged > 0) return; if (executing==null && instructions.size() > 0) executing = instructions.remove(); if (executing==null) return; - if (executing instanceof Instruction.Clog) { - clogged++; - executing = null; - return; - } - boolean enabled = true; if (executing instanceof Instruction.PredicatedInstruction) { Instruction.PredicatedInstruction ip = (Instruction.PredicatedInstruction)executing; switch(ip.predicate) { - case Instruction.PredicatedInstruction.P_ALWAYS: enabled = true; break; - case Instruction.PredicatedInstruction.P_IF_A: enabled = flag_a; break; - case Instruction.PredicatedInstruction.P_IF_B: enabled = flag_b; break; - case Instruction.PredicatedInstruction.P_IF_Z: enabled = loopCounter==0; break; + case IgnoreOLC: enabled = true; break; + case Default: enabled = loopCounter!=0; break; + case FlagA: enabled = flag_a; break; + case FlagB: enabled = flag_b; break; + //case FlagC: enabled = ; break; + case NotFlagA: enabled = !flag_a; break; + case NotFlagB: enabled = !flag_b; break; + //case NotFlagC: enabled = loopCounter==0; break; } } int oldLoopCounter = loopCounter; if (enabled) { - if (executing.isDL()) loopCounter = Math.max(0, loopCounter-1); - + if (executing instanceof Instruction.Set.OLC.Decrement) loopCounter = Math.max(0, loopCounter-1); if (executing instanceof Instruction.Counter) { Instruction.Counter ic = (Instruction.Counter)executing; if (ic.source == Instruction.Counter.LOOP_COUNTER && ic.dest == Instruction.Counter.DATA_LATCH) { - setDataLatch(oldLoopCounter); /* FIXME: which is correct here? */ + setDataLatch(oldLoopCounter); // FIXME: which is correct here? } else if (ic.dest == Instruction.Counter.LOOP_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) { loopCounter = (int)peekDataLatch(); } else if (ic.dest == Instruction.Counter.REPEAT_COUNTER && ic.source == Instruction.Counter.DATA_LATCH) { @@ -107,10 +107,9 @@ abstract class InstructionPump extends InterpreterPump { repeatCounter = ic.source; } - } else if (executing instanceof Instruction.SetFlags) { - Instruction.SetFlags sf = (Instruction.SetFlags)executing; - boolean old_s = ((peekDataLatch() >> (getInterpreter().getWordSize()-1)) & 1) != 0; - boolean old_z = oldLoopCounter == 0; + } else if (executing instanceof Instruction.Set.Flags) { + Instruction.Set.Flags sf = (Instruction.Set.Flags)executing; + boolean old_c = oldLoopCounter == 0; boolean old_a = flag_a; boolean old_b = flag_b; flag_a = @@ -118,37 +117,35 @@ abstract class InstructionPump extends InterpreterPump { (((sf.flag_a & sf.FLAG_NOT_A) != 0) ? !old_a : false) | (((sf.flag_a & sf.FLAG_B) != 0) ? old_b : false) | (((sf.flag_a & sf.FLAG_NOT_B) != 0) ? !old_b : false) | - (((sf.flag_a & sf.FLAG_Z) != 0) ? old_z : false) | - (((sf.flag_a & sf.FLAG_NOT_Z) != 0) ? !old_z : false) | - (((sf.flag_a & sf.FLAG_S) != 0) ? old_s : false) | - (((sf.flag_a & sf.FLAG_NOT_S) != 0) ? !old_s : false); + (((sf.flag_a & sf.FLAG_C) != 0) ? old_c : false) | + (((sf.flag_a & sf.FLAG_NOT_C) != 0) ? !old_c : false); flag_b = (((sf.flag_b & sf.FLAG_A) != 0) ? old_a : false) | (((sf.flag_b & sf.FLAG_NOT_A) != 0) ? !old_a : false) | (((sf.flag_b & sf.FLAG_B) != 0) ? old_b : false) | (((sf.flag_b & sf.FLAG_NOT_B) != 0) ? !old_b : false) | - (((sf.flag_b & sf.FLAG_Z) != 0) ? old_z : false) | - (((sf.flag_b & sf.FLAG_NOT_Z) != 0) ? !old_z : false) | - (((sf.flag_b & sf.FLAG_S) != 0) ? old_s : false) | - (((sf.flag_b & sf.FLAG_NOT_S) != 0) ? !old_s : false); - } else if (executing instanceof Instruction.DecrLoop) { + (((sf.flag_b & sf.FLAG_C) != 0) ? old_c : false) | + (((sf.flag_b & sf.FLAG_NOT_C) != 0) ? !old_c : false); + } else if (executing instanceof Instruction.Set.OLC.Decrement) { } else { if (!service(executing)) return; } } if (executing==null) return; - if (executing.isRepeating() && repeatCounter > 1) { + if ((executing instanceof Instruction.Move) && repeatCounter > 1) { repeatCounter--; - } else if (executing.isRepeating() && repeatCounter == -1) { + } else if ((executing instanceof Instruction.Move) && repeatCounter == -1) { // repeat - } else if (executing.isLooping() && oldLoopCounter > 0) { + } else if ((executing instanceof Instruction.PredicatedInstruction && ((Instruction.PredicatedInstruction)executing).looping) && oldLoopCounter > 0) { addInstruction(executing); executing = null; } else { executing = null; } + */ } + } diff --git a/src/edu/berkeley/fleet/interpreter/Interpreter.java b/src/edu/berkeley/fleet/interpreter/Interpreter.java index cc5650b..5db6ae1 100644 --- a/src/edu/berkeley/fleet/interpreter/Interpreter.java +++ b/src/edu/berkeley/fleet/interpreter/Interpreter.java @@ -5,12 +5,23 @@ import java.util.concurrent.*; import java.lang.reflect.*; import edu.berkeley.fleet.*; import edu.berkeley.sbp.util.ANSI; -import edu.berkeley.fleet.doc.*; import edu.berkeley.fleet.api.*; import edu.berkeley.fleet.ies44.*; +import edu.berkeley.fleet.assembler.*; +import edu.berkeley.fleet.two.*; +import edu.berkeley.fleet.util.*; + +public class Interpreter extends Fleet implements Parser.FleetWithDynamicShips { + + public Ship getShip(String type, int ordinal) { + for(Ship s : this) + if (s.getType().equals(type)) + if (ordinal-- < 0) + return s; + return null; + } -public class Interpreter extends Fleet implements Fleet.WithDynamicShips { - + public int getWordWidth() { return 37; } /** some "halt ship" can turn this on to stop the interpreter */ private HashMap ships = new HashMap(); private BlockingQueue debugStream = new LinkedBlockingQueue(); @@ -20,13 +31,18 @@ public class Interpreter extends Fleet implements Fleet.WithDynamicShips { public FleetProcess run(final byte[] instructions) { try { final FleetProcess fp = new FleetProcess() { + public void dispatchInstruction(Instruction i) { throw new RuntimeException(); } public void invokeInstruction(Instruction i) { throw new RuntimeException("not supported"); } - public long readWord() { + public Dock getDebugInputDock() { return null; } + public BitVector readWord() { + /* try { return debugStream.take(); } catch (Exception e) { throw new RuntimeException(e); - } } + }*/ + throw new RuntimeException(); + } protected void _terminate() { // FIXME: hack ships = new HashMap(); @@ -43,10 +59,14 @@ public class Interpreter extends Fleet implements Fleet.WithDynamicShips { iscratch = (InterpreterShip)ship; break; } - if (iscratch==null) + if (iscratch==null) { + BufferedReader br = + new BufferedReader(new InputStreamReader(new FileInputStream("ships/Memory.ship"))); + ShipDescription sd = new ShipDescription("Memory", br); iscratch = (InterpreterShip)Class.forName("edu.berkeley.fleet.interpreter.Memory") - .getConstructor(new Class[] { Interpreter.class, String.class }) - .newInstance(new Object[] { Interpreter.this, "memory" }); + .getConstructor(new Class[] { Interpreter.class, String.class, ShipDescription.class }) + .newInstance(new Object[] { Interpreter.this, "memory", sd }); + } iscratch .getClass() .getMethod("boot", new Class[] { byte[].class }) @@ -83,27 +103,14 @@ public class Interpreter extends Fleet implements Fleet.WithDynamicShips { public void dispatch(Instruction i, long address) { Log.dispatch(i); - if (i instanceof Instruction.CodeBagDescriptor) { - Instruction.CodeBagDescriptor cbd = (Instruction.CodeBagDescriptor)i; - long absolute_cbd = ((cbd.offset+address) << 6) | cbd.size; - throw new RuntimeException(); - //new Packet(this, null, (int)absolute_cbd, (InterpreterDestination)cbd.pump).send(); - - } else if (i instanceof Instruction.UnClog) { - Instruction.UnClog ic = (Instruction.UnClog)i; - ((InstructionPump)(ic.pump)).clogged--; - - } else if (i instanceof Instruction.Kill) { - InterpreterPump pump = (InterpreterPump)(((Instruction.Kill)i).pump); - ((InstructionPump)pump).kill(); - - } else if (i instanceof Instruction.Massacre) { - InterpreterPump pump = (InterpreterPump)(((Instruction.Massacre)i).pump); - ((InstructionPump)pump).massacre(); + + if (i instanceof Instruction.Tail) { + Instruction.Tail ic = (Instruction.Tail)i; + ((InstructionDock)(ic.dock)).tailged--; } else { - InterpreterPump sourcePump = (InterpreterPump)(((Instruction)i).pump); - ((InstructionPump)sourcePump).addInstruction(((Instruction)i)); + InterpreterDock sourceDock = (InterpreterDock)(((Instruction)i).dock); + ((InstructionDock)sourceDock).addInstruction(((Instruction)i)); } } @@ -112,14 +119,14 @@ public class Interpreter extends Fleet implements Fleet.WithDynamicShips { public Ship createShip(String shipType, String shipname) { try { Class c = Class.forName("edu.berkeley.fleet.interpreter."+shipType); - Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class }); - InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname }); + Constructor con = c.getConstructor(new Class[] { Interpreter.class, String.class, ShipDescription.class }); BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ships/"+shipType+".ship"))); - ShipDescription sd = new ShipDescription(shipname, br); - ret.setShipDescription(sd); + ShipDescription sd = new ShipDescription(shipType, br); + InterpreterShip ret = (InterpreterShip)con.newInstance(new Object[] { this, shipname, sd }); ships.put(shipname, ret); return ret; } catch (Exception e) { + e.printStackTrace(); return null; } } @@ -136,24 +143,28 @@ public class Interpreter extends Fleet implements Fleet.WithDynamicShips { // Instruction Encoding ///////////////////////////////////////////////////////////////////////// public final InterpreterInstructionEncoder iie = new InterpreterInstructionEncoder(); - public Instruction readInstruction(DataInputStream is) throws IOException { return iie.readInstruction(is); } - public Instruction readInstruction(long instr) { return iie.readInstruction(instr); } - public long writeInstruction(Instruction d) { return writeInstruction(d); } - public void writeInstruction(DataOutputStream os, Instruction d) throws IOException { iie.writeInstruction(os, d); } + public Instruction readInstruction(DataInputStream is, Dock dispatchFrom) throws IOException { return iie.readInstruction(dispatchFrom, is); } + public Instruction readInstruction(Dock dispatchFrom, long instr) { return iie.readInstruction(dispatchFrom, instr); } + public long writeInstruction(Dock dispatchFrom, Instruction d) { return writeInstruction(dispatchFrom, d); } + public void writeInstruction(DataOutputStream os, Dock dispatchFrom, Instruction d) throws IOException { iie.writeInstruction(os, dispatchFrom, d); } + public Dock getUniversalSource() { return null; } public class InterpreterInstructionEncoder extends InstructionEncoder { - public long getDestAddr(Destination box) { return ((InterpreterDestination)box).getDestAddr(); } - public long getBoxInstAddr(Pump box) { return ((InterpreterPump)box).getDestAddr(); } + public Dock getUniversalSource() { return null; } + public long getDestAddr(Path path) { throw new RuntimeException(); } + public long getBoxInstAddr(Dock box) { return ((InterpreterDock)box).getDestAddr(); } + public Path getPathByAddr(Dock source, long dest) { throw new RuntimeException(); } public Destination getDestByAddr(long dest) { + /* for(Ship ship : Interpreter.this) - for(Pump bb : ship.getPumps()) - for(Destination d : bb.getDestinations()) - if (getDestAddr(d)==dest) - return d; + for(Dock bb : ship) + if (getDestAddr(bb.getDataDestination())==dest) + return bb.getDataDestination(); + */ return null; } - public Pump getBoxByInstAddr(long dest) { + public Dock getBoxByInstAddr(long dest) { for(Ship ship : Interpreter.this) - for(Pump bb : ship.getPumps()) + for(Dock bb : ship) if (getBoxInstAddr(bb) == dest) return bb; return null; @@ -175,36 +186,33 @@ public class Interpreter extends Fleet implements Fleet.WithDynamicShips { pw.println("package edu.berkeley.fleet.interpreter;"); pw.println("import edu.berkeley.sbp.util.ANSI;"); pw.println("import edu.berkeley.fleet.api.*;"); + pw.println("import edu.berkeley.fleet.two.*;"); pw.println("import edu.berkeley.fleet.*;"); pw.println("import java.util.*;"); pw.println("import java.io.*;"); pw.println(""); pw.println("public class "+filename+" extends InterpreterShip {"); pw.println(""); - for(PumpDescription b : sd) { + for(DockDescription b : sd) { String name = b.getName(); pw.print(" "); - if ( b.isInbox()) pw.print("Inbox"); - if (!b.isInbox()) pw.print("Outbox"); + if ( b.isInputDock()) pw.print("Inbox"); + if (!b.isInputDock()) pw.print("Outbox"); pw.print(" box_"); pw.print(name); pw.print(" = new "); - if ( b.isInbox()) pw.print("Inbox"); - if (!b.isInbox()) pw.print("Outbox"); - pw.print("(this, \""+name+"\", new String[] { "); + if ( b.isInputDock()) pw.print("Inbox"); + if (!b.isInputDock()) pw.print("Outbox"); + pw.print("(this, new String[] { "); boolean first = true; - for(String destination : b) { - if (!first) pw.print(", "); - first = false; - pw.print("\""+destination+"\""); - } - pw.println("});"); + pw.print("\"\""); + pw.println("}, shipDescription.getDockDescription(\""+name+"\"));"); } pw.println(""); - pw.println(" public "+filename+"(Interpreter fleet, String name) {"); - pw.println(" super(fleet, name, \""+filename+"\");"); - for(PumpDescription b : sd) - pw.println(" addPump(\""+b.getName()+"\", box_"+b.getName()+");"); + pw.println(" public "+filename+"(Interpreter fleet, String name, ShipDescription sd) {"); + pw.println(" super(fleet, name, sd);"); + for(DockDescription b : sd) + pw.println(" addDock(\""+b.getName()+"\", box_"+b.getName()+");"); pw.println(" }"); pw.println(""); pw.println(sd.getSection("fleeterpreter")); diff --git a/src/edu/berkeley/fleet/interpreter/InterpreterDestination.java b/src/edu/berkeley/fleet/interpreter/InterpreterDestination.java index 87748bd..ac466c8 100644 --- a/src/edu/berkeley/fleet/interpreter/InterpreterDestination.java +++ b/src/edu/berkeley/fleet/interpreter/InterpreterDestination.java @@ -3,7 +3,8 @@ import edu.berkeley.fleet.api.*; import java.util.*; abstract class InterpreterDestination extends Destination { + public InterpreterDestination(InterpreterDock d, boolean isInstructionDestination) { super(d); } public abstract long getDestAddr(); public abstract void addDataFromFabric(Packet packet); public abstract String getDestinationName(); -} \ No newline at end of file +} diff --git a/src/edu/berkeley/fleet/interpreter/InterpreterPump.java b/src/edu/berkeley/fleet/interpreter/InterpreterDock.java similarity index 63% rename from src/edu/berkeley/fleet/interpreter/InterpreterPump.java rename to src/edu/berkeley/fleet/interpreter/InterpreterDock.java index 42a65cd..a0e8dc5 100644 --- a/src/edu/berkeley/fleet/interpreter/InterpreterPump.java +++ b/src/edu/berkeley/fleet/interpreter/InterpreterDock.java @@ -1,32 +1,28 @@ package edu.berkeley.fleet.interpreter; -import edu.berkeley.fleet.doc.*; import edu.berkeley.fleet.api.*; -import edu.berkeley.fleet.api.Pump; +import edu.berkeley.fleet.api.Dock; +import edu.berkeley.fleet.two.*; import java.util.*; + /** anything that has a destination address on the switch fabric */ -public abstract class InterpreterPump extends Pump { +public abstract class InterpreterDock extends FleetTwoDock { - private final String name; private final InterpreterShip ship; private final Destination[] ports; private final int addr = max_addr++; - private PumpDescription bbd; - - public void setDescription(PumpDescription bbd) { - this.bbd = bbd; - } - public long resolveLiteral(String literal) { - return bbd.resolveLiteral(literal); - } - public InterpreterPump(InterpreterShip ship, String name, String[] ports) { + public InterpreterDock(InterpreterShip ship, String[] ports, DockDescription bbd) { + super(ship, bbd); this.ship = ship; - this.name = name; this.ports = new Destination[ports.length]; for(int i=0; i getDestinations() { @@ -35,6 +31,14 @@ public abstract class InterpreterPump extends Pump { return ret; } + public Destination getInstructionDestination() { + return ports[0]; + } + public Destination getDataDestination() { + return ports[0]; + } + + /** adds the included datum to the port from the switch fabric side */ public abstract void addDataFromFabric(Packet packet); @@ -44,23 +48,24 @@ public abstract class InterpreterPump extends Pump { public Ship getShip() { return ship; } public Fleet getFleet() { return getShip().getFleet(); } - public String toString() { return ship+"."+name; } - public String getName() { return name; } - public int getInstructionFifoLength() { return 4; } + public String toString() { return ship+"."+getName(); } + public int getInstructionFifoSize() { return 4; } Interpreter getInterpreter() { return ((InterpreterShip)getShip()).getInterpreter(); } public long getDestAddr() { return addr; } private static int max_addr; - - private class InterpreterPumpDestination extends InterpreterDestination { + private class InterpreterDockDestination extends InterpreterDestination { public String name; public long addr = max_addr++; - public InterpreterPumpDestination(String name) { this.name = name; } + public InterpreterDockDestination(String name, InterpreterDock id, boolean isInstructionDestination) { + super(id, isInstructionDestination); + this.name = name; + } public String getDestinationName() { return name; } - public Ship getShip() { return InterpreterPump.this.getShip(); } - public void addDataFromFabric(Packet packet) { InterpreterPump.this.addDataFromFabric(packet); } + public Ship getShip() { return InterpreterDock.this.getShip(); } + public void addDataFromFabric(Packet packet) { InterpreterDock.this.addDataFromFabric(packet); } public String toString() { return getShip()+"."+getName(); } public long getDestAddr() { return addr; } } diff --git a/src/edu/berkeley/fleet/interpreter/InterpreterShip.java b/src/edu/berkeley/fleet/interpreter/InterpreterShip.java index 83fdaec..37c10cd 100644 --- a/src/edu/berkeley/fleet/interpreter/InterpreterShip.java +++ b/src/edu/berkeley/fleet/interpreter/InterpreterShip.java @@ -1,35 +1,21 @@ package edu.berkeley.fleet.interpreter; import edu.berkeley.fleet.api.*; -import edu.berkeley.fleet.doc.*; +import edu.berkeley.fleet.two.*; import java.util.*; import java.io.*; /** a ship, which belongs to a fleet and which may have many ports */ -abstract class InterpreterShip extends Ship { +abstract class InterpreterShip extends FleetTwoShip { /** You should instantiate a bunch of Inboxes and Outboxes in your constructor */ - public InterpreterShip(Interpreter fleet, String name, String type) { - this.fleet = fleet; - this.type = type; + public InterpreterShip(Interpreter fleet, String name, ShipDescription sd) { + super(fleet, sd); } - private Interpreter fleet; - private String type; - private HashMap ports = new HashMap(); + private HashMap ports = new HashMap(); - public Iterable getPumps() { return (Iterable)(Object)ports.values(); } - public String getType() { return type; } - public Fleet getFleet() { return fleet; } - public Interpreter getInterpreter() { return fleet; } - - public void setShipDescription(ShipDescription sd) { - for(InterpreterPump ibb : ports.values()) { - for(PumpDescription bbd : sd) { - if (bbd.getName().equals(ibb.getName())) - ibb.setDescription(bbd); - } - } - } + public Iterator iterator() { return (Iterator)(Object)ports.values().iterator(); } + public Interpreter getInterpreter() { return (Interpreter)getFleet(); } /** * Override this method, check inboxes for the data you need, and @@ -39,16 +25,16 @@ abstract class InterpreterShip extends Ship { public abstract void service(); public final void _service() { - for(InterpreterPump p : ports.values()) p.service(); + for(InterpreterDock p : ports.values()) p.service(); service(); } - protected void addPump(String name, InterpreterPump port) { + protected void addDock(String name, InterpreterDock port) { ports.put(name, port); } public void shutdown() { - for(InterpreterPump p : ports.values()) + for(InterpreterDock p : ports.values()) p.shutdown(); } } diff --git a/src/edu/berkeley/fleet/interpreter/Log.java b/src/edu/berkeley/fleet/interpreter/Log.java index e012e32..9fbd93c 100644 --- a/src/edu/berkeley/fleet/interpreter/Log.java +++ b/src/edu/berkeley/fleet/interpreter/Log.java @@ -36,13 +36,13 @@ public class Log { println(ANSI.green("dispatch: " + indent(d+"", " "))); } - public static void data(String data, Pump source, Destination dest) { + public static void data(String data, Dock source, Destination dest) { println((" data: ") + indent(ANSI.purple(data) + (source==null ? "" : (" : " + source))+(" -> "+ANSI.purple(""+dest)), " ")); } - public static void token(Pump source, Destination dest) { + public static void token(Dock source, Destination dest) { println(ANSI.purple(" token: ") + (source + " -> " + ANSI.purple(dest+""))); } diff --git a/src/edu/berkeley/fleet/interpreter/Outbox.java b/src/edu/berkeley/fleet/interpreter/Outbox.java index 3a9d411..f3efd49 100644 --- a/src/edu/berkeley/fleet/interpreter/Outbox.java +++ b/src/edu/berkeley/fleet/interpreter/Outbox.java @@ -5,9 +5,10 @@ import edu.berkeley.fleet.ies44.*; import edu.berkeley.sbp.util.*; import edu.berkeley.fleet.util.*; import static edu.berkeley.fleet.util.BitManipulations.*; +import edu.berkeley.fleet.two.*; import edu.berkeley.fleet.api.Instruction; -public class Outbox extends InstructionPump { +public class Outbox extends InstructionDock { /** are we ready to accept another item from the ship? */ private boolean readyForDataFromShip = false; @@ -22,15 +23,14 @@ public class Outbox extends InstructionPump { /** the latched value */ private long register; - public boolean isInbox() { return false; } - public boolean isOutbox() { return true; } - public Outbox(InterpreterShip ship, String name) { this(ship, name, new String[] { "" }); } - public Outbox(InterpreterShip ship, String name, String[] ports) { super(ship, name, ports); } + public Outbox(InterpreterShip ship, DockDescription dd) { this(ship, new String[] { "" }, dd); } + public Outbox(InterpreterShip ship, String[] ports, DockDescription dd) { super(ship, ports, dd); } protected void setDataLatch(long value) { register = value; } protected long peekDataLatch() { return register; } protected final boolean service(Instruction instruction_) { + /* if (instruction_ instanceof Instruction.Literal) { register = ((Instruction.Literal)instruction_).literal; return true; @@ -42,6 +42,7 @@ public class Outbox extends InstructionPump { : setField(18, 0, ll.literal, register); return true; } + */ Instruction.Move instruction = (Instruction.Move)instruction_; // if no instruction waiting, do nothing @@ -59,24 +60,24 @@ public class Outbox extends InstructionPump { // consume item if (instruction.dataIn) { haveDataFromShip = false; - if (instruction.latch) + if (instruction.latchData) register = itemPresentedByShip; } if (instruction.dataOut) { // if item to be transmitted, send it - InterpreterDestination dest = (InterpreterDestination)instruction.dest; - if (instruction.dataOutDest) { + InterpreterDestination dest = (InterpreterDestination)(Object)instruction.path; + if (instruction.latchPath) { // FIXME: still not supported - long bits = InstructionEncoder.PUMP_NAME.getval(register); - getInterpreter().dispatch(((Interpreter)getInterpreter()).iie.readInstruction(register), bits); + long bits = InstructionEncoder.DISPATCH_PATH.getval(register); + getInterpreter().dispatch(((Interpreter)getInterpreter()).iie.readInstruction(null, register), bits); /* dest = (InterpreterDestination)(((Interpreter)getInterpreter()).iie.getDestByAddr(bits)); if (dest == null) { if (pump != null) { - Pump pump = ((Interpreter)getInterpreter()).iie.getDestByInstAddr(bits); + Dock pump = ((Interpreter)getInterpreter()).iie.getDestByInstAddr(bits); } } */ @@ -90,7 +91,7 @@ public class Outbox extends InstructionPump { } else if (instruction.tokenOut) { // if no item was sent, we might still send an ack - new Packet(getInterpreter(), this, 0, (InterpreterDestination)instruction.dest).send(); + new Packet(getInterpreter(), this, 0, (InterpreterDestination)(Object)instruction.path).send(); } return true; diff --git a/src/edu/berkeley/fleet/interpreter/Packet.java b/src/edu/berkeley/fleet/interpreter/Packet.java index 3042201..8b5c940 100644 --- a/src/edu/berkeley/fleet/interpreter/Packet.java +++ b/src/edu/berkeley/fleet/interpreter/Packet.java @@ -5,7 +5,6 @@ import java.util.concurrent.*; import java.lang.reflect.*; import edu.berkeley.fleet.*; import edu.berkeley.sbp.util.ANSI; -import edu.berkeley.fleet.doc.*; import edu.berkeley.fleet.api.*; import edu.berkeley.fleet.ies44.*; @@ -15,7 +14,7 @@ class Packet { long value; InterpreterDestination destination; - public Packet(Interpreter interpreter, InterpreterPump source, long value, InterpreterDestination destination) { + public Packet(Interpreter interpreter, InterpreterDock source, long value, InterpreterDestination destination) { Log.data(value+"", source, (Destination)destination); this.interpreter = interpreter; this.value = value; @@ -26,4 +25,4 @@ class Packet { destination.addDataFromFabric(this); } -} \ No newline at end of file +} diff --git a/src/edu/berkeley/fleet/ir/IR.java b/src/edu/berkeley/fleet/ir/IR.java new file mode 100644 index 0000000..0c670fd --- /dev/null +++ b/src/edu/berkeley/fleet/ir/IR.java @@ -0,0 +1,84 @@ +package edu.berkeley.fleet; + +// interesting primitive: an "atomic" +// take-from-fred-and-deliver-to-mary transition; you can give it +// predecessors and successors. +// -- hitch: this artificially causes fred's successor to wait until +// mary has gotten the data item + + +// Literal gets folded into anything involving a UsesData +// Repeat-literal-count appears to the programmer just as repeat with a separate literal +// FEATURE: apply tachio analysis to ensure kills never get stuck +// FEATURE: ability to save the MSB flag for later use +public class IR { + /* + public interface Nodes extends Iterable { + } + + public class NodesImpl extends Nodes { + public NodesImpl(Node[] ns) { } // FIXME + public NodesImpl(Node n1, Node n2) { this(new Node[] { n1, n2 }); } + public NodesImpl() { this(new Node[0]); } + //public Iterator iterator() { return new SingletonIterator(this); } + } + + public abstract class Node extends Nodes { + public abstract Nodes preds(); + public abstract Nodes succs(); + public Iterator iterator() { return new SingletonIterator(this); } + } + + public class Join extends Node { + public Node succ; + public Nodes preds; + public Nodes preds() { return preds; } + public Nodes succs() { return succ; } + } + public class Fork extends Node { + public Node pred; + public Nodes succs; + public Nodes preds() { return pred; } + public Nodes succs() { return succs; } + } + + public abstract class Linear extends Node { + public Node pred; + public Node succ; + public Nodes preds() { return pred; } + public Nodes succs() { return succ; } + } + + // Actual Instructions ////////////////////////////////////////////////////////////////////////////// + + public class Repeat extends Linear { + public Node bodyFirst; + public Node bodyLast; + public Nodes preds() { return new Nodes(pred, bodyLast); } + public Nodes succs() { return new Nodes(succ, bodyFirst); } + } + + public class RepeatCount extends Repeat implements UsesData { + } + + // if nonnegative then...else... + public class IfThenElse extends Linear implements UsesData { + public Node thenFirst; + public Node thenLast; + public Node elseFirst; + public Node elseLast; + public Join impliedJoin; + } + + public class Break extends Linear { } + + public class Deliver extends Linear implements UsesData { } + public class Recv extends Linear implements UsesData { } // is marked killable if any torpedo "points at" it + public class Collect extends Linear { } + public class Send extends Linear { + public Ship dest; // if null, then this is a "dispatch" + public boolean token; + public boolean torpedo; + } + */ +} diff --git a/src/edu/berkeley/fleet/two/DockDescription.java b/src/edu/berkeley/fleet/two/DockDescription.java new file mode 100644 index 0000000..eaf79d0 --- /dev/null +++ b/src/edu/berkeley/fleet/two/DockDescription.java @@ -0,0 +1,37 @@ +package edu.berkeley.fleet.two; +import edu.berkeley.fleet.api.*; +import java.io.*; +import java.util.*; + +/** NOT YET FINALIZED: A description of a dock on a ship */ +public class DockDescription { + + private final ShipDescription ship; + private final String name; + private final boolean inbox; + private final boolean left; + private final HashMap constants = new HashMap(); + + DockDescription(ShipDescription ship, String name, boolean left, boolean inbox) { + this.left = left; + this.ship = ship; + this.name = name; + this.inbox = inbox; + } + + public String getName() { return name; } + public boolean isInputDock() { return inbox; } + public boolean isOutputDock() { return !inbox; } + + /** Indicates if this dock should be drawn on the "left hand side" of the ship for visual purposes */ + boolean isLeft() { return left; } + + /** Searches the dock-specific constants first, then ship-wide constants */ + public ShipDescription.Constant getConstant(String name) { + ShipDescription.Constant ret = constants.get(name); + if (ret == null) ret = ship.getConstant(name); + return ret; + } + + void addConstant(String s, ShipDescription.Constant c) { constants.put(s, c); } +} diff --git a/src/edu/berkeley/fleet/two/FleetTwoDock.java b/src/edu/berkeley/fleet/two/FleetTwoDock.java new file mode 100644 index 0000000..5b7807a --- /dev/null +++ b/src/edu/berkeley/fleet/two/FleetTwoDock.java @@ -0,0 +1,24 @@ +package edu.berkeley.fleet.two; +import edu.berkeley.fleet.api.*; +import java.util.*; + +/** A dock on a ship */ +public abstract class FleetTwoDock extends Dock { + + private final DockDescription dockDescription; + + public FleetTwoDock(Ship ship, DockDescription dockDescription) { + super(ship); + this.dockDescription = dockDescription; + } + + public String getName() { return dockDescription.getName(); } + + public ShipDescription.Constant getConstant(String s) { return dockDescription.getConstant(s); } + + public boolean isInputDock() { return dockDescription.isInputDock(); } + + public boolean isOutputDock() { return !dockDescription.isInputDock(); } + + +} diff --git a/src/edu/berkeley/fleet/two/FleetTwoShip.java b/src/edu/berkeley/fleet/two/FleetTwoShip.java new file mode 100644 index 0000000..5a89616 --- /dev/null +++ b/src/edu/berkeley/fleet/two/FleetTwoShip.java @@ -0,0 +1,33 @@ +package edu.berkeley.fleet.two; +import edu.berkeley.fleet.api.*; +import java.util.*; + +/** A ship in a Fleet; each ship consists of a collection of Docks */ +public abstract class FleetTwoShip extends Ship { + + protected final ShipDescription shipDescription; + + public FleetTwoShip(Fleet fleet, ShipDescription shipDescription) { + super(fleet); + this.shipDescription = shipDescription; + } + + /** returns the type of the ship ("Fetch", "ALU", etc) */ + public String getType() { return shipDescription.getName(); } + + public Dock getDock(String s) { + for(Dock b : this) + if (b.getName().equals(s)) + return b; + throw new RuntimeException("unknown port \""+getType()+"."+s+"\""); + } + + public int getOrdinal() { + int ord = 0; + for(Ship s : getFleet()) { + if (s==this) return ord; + if (s.getType() != null && s.getType().equals(getType())) ord++; + } + throw new RuntimeException("inconsistency: Ship does not belong to its own Fleet!"); + } +} diff --git a/src/edu/berkeley/fleet/two/ShipDescription.java b/src/edu/berkeley/fleet/two/ShipDescription.java new file mode 100644 index 0000000..13d56de --- /dev/null +++ b/src/edu/berkeley/fleet/two/ShipDescription.java @@ -0,0 +1,211 @@ +package edu.berkeley.fleet.two; +import edu.berkeley.fleet.api.*; +import java.io.*; +import java.util.*; + +/** NOT YET FINALIZED: A description (specification) of a ship */ +public class ShipDescription implements Iterable { + + private String name; + private LinkedHashMap docks = new LinkedHashMap(); + private HashMap sections = new HashMap(); + private HashMap constants = new HashMap(); + + 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 iterator() { return docks.values().iterator(); } + + public ShipDescription(String name, BufferedReader r) throws IOException { + this.name = name; + String sectionName = null; + StringBuffer sb = new StringBuffer(); + while(true) { + String s = r.readLine(); + if (s==null || s.startsWith("==")) { + if (sectionName != null) sections.put(sectionName, sb.toString()); + if (s==null) break; + sb = new StringBuffer(); + sectionName = s.trim(); + while(sectionName.startsWith("=")) + sectionName = sectionName.substring(1); + while(sectionName.endsWith("=")) + sectionName = sectionName.substring(0, sectionName.length()-1); + sectionName = sectionName.trim().toLowerCase(); + continue; + } + sb.append(s+"\n"); + } + for(String s : sections.keySet()) + processSection(s); + } + + public Constant getConstant(String name) { + return constants.get(name); + } + + private void processSection(String section) throws IOException { + if (section.equals("")) { + BufferedReader br = new BufferedReader(new StringReader(sections.get(section))); + for(String s = br.readLine(); s != null; s = br.readLine()) { + if (s.trim().length()==0) continue; + String key = s.substring(0, s.indexOf(':')).trim(); + String val = s.substring(s.indexOf(':')+1).trim(); + if (key.toLowerCase().equals("ship")) + name = val.trim(); + } + } else if (section.equals("constants")) { + BufferedReader br = new BufferedReader(new StringReader(sections.get(section))); + for(String s = br.readLine(); s != null; s = br.readLine()) { + if (s.indexOf(':')==-1) continue; + String key = s.substring(0, s.indexOf(':')).trim(); + if (key.startsWith("constant")) { + String constname = key.substring("constant".length()+1).trim(); + String val = s.substring(s.indexOf(':')+1).trim(); + constants.put(constname, new Constant(val)); + } + } + } else if (section.equals("ports")) { + BufferedReader br = new BufferedReader(new StringReader(sections.get(section))); + boolean rightSide = false; + DockDescription p = null; + for(String s = br.readLine(); s != null; s = br.readLine()) { + if (s.trim().length()==0) { rightSide = true; continue; } + + String key = s.substring(0, s.indexOf(':')).trim(); + boolean inbox = 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("out")) { inbox = false; } + else if (key.startsWith("constant")) { + String constname = key.substring("constant".length()+1).trim(); + String val = s.substring(s.indexOf(':')+1).trim(); + p.addConstant(constname, new Constant(val)); + continue; + } else if (key.startsWith("shortcut to")) { + continue; + } + else throw new RuntimeException("unknown port type: \""+key+"\""); + + p = null; + String val = s.substring(s.indexOf(':')+1).trim(); + String boxname = val.indexOf('.') != -1 ? val.substring(0, val.indexOf('.')) : val; + 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); + } + } + } + } + + public void printTeX(PrintWriter pw) throws Exception { + ShipDescription sd = this; + pw.println("\\pagebreak"); + pw.println("\\section*{The {\\tt "+sd.getName()+"} Ship}"); + pw.println("\\addcontentsline{toc}{subsection}{"+sd.getName()+"}"); + String tex = sd.getSection("tex"); + /* + for(DockDescription bbd : sd) { + pw.println("{\\bf "+(bbd.isInputDock() ? "Input: " : "Output: ")+"{\\tt "+bbd.getName()+"}}\n\n"); + } + */ + int boxGap = 5; + int boxHeight = 25; + int boxWidth = 75; + + int leftSize = 0; + int rightSize = 0; + for(DockDescription bbd : sd) + if (bbd.isLeft()) leftSize += (boxHeight+boxGap); + else rightSize += (boxHeight+boxGap); + + int totalHeight = Math.max(leftSize, rightSize); + int shipWidth = (int)(boxWidth * 1.5); + int totalWidth = boxGap*2 + boxWidth*2 + shipWidth; + + pw.println(""); + pw.println("\\begin{center}"); + pw.println("\\begin{empfile}["+sd.getName()+"]"); + pw.println("\\begin{emp}["+sd.getName()+"]("+(totalWidth+10)+","+(totalHeight+10)+")"); + pw.println(" beginfig(1)"); + pw.println(" pickup pencircle scaled 1pt;"); + pw.println(" draw "+ + "("+((totalWidth-shipWidth)/2)+","+0+")--"+ + "("+((totalWidth-shipWidth)/2)+","+totalHeight+")--"+ + "("+(totalWidth-((totalWidth-shipWidth)/2))+","+totalHeight+")--"+ + "("+(totalWidth-((totalWidth-shipWidth)/2))+","+0+")--"+ + "("+((totalWidth-shipWidth)/2)+","+0+");"); + int left = 0; + int right = 0; + for(DockDescription bbd : sd) { + int ypos = (totalHeight - (boxGap/2) - (bbd.isLeft() ? left : right)); + int half = (totalWidth-shipWidth)/2; + int p1 = bbd.isLeft() ? (half-5) : ((totalWidth-half)+5); + int p3 = bbd.isLeft() ? (p1 - boxWidth) : (p1 + boxWidth); + if (bbd.isInputDock()) { + int p1x = p1; + p1 = p3; + p3 = p1x; + } + boolean goo = ((bbd.isLeft() && bbd.isInputDock()) || (!bbd.isLeft() && bbd.isOutputDock())); + int p2 = goo ? (p3 - (boxHeight/2)) : (p3 + (boxHeight/2)); + if (bbd.isLeft()) left += (boxHeight+boxGap); + else right += (boxHeight+boxGap); + if (goo) { + pw.println(" label.rt(btex \\tt "+bbd.getName()+" etex, ("+(p1+3)+","+(ypos-boxHeight/2)+"));"); + } else { + pw.println(" label.lft(btex \\tt "+bbd.getName()+" etex, ("+(p1-3)+","+(ypos-boxHeight/2)+"));"); + } + pw.println(" draw "+ + " ("+p1+","+ypos+")--"+ + " ("+p2+","+ypos+")--"+ + " ("+p3+","+(ypos-(boxHeight/2))+")--"+ + " ("+p2+","+(ypos-boxHeight)+")--"+ + " ("+p1+","+(ypos-boxHeight)+")--"+ + " ("+p1+","+ypos+");"); + if (bbd.isLeft()) leftSize += boxHeight; + else rightSize += boxHeight; + } + pw.println(" endfig;"); + pw.println("\\end{emp}"); + pw.println("\\end{empfile}"); + pw.println("\\end{center}"); + pw.println(""); + + if (tex!=null) + pw.println(tex); + } + + public class Constant { + public long setbits = 0; + public long clearbits = 0; + public boolean signExtend = false; + public int numberOffset = 0; + public int numberWidth = 0; + public Constant(String s) { + if (s.startsWith("0x")) { + setbits = Long.parseLong(s.substring(2), 16); + clearbits = ~setbits; + } else if (s.length() == 37) { + for(int i=36; i>=0; i--) { + char c = s.charAt(36-i); + switch(c) { + case '0': clearbits |= (1<> "+valmaskmin+")"; + //return "(("+var+" & "+allmax+"'b"+Long.toString(valmask,2)+") >> "+valmaskmin+")"; + return ""+var+"["+valmaskmax+":"+valmaskmin+"]"; } public long getval(long in) { return (in & valmask) >>> valmaskmin; } + public long setval(long in, BitVector targ) { + long ret = 0; + for(int i=0; i