From: Adam Megacz Date: Tue, 3 Mar 2009 20:37:49 +0000 (+0000) Subject: eliminate need for adam.jar X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=696463d91dca9992863b6096fdfc2265e10e8e3e;p=fleet.git eliminate need for adam.jar --- diff --git a/testCode/edu/berkeley/fleet/api/BitVector.java b/testCode/edu/berkeley/fleet/api/BitVector.java new file mode 100644 index 0000000..8b08fc6 --- /dev/null +++ b/testCode/edu/berkeley/fleet/api/BitVector.java @@ -0,0 +1,148 @@ +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. Bits are numbered starting with LSB as "bit + * zero". + * + * The toLong(), set(long), and setAndSignExtend(long) methods offer + * the following guarantee: for all i, unless an exception is thrown + * the following identities will hold: + * + * bv.set(i).toLong() == i + * bv.equals(new BitVector(bv.length()).set(bv.toLong())) + * + * An exception is thrown if the BitVector in question is more than + * 64 bits long (in which case it cannot be converted to a long with + * toLong()) or the long in question cannot be represented as a two's + * complement number using the number of bits allocated in the + * BitVector. + */ +public class BitVector { + + private final boolean[] bits; + + private boolean immutable = false; + + public BitVector(int length) { + this.bits = new boolean[length]; + } + + /** copy constructor */ + public BitVector(BitVector bv) { + this(bv.length()); + for(int i=0; ithis */ + public BitVector set(long value) { + if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector"); + for(int i=0; i>> i) & 1L) != 0); + return this; + } + + public BitVector set(BitVector bv) { + if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector"); + if (length()!=bv.length()) throw new RuntimeException("attempt to copy between BitVectors of unequal sizes"); + for(int i=0; ithis */ + public BitVector setAndSignExtend(long value) { + if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector"); + for(int i=0; i>> i) & 1L) != 0) : value<0 ? true : false); + return this; + } + + /** returns the length of this BitVector */ + public int length() { + return bits.length; + } + + /** sets the specified bit to the given value */ + public BitVector set(int bit, boolean value) { + if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector"); + bits[bit] = value; + return this; + } + + /** returns the value of the specified bit */ + public boolean get(int bit) { + return bits[bit]; + } + + /** get a sub-BitVector of a BitVector */ + public BitVector get(int high, int low) { + if (low < 0 || high < 0 || high>low) + throw new RuntimeException("attempt to invoke BitVector("+high+","+low+")"); + if (high > length()-1) + throw new RuntimeException("attempt to invoke BitVector("+high+","+low+") on an "+length()+"-bit BitVector"); + BitVector ret = new BitVector(1+high-low); + for(int i=low; i<=high; i++) + ret.set(i-low, get(i)); + return ret; + } + + 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(); + } + + /** makes this BitVector immutable; cannot be undone */ + public void setImmutable() { + immutable = true; + } + + /** indicates if this BitVector has been marked as immutable */ + public boolean getImmutable() { + return immutable; + } + + public int hashCode() { + int ret = 0; + for(int i=0; i64 + */ + public long toLong() { + if (length() > 64) + throw new RuntimeException("a " + length() + "-bit BitVector cannot fit in a Java long"); + long ret = 0; + for(int i=0; i<64; i++) + if (iPath 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(); + + /** get a constant associated with a dock; returns null if none found */ + public BitVector getConstant(String constantName) { + return null; + } + + public String toString() { return getShip()+"."+getName(); } +} diff --git a/testCode/edu/berkeley/fleet/api/Fleet.java b/testCode/edu/berkeley/fleet/api/Fleet.java new file mode 100644 index 0000000..ce0cfb2 --- /dev/null +++ b/testCode/edu/berkeley/fleet/api/Fleet.java @@ -0,0 +1,57 @@ +package edu.berkeley.fleet.api; +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 { + + public abstract Iterator iterator(); + + /** 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); + + /** the natural word width of this machine */ + public abstract int getWordWidth(); + + /** the width of the immediate field in the "shift data latch" instruction */ + public abstract int getShiftWidth(); + + /** the width of the immediate field in the "set data latch" instruction */ + public abstract int getSetWidth(); + + /** + * Encodes an instruction as a BitVector + * @instruction The instruction to encode + * @dispatchFrom The dock from which the instruction being written is to be dispatched (required for encoding) + */ + public abstract BitVector encodeInstruction(Instruction instruction, Dock dispatchFrom); + + /** + * Decodes an instruction from a BitVector + * @instruction The instruction to decode + * @dispatchFrom The dock from which the instructions being read are to be dispatched (required for decoding) + */ + public abstract Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom); + + /** 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/testCode/edu/berkeley/fleet/api/FleetProcess.java b/testCode/edu/berkeley/fleet/api/FleetProcess.java new file mode 100644 index 0000000..1db837f --- /dev/null +++ b/testCode/edu/berkeley/fleet/api/FleetProcess.java @@ -0,0 +1,55 @@ +package edu.berkeley.fleet.api; +import java.io.*; +import java.util.*; + +/** + * 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, words, and tokens + * 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; + + /** dispatch an instruction; may be buffered */ + public abstract void sendInstruction(Instruction i); + + /** dispatch a word to a given destination; may be buffered */ + public abstract void sendWord(Destination d, BitVector word); + + /** dispatch a token to a given destination; may be buffered */ + public abstract void sendToken(Destination d); + + /** flush all instructions, words, and tokens dispatched so far */ + public abstract void flush(); + + /** the dock used to read back data from the slave */ + public abstract Dock getDebugInputDock(); + + /** returns the next word delivered at the dock specified by getDebugInputDock() */ + public abstract BitVector recvWord(); + + /** Terminate the process; subclasses may be assured that this will be called exactly once. */ + protected abstract void _terminate(); + + /** Terminate the process. */ + public final synchronized void terminate() { + if (terminated) return; + terminated = true; + _terminate(); + } + + /** Returns true if the process is terminated */ + public final boolean isTerminated() { return terminated; } + + public synchronized void finalize() { terminate(); } + + /** return the Fleet that this FleetProcess controls */ + public abstract Fleet getFleet(); +} diff --git a/testCode/edu/berkeley/fleet/api/Instruction.java b/testCode/edu/berkeley/fleet/api/Instruction.java new file mode 100644 index 0000000..7c0719f --- /dev/null +++ b/testCode/edu/berkeley/fleet/api/Instruction.java @@ -0,0 +1,353 @@ +package edu.berkeley.fleet.api; +import java.util.*; + +/** a Fleet instruction; includes execution location but not full dispatch path */ +public abstract class Instruction { + + /** the dock which is to execute this instruction */ + public final Dock dock; + + /** true if the instruction is an outer-looping instruction */ + public final boolean looping; + + /** the instruction's predicate */ + public final Predicate predicate; + + 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 abstract Instruction withLooping(boolean newLooping); + //public abstract Instruction withPredicate(Predicate newPredicate); + + public String toString() { + String s = predicate.toString(); + if (s.length()>0) s = "["+s+"] "; + if (looping) s += "[Rq] "; + return dock+": "+s; + } + + /** + * 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 { + + /** 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 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, SetDest dest, SetSource source) { this(dock, false, Predicate.Default, dest, source); } + 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); + } + this.source = source; + this.dest = dest; + this.immediate = 0; + this.newFlagA = null; + this.newFlagB = null; + } + + /** constructor for set instructions with immediates */ + public Set(Dock dock, SetDest dest, long immediate) { this(dock, false, Predicate.Default, dest, immediate); } + 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.newFlagA = null; + this.newFlagB = null; + } + + /** constructor for set flags instructions */ + public Set(Dock dock, FlagFunction newFlagA, FlagFunction newFlagB) { this(dock, false, Predicate.Default, newFlagA, newFlagB); } + 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.newFlagA = newFlagA; + this.newFlagB = newFlagB; + } + + /** possible sources for the Set instruction */ + public static enum SetSource { + Infinity, DataLatch, Immediate, Decrement; + } + /** possible destinations for the Set instruction */ + public static enum SetDest { + InnerLoopCounter, OuterLoopCounter, Flags, DataLatch; + } + + /** + * (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 boolean evaluate(boolean flag_a, boolean flag_b, boolean flag_c, boolean olc_zero) { + boolean ret = false; + for(Predicate p : this) + ret |= p.evaluate(flag_a, flag_b, flag_c, olc_zero); + return ret; + } + } + + public String toString() { + switch(dest) { + 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 Flags: return super.toString()+"set flags a="+newFlagA+", b="+newFlagB+";"; + case DataLatch: return super.toString()+"set word="+immediate+";"; + } + throw new Error("impossible"); + } + } + + /** 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, BitVector immediate) { this(dock, false, Predicate.Default, immediate); } + public Shift(Dock dock, boolean looping, Predicate predicate, BitVector immediate) { + super(dock, looping, predicate); + this.immediate = immediate; + this.immediate.setImmutable(); + if (immediate.length() != dock.getShip().getFleet().getShiftWidth()) + throw new RuntimeException("attempt to create a Shift instruction with a "+immediate.length()+ + "-bit immediate on a Fleet that uses "+dock.getShip().getFleet().getShiftWidth()+ + "-bit shift instructions"); + } + public String toString() { return super.toString()+"shift "+immediate; } + } + + /** a flush instruction */ + public static class Flush extends Instruction { + public Flush(Dock dock) { this(dock, false, Predicate.Default); } + public Flush(Dock dock, boolean looping, Predicate predicate) { + super(dock, looping, predicate); + if (!dock.isInputDock()) throw new RuntimeException("Flush is only allowed at input docks"); + } + public String toString() { return super.toString()+"flush"; } + } + + /** 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; + + /** 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 Move(Dock dock, + Path path, + boolean tokenIn, + boolean dataIn, + boolean latchData, + boolean latchPath, + boolean dataOut, + boolean tokenOut + ) { + this(dock, false, Predicate.Default, false, path, tokenIn, dataIn, latchData, latchPath, dataOut, tokenOut); } + public Move(Dock dock, + boolean looping, + Predicate predicate, + boolean interruptible, + Path path, + boolean tokenIn, + boolean dataIn, + boolean latchData, + boolean latchPath, + boolean dataOut, + boolean tokenOut + ) { + super(dock, looping, predicate); + this.path = path; + this.tokenIn = tokenIn; + this.dataIn = dataIn; + this.latchData = latchData; + this.latchPath = latchPath; + this.dataOut = dataOut; + this.tokenOut = tokenOut; + this.interruptible = interruptible; + if (dock != null && dock.isInputDock() && tokenIn && dataIn) + throw new RuntimeException("cannot have two \"recv\"s: " + this); + if (dock != null && dock.isOutputDock() && tokenOut && dataOut) + throw new RuntimeException("cannot have two \"send\"s: " + 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() { + StringBuffer ret = new StringBuffer(); + if (tokenIn) ret.append(", recv token"); + if (dataIn) { + if (latchPath && latchData) ret.append(!dock.isInputDock() ? ", collect packet" : ", recv packet"); + if (latchPath) ret.append(!dock.isInputDock() ? ", collect path" : ", recv path"); + else if (latchData) ret.append(!dock.isInputDock() ? ", collect" : ", recv"); + else ret.append(!dock.isInputDock() ? ", collect nothing" : ", recv nothing"); + } + if (dataOut && dock.isInputDock()) ret.append(", deliver"); + if (dataOut && !dock.isInputDock()) ret.append(path==null ? ", send" : ", send to " + path.getDestination().getDock()); + if (tokenOut) ret.append(path==null ? ", token" : ", send token to " + path.getDestination().getDock()); + String s = ret.toString(); + s = s.equals("") ? "nop" : s.substring(2); + if (interruptible) s = "[T] " + s; + return super.toString()+s+";"; + } + } + + /** a flush instruction */ + public static class Abort extends Instruction { + public Abort(Dock dock, Predicate predicate) { super(dock, false, predicate); } + public String toString() { return super.toString()+"abort;"; } + } + + /** marks the start of a loop; closes the hatch */ + public static class Head extends Instruction { + public Head(Dock dock) { super(dock, false, Predicate.IgnoreFlagD); } + public String toString() { return dock+": head;"; } + } + + /** marks the end of a loop; closes the hatch */ + public static class Tail extends Instruction { + public Tail(Dock dock) { super(dock, false, Predicate.IgnoreFlagD); } + public String toString() { return dock+": tail;"; } + } + +} diff --git a/testCode/edu/berkeley/fleet/api/Path.java b/testCode/edu/berkeley/fleet/api/Path.java new file mode 100644 index 0000000..5de20fb --- /dev/null +++ b/testCode/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/testCode/edu/berkeley/fleet/api/Predicate.java b/testCode/edu/berkeley/fleet/api/Predicate.java new file mode 100644 index 0000000..2556e47 --- /dev/null +++ b/testCode/edu/berkeley/fleet/api/Predicate.java @@ -0,0 +1,37 @@ +package edu.berkeley.fleet.api; + +/** possible predicate field values */ +public enum Predicate { + Default, FlagA, NotFlagA, FlagB, NotFlagB, FlagC, NotFlagC, IgnoreFlagD, FlagD; + 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 IgnoreFlagD:return "*"; + case FlagD: return "d"; + default: throw new Error("unknown predicate " + this); + } + } + + /** evaluates this predicate for a given set of flags and olc */ + public boolean evaluate(boolean flag_a, boolean flag_b, boolean flag_c, boolean flag_d) { + switch(this) { + case Default: return !flag_d; + case FlagA: return !flag_d && flag_a; + case FlagB: return !flag_d && flag_b; + case FlagC: return !flag_d && flag_c; + case NotFlagA: return !flag_d && !flag_a; + case NotFlagB: return !flag_d && !flag_b; + case NotFlagC: return !flag_d && !flag_c; + case IgnoreFlagD:return true; + case FlagD: return flag_d; + default: throw new Error("unknown predicate " + this); + } + } + +} diff --git a/testCode/edu/berkeley/fleet/api/Ship.java b/testCode/edu/berkeley/fleet/api/Ship.java new file mode 100644 index 0000000..f5eafa4 --- /dev/null +++ b/testCode/edu/berkeley/fleet/api/Ship.java @@ -0,0 +1,37 @@ +package edu.berkeley.fleet.api; +import java.util.*; + +/** 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 Fleet getFleet() { return fleet; } + + /** returns the type of the ship ("Fetch", "Alu", etc) */ + public abstract String getType(); + + public abstract Iterator iterator(); + + /** 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(); + + /** get a constant associated with a ship; returns null if none found */ + public BitVector getConstant(String constantName) { + return null; + } + + public String toString() { + String name = getType(); + name = name.substring(0,1).toLowerCase()+name.substring(1); + return name + "" + getOrdinal() + ""; + } +} diff --git a/testCode/edu/berkeley/fleet/marina/MarinaDock.java b/testCode/edu/berkeley/fleet/marina/MarinaDock.java new file mode 100644 index 0000000..05a301a --- /dev/null +++ b/testCode/edu/berkeley/fleet/marina/MarinaDock.java @@ -0,0 +1,26 @@ +package edu.berkeley.fleet.marina; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.two.*; + +public class MarinaDock extends FleetTwoDock { + + public Destination getDataDestination() { return null; } + public Destination getInstructionDestination() { return null; } + public int getInstructionFifoSize() { return 0; } + public Path getPath(Destination d,BitVector bv) { return null; } + + private boolean isInput; + public boolean isInputDock() { return isInput; } + public boolean isOutputDock() { return !isInput; } + + public MarinaDock(MarinaShip ship, boolean isInput) { + super(ship, null); + this.isInput = isInput; + ship.addDock(this); + } + + public String getName() { return "fakedock"; } + public ShipDescription.Constant getDockConstant(String s) { return null; } + +} + diff --git a/testCode/edu/berkeley/fleet/marina/MarinaFleet.java b/testCode/edu/berkeley/fleet/marina/MarinaFleet.java new file mode 100644 index 0000000..192e9b6 --- /dev/null +++ b/testCode/edu/berkeley/fleet/marina/MarinaFleet.java @@ -0,0 +1,43 @@ +package edu.berkeley.fleet.marina; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.two.*; +import edu.berkeley.fleet.*; +import java.util.*; + +public class MarinaFleet extends FleetTwoFleet { + + MarinaShip fakeShip = new MarinaShip(this); + MarinaDock onlyDock = new MarinaDock(fakeShip, true); + + public MarinaFleet() { + // use "internal encoding" + super(true); + } + + public BitVector encodeInstruction(Dock dispatchFrom, Instruction instruction) { + return encodeInstruction(instruction, dispatchFrom); + } + + public Iterator iterator() { + HashSet hs = new HashSet(); + hs.add(fakeShip); + return hs.iterator(); + } + + public Ship getShip(String type, int ordinal) { + throw new RuntimeException("not implemented"); + } + + public FleetProcess run(Instruction[] instructions) { + throw new RuntimeException("not implemented"); + } + + public BitVector getDestAddr(Path path) { + if (path==null) return new BitVector(0); + return ((MarinaPath)path).bv; + } + + public Dock getOnlyInputDock() { + return onlyDock; + } +} diff --git a/testCode/edu/berkeley/fleet/marina/MarinaPath.java b/testCode/edu/berkeley/fleet/marina/MarinaPath.java new file mode 100644 index 0000000..0c9ba58 --- /dev/null +++ b/testCode/edu/berkeley/fleet/marina/MarinaPath.java @@ -0,0 +1,30 @@ +package edu.berkeley.fleet.marina; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.two.*; + +public class MarinaPath extends FleetTwoPath { + + private final MarinaFleet marina; + final BitVector bv; + + public MarinaPath(MarinaFleet marina, BitVector bv) { + this.marina = marina; + this.bv = bv; + bv.setImmutable(); + } + + public String toString() { return "MarinaPath("+bv+")"; } + + public BitVector getSignal() { + throw new RuntimeException("not implemented"); + } + + public Dock getSource() { return marina.onlyDock; } + public Destination getDestination() { + throw new RuntimeException("not implemented"); + } + public int getBufferingAmount() { return 1; } + public int getLatencyMetric() { return 0; } + +} + diff --git a/testCode/edu/berkeley/fleet/marina/MarinaShip.java b/testCode/edu/berkeley/fleet/marina/MarinaShip.java new file mode 100644 index 0000000..c2b8aad --- /dev/null +++ b/testCode/edu/berkeley/fleet/marina/MarinaShip.java @@ -0,0 +1,23 @@ +package edu.berkeley.fleet.marina; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.two.*; +import java.util.*; + +public class MarinaShip extends FleetTwoShip { + + private HashSet docks = new HashSet(); + + public Iterator iterator() { return (Iterator)(Object)docks.iterator(); } + + private MarinaFleet fleet; + + /*package*/ void addDock(MarinaDock dock) { docks.add(dock); } + + public MarinaShip(MarinaFleet fleet) { + super(fleet, null); + this.fleet = fleet; + } + + public String getType() { return "MarinaShip"; } +} + diff --git a/testCode/edu/berkeley/fleet/two/DockDescription.java b/testCode/edu/berkeley/fleet/two/DockDescription.java new file mode 100644 index 0000000..eccbe6e --- /dev/null +++ b/testCode/edu/berkeley/fleet/two/DockDescription.java @@ -0,0 +1,43 @@ +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 boolean isDockless; + private final HashMap constants = new HashMap(); + + DockDescription(ShipDescription ship, String name, boolean left, boolean inbox) { + this(ship, name, left, inbox, false); + } + DockDescription(ShipDescription ship, String name, boolean left, boolean inbox, boolean isDockless) { + this.left = left; + this.ship = ship; + this.name = name; + this.inbox = inbox; + this.isDockless = isDockless; + } + + public String getName() { return name; } + public boolean isInputDock() { return inbox; } + public boolean isOutputDock() { return !inbox; } + public boolean isDockless() { return isDockless; } + + /** Indicates if this dock should be drawn on the "left hand side" of the ship for visual purposes */ + boolean isLeft() { return left; } + + /** 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/testCode/edu/berkeley/fleet/two/FleetTwoDock.java b/testCode/edu/berkeley/fleet/two/FleetTwoDock.java new file mode 100644 index 0000000..3990c1d --- /dev/null +++ b/testCode/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 getDockConstant(String s) { return dockDescription.getConstant(s); } + + public boolean isInputDock() { return dockDescription.isInputDock(); } + + public boolean isOutputDock() { return !dockDescription.isInputDock(); } + + +} diff --git a/testCode/edu/berkeley/fleet/two/FleetTwoFleet.java b/testCode/edu/berkeley/fleet/two/FleetTwoFleet.java new file mode 100644 index 0000000..e446dd0 --- /dev/null +++ b/testCode/edu/berkeley/fleet/two/FleetTwoFleet.java @@ -0,0 +1,475 @@ +package edu.berkeley.fleet.two; +import java.io.*; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.util.*; +import edu.berkeley.fleet.api.Instruction.Set; +import static edu.berkeley.fleet.api.Instruction.Set.*; +import static edu.berkeley.fleet.api.Instruction.*; +import static edu.berkeley.fleet.api.Predicate.*; + +/** common subclass for the "FleetTwo" generation of processors, all 37-bit wide, with AM33 encoding */ +public abstract class FleetTwoFleet extends Fleet { + + private final boolean hack = "true".equals(System.getProperty("inverted-dc-bit-hack", "false")); + + public final Mask PACKET_TOKEN; + public final Mask PACKET_IS_TOKEN; + public final Mask PACKET_DATA; + public final Mask PACKET_SIGNAL; + public final Mask PACKET_DEST; + + public final Mask CBD_SIZE; + public final Mask CBD_OFFSET; + + public final Mask WHOLE_WORD; + public final Mask DISPATCH_PATH; + public final Mask DISPATCH_INSTR; + public final Mask NOT_INTERRUPTIBLE; + public final Mask OS; + public final Mask P; + public final Mask P_NOT_A; + public final Mask P_A; + public final Mask P_NOT_B; + public final Mask P_B; + public final Mask P_UNUSED; + public final Mask P_OLC_ZERO; + public final Mask P_OLC_NONZERO; + public final Mask P_ALWAYS; + + public final Mask SHIFT; + + public final Mask TAIL; + public final Mask HEAD; + public final Mask ABORT; + + public final Mask MOVE; + public final Mask TI; + public final Mask DI; + public final Mask FLUSH; + public final Mask DC; + public final Mask DO; + public final Mask TO; + public final Mask PATH_IMMEDIATE; + public final Mask PATH_DATA; + public final Mask PATH_NOCHANGE; + + public final Mask SET_OLC_FROM_IMMEDIATE; + public final Mask SET_OLC_FROM_DATA_LATCH; + public final Mask SET_OLC_FROM_OLC_MINUS_ONE; + + public final Mask SET_ILC_FROM_IMMEDIATE; + public final Mask SET_ILC_FROM_INFINITY; + public final Mask SET_ILC_FROM_DATA_LATCH; + + public final Mask SET_IMMEDIATE; + public final Mask SET_IMMEDIATE_EXTEND; + + public final Mask SET_FLAGS; + public final Mask SET_FLAGS_A; + public final Mask SET_FLAGS_B; + public final Mask SET_FLAGS_VALUE_A; + public final Mask SET_FLAGS_VALUE_NOT_A; + public final Mask SET_FLAGS_VALUE_B; + public final Mask SET_FLAGS_VALUE_NOT_B; + public final Mask SET_FLAGS_VALUE_C; + public final Mask SET_FLAGS_VALUE_NOT_C; + + public final int WIDTH_WORD; + public final int WIDTH_PACKET; + + public final long DataLatch_WIDTH; + private final long mask; + + public FleetTwoFleet() { this(false); } + + public FleetTwoFleet(boolean useInternalEncoding) { + PACKET_TOKEN = new Mask("v................................................."); + PACKET_IS_TOKEN = new Mask("1................................................."); + PACKET_DATA = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv............"); + PACKET_SIGNAL = new Mask("......................................v..........."); + PACKET_DEST = new Mask(".......................................vvvvvvvvvvv"); + + CBD_SIZE = new Mask("...............................vvvvvv"); + CBD_OFFSET = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv......"); + + WHOLE_WORD = new Mask("vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"); + + if (useInternalEncoding) { + + DISPATCH_PATH = new Mask("v...................................."); + DISPATCH_INSTR = new Mask(".vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"); + NOT_INTERRUPTIBLE = new Mask(".................1..................."); + OS = new Mask(".......1............................."); + P = new Mask(".vvvvvv.............................."); + P_NOT_A = new Mask(".011110.............................."); + P_A = new Mask(".011101.............................."); + P_NOT_B = new Mask(".011011.............................."); + P_B = new Mask(".010111.............................."); + P_UNUSED = new Mask(".000000.............................."); + P_OLC_ZERO = new Mask(".101111.............................."); + P_OLC_NONZERO = new Mask(".011111.............................."); + P_ALWAYS = new Mask(".111111.............................."); + + SHIFT = new Mask("..........101111.1vvvvvvvvvvvvvvvvvvv"); + + /* + // use these when Marina gets updated to 07-Jan-2009 version of internal encoding + HEAD = new Mask(".......1............................."); + ABORT = new Mask("........1............................"); + TAIL = new Mask(".........1..........................."); + */ + + TAIL = new Mask("................1...................0"); + HEAD = null; + ABORT = null; + + MOVE = new Mask("..........110111....................."); + TI = new Mask("..........110111..1.................."); + DI = new Mask("..........110111...1................."); + FLUSH = new Mask(".........1110111....................."); + DC = new Mask("..........110111....1................"); + DO = new Mask("..........110111.....1..............."); + TO = new Mask("..........110111......1.............."); + PATH_IMMEDIATE = new Mask("..........110111.......1vvvvvvvvvvvvv"); + PATH_DATA = new Mask("..........110111.......00............"); + PATH_NOCHANGE = new Mask("..........110111.......01............"); + + SET_OLC_FROM_IMMEDIATE = new Mask("..........111101.0.............vvvvvv"); + SET_OLC_FROM_DATA_LATCH = new Mask("..........111101.1..................."); + SET_OLC_FROM_OLC_MINUS_ONE = new Mask("..........111011....................."); + + SET_ILC_FROM_IMMEDIATE = new Mask("..........011111.0...........0.vvvvvv"); + SET_ILC_FROM_INFINITY = new Mask("..........011111.............1......."); + SET_ILC_FROM_DATA_LATCH = new Mask("..........011111.1..................."); + + SET_IMMEDIATE = new Mask("..........101111.0.....vvvvvvvvvvvvvv"); + SET_IMMEDIATE_EXTEND = new Mask("..........101111.0....v.............."); + + SET_FLAGS = new Mask("..........111110....................."); + SET_FLAGS_A = new Mask("..........111110...............vvvvvv"); + SET_FLAGS_B = new Mask("..........111110.........vvvvvv......"); + + SET_FLAGS_VALUE_A = new Mask(".....1"); + SET_FLAGS_VALUE_NOT_A = new Mask("....1."); + SET_FLAGS_VALUE_B = new Mask("...1.."); + SET_FLAGS_VALUE_NOT_B = new Mask("..1..."); + SET_FLAGS_VALUE_C = new Mask(".1...."); + SET_FLAGS_VALUE_NOT_C = new Mask("1....."); + + } else { + DISPATCH_PATH = new Mask("vvvvvvvvvvv.........................."); + DISPATCH_INSTR = new Mask("...........vvvvvvvvvvvvvvvvvvvvvvvvvv"); + NOT_INTERRUPTIBLE = new Mask("...........1........................."); + OS = new Mask("............1........................"); + P = new Mask(".............vvv....................."); + P_NOT_A = new Mask(".............000....................."); + P_A = new Mask(".............001....................."); + P_NOT_B = new Mask(".............010....................."); + P_B = new Mask(".............011....................."); + P_UNUSED = new Mask(".............100....................."); + P_OLC_ZERO = new Mask(".............101....................."); + P_OLC_NONZERO = new Mask(".............110....................."); + P_ALWAYS = new Mask(".............111....................."); + + SHIFT = new Mask("................00vvvvvvvvvvvvvvvvvvv"); + + ABORT = new Mask("................1100................."); // note: has a predicate! + + HEAD = new Mask("................1110................."); + TAIL = new Mask("................1111................."); + + MOVE = new Mask("................01..................."); + TI = new Mask("................011.................."); + DI = new Mask("................01.1................."); + FLUSH = new Mask("................01.01................"); + DC = new Mask("................01.11................"); + DO = new Mask("................01...1..............."); + TO = new Mask("................01....1.............."); + PATH_IMMEDIATE = new Mask("................01.....1vvvvvvvvvvvvv"); + PATH_DATA = new Mask("................01.....01............"); + PATH_NOCHANGE = new Mask("................01.....00............"); + + SET_OLC_FROM_IMMEDIATE = new Mask("................101000100......vvvvvv"); + SET_OLC_FROM_DATA_LATCH = new Mask("................101000010............"); + SET_OLC_FROM_OLC_MINUS_ONE = new Mask("................101000001............"); + + SET_ILC_FROM_IMMEDIATE = new Mask("................10010010......0vvvvvv"); + SET_ILC_FROM_INFINITY = new Mask("................10010010......1......"); + SET_ILC_FROM_DATA_LATCH = new Mask("................10010001............."); + + SET_IMMEDIATE = new Mask("................100010.vvvvvvvvvvvvvv"); + SET_IMMEDIATE_EXTEND = new Mask("................100010v.............."); + + SET_FLAGS = new Mask("................100001..............."); + SET_FLAGS_A = new Mask("................100001...vvvvvv......"); + SET_FLAGS_B = new Mask("................100001.........vvvvvv"); + + SET_FLAGS_VALUE_A = new Mask("1....."); + SET_FLAGS_VALUE_NOT_A = new Mask(".1...."); + SET_FLAGS_VALUE_B = new Mask("..1..."); + SET_FLAGS_VALUE_NOT_B = new Mask("...1.."); + SET_FLAGS_VALUE_C = new Mask("....1."); + SET_FLAGS_VALUE_NOT_C = new Mask(".....1"); + } + + WIDTH_WORD = PACKET_DATA.valmaskwidth; + WIDTH_PACKET = PACKET_TOKEN.width; + DataLatch_WIDTH = SET_IMMEDIATE.valmaskmax-SET_IMMEDIATE.valmaskmin+1; // FIXME: this is an abstraction breakage + mask = ~(-1L << DataLatch_WIDTH); + } + + // Misc ////////////////////////////////////////////////////////////////////////////// + + public boolean isSmallEnoughToFit(long immediate) { + if ((immediate & ~mask) == 0) return true; + if ((immediate | mask) == -1L) return true; + return false; + } + + public int getWordWidth() { return 37; } + + ////////////////////////////////////////////////////////////////////////////// + + /** get the bits describing this box's location on the DESTINATION HORN */ + protected abstract BitVector getDestAddr(Path box); + + private static final BitVector SIGNAL_ZERO = new BitVector(1); + private static final BitVector SIGNAL_ONE = new BitVector(1).set(0,true); + + /** decode a path, given the starting point and the bits that comprise it */ + public Path getPathByAddr(Dock source, BitVector dest) { + for(Ship ship : this) + for(Dock bb : ship) { + for(Destination d : new Destination[] { bb.getInstructionDestination(), bb.getDataDestination() }) { + for(BitVector signal : new BitVector[] { SIGNAL_ZERO, SIGNAL_ONE }) { + Path p = (Path)source.getPath(d, signal); + if (getDestAddr(p).equalsZeroExtended(dest)) return p; + } + } + } + return null; + } + + public Instruction decodeInstruction(BitVector instruction, Dock dispatchFrom) { + return readInstruction(instruction.toLong(), dispatchFrom); + } + + public BitVector encodeInstruction(Instruction instr, Dock dispatchFrom) { + return new BitVector(getWordWidth()).set(writeInstruction(instr, dispatchFrom)); + } + + public int getShiftWidth() { return SHIFT.valmaskwidth; } + public int getSetWidth() { return SET_IMMEDIATE.valmaskwidth+1; } + + // FIXME: should use BitVector here + public Instruction readInstruction(long inst, Dock dispatchFrom) { + Dock dock = getPathByAddr(dispatchFrom, DISPATCH_PATH.getvalAsBitVector(inst)).getDestination().getDock(); + + if (TAIL.get(inst)) return new Tail(dock); + if (HEAD.get(inst)) return new Head(dock); + + Predicate predicate = Default; + if (P_ALWAYS.get(inst)) predicate = IgnoreFlagD; + if (P_OLC_NONZERO.get(inst)) predicate = Default; + if (P_OLC_ZERO.get(inst)) predicate = FlagD; + if (P_A.get(inst)) predicate = FlagA; + if (P_B.get(inst)) predicate = FlagB; + if (P_NOT_A.get(inst)) predicate = NotFlagA; + if (P_NOT_B.get(inst)) predicate = NotFlagB; + + boolean looping = !OS.get(inst); + if (FLUSH.get(inst)) + return new Flush(dock, looping, predicate); + if (ABORT.get(inst)) + return new Abort(dock, predicate); + if (SHIFT.get(inst)) return new Shift(dock, looping, predicate, new BitVector(dock.getShip().getFleet().getShiftWidth()).set(SHIFT.getval(inst))); + if (SET_IMMEDIATE.get(inst)) { + boolean extend = SET_IMMEDIATE_EXTEND.getval(inst) != 0; + long immediate = SET_IMMEDIATE.getval(inst); + if (extend) immediate |= (-1L << DataLatch_WIDTH); + return new Set(dock, looping, predicate, SetDest.DataLatch, (immediate)); + } + + if (SET_OLC_FROM_OLC_MINUS_ONE.get(inst)) + return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.Decrement); + if (SET_OLC_FROM_IMMEDIATE.get(inst)) + return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, (SET_OLC_FROM_IMMEDIATE.getval(inst))); + if (SET_ILC_FROM_IMMEDIATE.get(inst)) + return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, (SET_ILC_FROM_IMMEDIATE.getval(inst))); + if (SET_OLC_FROM_DATA_LATCH.get(inst)) + return new Set(dock, looping, predicate, SetDest.OuterLoopCounter, SetSource.DataLatch); + if (SET_ILC_FROM_DATA_LATCH.get(inst)) + return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.DataLatch); + if (SET_ILC_FROM_INFINITY.get(inst)) + return new Set(dock, looping, predicate, SetDest.InnerLoopCounter, SetSource.Infinity); + if (SET_FLAGS.get(inst)) { + long flag_a = SET_FLAGS_A.getval(inst); + long flag_b = SET_FLAGS_B.getval(inst); + FlagFunction ap = FlagFunction.ZERO; + FlagFunction bp = FlagFunction.ZERO; + if (SET_FLAGS_VALUE_A .get(flag_a)) ap = ap.add(FlagA ); + if (SET_FLAGS_VALUE_NOT_A.get(flag_a)) ap = ap.add(NotFlagA ); + if (SET_FLAGS_VALUE_B .get(flag_a)) ap = ap.add(FlagB ); + if (SET_FLAGS_VALUE_NOT_B.get(flag_a)) ap = ap.add(NotFlagB ); + if (SET_FLAGS_VALUE_C .get(flag_a)) ap = ap.add(FlagC ); + if (SET_FLAGS_VALUE_NOT_C.get(flag_a)) ap = ap.add(NotFlagC ); + if (SET_FLAGS_VALUE_A .get(flag_b)) bp = bp.add(FlagA ); + if (SET_FLAGS_VALUE_NOT_A.get(flag_b)) bp = bp.add(NotFlagA ); + if (SET_FLAGS_VALUE_B .get(flag_b)) bp = bp.add(FlagB ); + if (SET_FLAGS_VALUE_NOT_B.get(flag_b)) bp = bp.add(NotFlagB ); + if (SET_FLAGS_VALUE_C .get(flag_b)) bp = bp.add(FlagC ); + if (SET_FLAGS_VALUE_NOT_C.get(flag_b)) bp = bp.add(NotFlagC ); + return new Set(dock, looping, predicate, ap, bp); + } + if (MOVE.get(inst)) + return new Move(dock, + looping, + predicate, + !NOT_INTERRUPTIBLE.get(inst), + PATH_DATA.get(inst)?null:getPathByAddr(dock, PATH_IMMEDIATE.getvalAsBitVector(inst)), + TI.get(inst), + DI.get(inst), + hack?(!DC.get(inst)):DC.get(inst), + PATH_DATA.get(inst), + DO.get(inst), + TO.get(inst) + ); + throw new RuntimeException("unknown instruction: 0x" + Long.toString(inst, 16)); + } + + // FIXME: should use BitVector here + public long writeInstruction(Instruction d, Dock dispatchFrom) { + long instr = 0; + + if (d.dock != null) { + BitVector bv = getDestAddr(dispatchFrom.getPath(d.dock.getInstructionDestination(),null)); + BitVector bv2 = new BitVector(DISPATCH_PATH.valmaskwidth); + for(int i=0; iDocks */ +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/testCode/edu/berkeley/fleet/two/ShipDescription.java b/testCode/edu/berkeley/fleet/two/ShipDescription.java new file mode 100644 index 0000000..dbc682e --- /dev/null +++ b/testCode/edu/berkeley/fleet/two/ShipDescription.java @@ -0,0 +1,238 @@ +package edu.berkeley.fleet.two; +import edu.berkeley.fleet.api.*; +//import edu.berkeley.fleet.fpga.verilog.Verilog.PercolatedPort; +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 LinkedHashMap ports = 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 Iterable ports() { + return ports.values(); + } + + //public final LinkedList percolatedPorts = new LinkedList(); + + public ShipDescription(String name, BufferedReader r) throws IOException { + if (name.endsWith(".ship")) name = name.substring(0, name.length()-".ship".length()); + 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; + boolean dockless = false; + key = key.replaceAll(" +", " "); + if (key.equals("data in")) { inbox = true; } + else if (key.equals("data out")) { inbox = false; } + else if (key.equals("in")) { inbox = true; } + else if (key.equals("dockless out")) { inbox = false; dockless = true; } + else if (key.equals("out")) { inbox = false; } + /* + else if (key.startsWith("percolate")) { + key = s; + key = key.substring("percolate".length()+1).trim(); + PercolatedPort.PortType type = null; + if (key.startsWith("up")) type = PercolatedPort.PortType.UP; + if (key.startsWith("down")) type = PercolatedPort.PortType.DOWN; + if (key.startsWith("inout")) type = PercolatedPort.PortType.INOUT; + key = key.substring(key.indexOf(':')+1).trim(); + String name = key.substring(0, key.indexOf(' ')); + int width = Integer.parseInt(key.substring(key.indexOf(' ')).trim()); + percolatedPorts.add(new PercolatedPort(name, width, type)); + continue; + } + */ + 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, dockless); + ports.put(boxname, p); + if (!dockless) 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); + } + + // FIXME: merge with BitMask + 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< 32) throw new RuntimeException("too big!"); + return (int)getField(highBit, lowBit, val); + } + public static long getField(int highBit, int lowBit, long val) { + long mask = 0xffffffffffffffffL; + mask = mask << ((highBit-lowBit)+1); + mask = ~mask; + mask = mask << lowBit; + long ret = val & mask; + ret = ret >> lowBit; + return ret; + } + public static long setField(int highBit, int lowBit, long val, long target) { + return (target & ~putField(highBit, lowBit, ~(-1L<<(1+highBit-lowBit)))) | putField(highBit, lowBit, val); + } + public static long doPutField(int highBit, int lowBit, long val) { + long mask = 0xffffffffffffffffL; + mask = mask << (highBit-lowBit+1); + mask = ~mask; + val = val & mask; + val = val << lowBit; + return val; + } + public static long putField(int highBit, int lowBit, long val) { + if (val < 0 || val >= (1L << (highBit-lowBit+1))) + throw new RuntimeException("bitfield width exceeded"); + return doPutField(highBit, lowBit, val); + } + public static long putSignedField(int highBit, int lowBit, long val) { + if (val <= (-1L * (1L << (highBit-lowBit+1-1)))) + throw new RuntimeException("bitfield width exceeded"); + if (val >= ( (1L << (highBit-lowBit+1-1)))) + throw new RuntimeException("bitfield width exceeded"); + return doPutField(highBit, lowBit, val); + } +} diff --git a/testCode/edu/berkeley/fleet/util/Mask.java b/testCode/edu/berkeley/fleet/util/Mask.java new file mode 100644 index 0000000..f252430 --- /dev/null +++ b/testCode/edu/berkeley/fleet/util/Mask.java @@ -0,0 +1,131 @@ +package edu.berkeley.fleet.util; +import edu.berkeley.fleet.api.*; +import edu.berkeley.fleet.*; +import java.io.*; + +public class Mask { + + private final String str; + + public final long mask; + public final long val; + public final long valmask; + public final int valmaskmin; + public final int valmaskmax; + public final int valmaskwidth; + public final int allmax; + public final int width; + + public String verilog(String var) { + // FIXME: throw an exception if this is called when no 1-bits or 0-bits were specified (ie only v-bits) + + StringBuffer sb = new StringBuffer(); + sb.append("{"); + boolean first = true; + int count = 0; + for(int i=63; i>=0; i--) { + if ((mask & (1L << i)) == 0) continue; + if (!first) sb.append(","); + first = false; + sb.append(var+"["+i+"]"); + count++; + } + sb.append("}=="+count+"'b"); + for(int i=63; i>=0; i--) { + if ((mask & (1L << i)) == 0) continue; + sb.append( (val & (1L << i))==0 ? "0" : "1" ); + } + return "("+sb.toString()+")"; + //return "(("+var+" & "+allmax+"'b"+Long.toString(mask,2)+")=="+allmax+"'b"+Long.toString(val,2)+")"; + } + + public long getval(long in) { + return (in & valmask) >>> valmaskmin; + } + public BitVector getvalAsBitVector(long in) { + // FIXME + return new BitVector(getWidth()).set(getval(in)); + } + public BitVector getvalAsBitVector(BitVector in) { + // FIXME + return new BitVector(getWidth()).set(getval(in.toLong())); + } + public long getval(BitVector targ) { + long in = 0; + for(int i=0; i>> valmaskmin; + } + public long setval(long in, BitVector targ) { + long ret = in; + if (targ.length() != (1+valmaskmax-valmaskmin)) + throw new RuntimeException("size mismatch trying to do "+this+".setval("+targ+")"); + for(int i=valmaskmin; i<=valmaskmax; i++) + if (targ.get(i-valmaskmin)) + ret |= (1L << i); + else + ret &= ~(1L << i); + return ret; + } + public long setval(long in, long targ) { + if (((targ << valmaskmin) & ~valmask) != 0) throw new RuntimeException("setval() with argument bigger than mask field"); + return (in & ~valmask) | ((targ << valmaskmin) & valmask); + } + public long set(long in) { + return (in & ~mask) | val; + } + public boolean get(long in) { + return (in & mask) == val; + } + + public String toString() { + return str; + } + + public int getWidth() { + int ret = 0; + long m = 1; + for(int i=0; i<64; i++) { + if ((valmask & m)!=0) ret++; + m = m << 1; + } + return ret; + } + + public Mask(String s) { + this.str = s; + long mask = 0; + long valmask = 0; + long val = 0; + int valmaskmin = Integer.MAX_VALUE; + int valmaskmax = 0; + int allmax = 0; + this.width = s.length(); + for(int i=0; i