--- /dev/null
+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; i<bv.length(); i++)
+ set(i, bv.get(i));
+ }
+
+ /** copy the low-order bits of the argument into this BitVector; returns <tt>this</tt> */
+ public BitVector set(long value) {
+ if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector");
+ for(int i=0; i<length(); i++)
+ set(i, ((value >>> 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; i<length(); i++)
+ set(i, bv.get(i));
+ return this;
+ }
+
+ /** copy the low-order bits of the argument into this BitVector and sign extend; returns <tt>this</tt> */
+ public BitVector setAndSignExtend(long value) {
+ if (immutable) throw new RuntimeException("attempt to modify an immutable BitVector");
+ for(int i=0; i<length(); i++)
+ set(i, i<64 ? (((value >>> 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; i<length(); i++)
+ if (get(i))
+ ret ^= (1L << (i % 32));
+ return ret;
+ }
+
+ public boolean equalsZeroExtended(BitVector bv) {
+ for(int i=0; i<Math.min(bv.bits.length, bits.length); i++)
+ if (bits[i] != bv.bits[i])
+ return false;
+ return true;
+ }
+
+ public boolean equals(Object o) {
+ if (o==null || !(o instanceof BitVector)) return false;
+ BitVector bv = (BitVector)o;
+ if (bv.bits.length != bits.length) return false;
+ return equalsZeroExtended(bv);
+ }
+
+ /**
+ * Converts this BitVector to a long, sign-extending if
+ * length()<64 and throwing an exception if length()>64
+ */
+ 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 (i<length() ? get(i) : get(length()-1))
+ ret |= (1L << i);
+ return ret;
+ }
+}
+
+
--- /dev/null
+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 {
+
+ 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();
+
+}
--- /dev/null
+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 <tt>Path</tt> from this dock to <tt>dest</tt>, 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(); }
+}
--- /dev/null
+package edu.berkeley.fleet.api;
+import java.io.*;
+import java.util.*;
+
+/**
+ * An instance of Fleet; each Fleet consists of a collection of
+ * <tt>Ship</tt>s.
+ *
+ * <p><b>Note about instruction representation:</b> it is very
+ * important to understand that the binary representation of an
+ * instruction includes a path from the dock which will
+ * <i>dispatch</i> the instruction to the dock which will
+ * <i>execute</i> the instruction. Therefore, an instruction cannot
+ * be converted <i>to</i> binary form without supplying a
+ * <i>dispatching dock</i> so the necessary path can be computed.
+ * <b>Moreover:</b> because a given string of bits uniquely describes
+ * a path only if given along with a starting point, instructions
+ * cannot be converted <i>from</i> binary format without knowing the
+ * dispatch dock from which they are meant to be dispatched. <i>This
+ * is why the {@link readInstruction} and {@link writeInstruction}
+ * methods take a "<tt>dispatchFrom</tt>" argument.</i>
+ */
+public abstract class Fleet implements Iterable<Ship> {
+
+ public abstract Iterator<Ship> 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()");
+ }
+}
--- /dev/null
+package edu.berkeley.fleet.api;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Represents a <i>running</i> "slave" fleet with debugging
+ * facilities controlled by the "master" JVM.
+ *
+ * <p>Each Fleet which supports this API must include:
+ * <ul><li> The ability to dispatch instructions, words, and tokens
+ * from the master, "on the fly".
+ * <li> A "debug.in" dock such that any words delivered there
+ * are sent back to the master.
+ * </ul>
+ */
+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 <tt>getDebugInputDock()</tt> */
+ 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();
+}
--- /dev/null
+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 <tt>set</tt> instruction.
+ *
+ * Note that immediates are supplied as Java <tt>long</tt> 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
+ * <tt>BitVector</tt>.
+ */
+ public static class Set extends Instruction {
+
+ /** the destination (latch to be set) */
+ public final SetDest dest;
+
+ /** the source (what will be put in the <tt>dest</tt> latch) */
+ public final SetSource source;
+
+ /** if <tt>source</tt> is <tt>Immediate</tt>, this is the immediate value; an integer */
+ public final long immediate;
+
+ /** if <tt>dest</tt> is <tt>Flags</tt>, this is the truth table to update flag "a" */
+ public final FlagFunction newFlagA;
+
+ /** if <tt>dest</tt> is <tt>Flags</tt>, 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 <tt>set flags</tt> 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<Predicate> {
+
+ /** 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<Predicate> predicates;
+
+ public Iterator<Predicate> iterator() { return predicates.iterator(); }
+
+ private FlagFunction() { this(Collections.EMPTY_SET); }
+ private FlagFunction(java.util.Set<Predicate> set) { this.predicates = Collections.unmodifiableSet(set); }
+
+ /** returns the function which is the logical OR of this function and <tt>ff</tt> */
+ 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 <tt>p</tt> */
+ 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 <tt>p</tt> 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;"; }
+ }
+
+}
--- /dev/null
+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()));
+ }
+
+}
--- /dev/null
+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);
+ }
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet.api;
+import java.util.*;
+
+/** A ship in a Fleet; each ship consists of a collection of <tt>Dock</tt>s */
+public abstract class Ship implements Iterable<Dock> {
+
+ 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<Dock> 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() + "";
+ }
+}
--- /dev/null
+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; }
+
+}
+
--- /dev/null
+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<Ship> iterator() {
+ HashSet hs = new HashSet<Ship>();
+ 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;
+ }
+}
--- /dev/null
+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; }
+
+}
+
--- /dev/null
+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<MarinaDock> docks = new HashSet<MarinaDock>();
+
+ public Iterator<Dock> iterator() { return (Iterator<Dock>)(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"; }
+}
+
--- /dev/null
+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<String,ShipDescription.Constant> constants = new HashMap<String,ShipDescription.Constant>();
+
+ DockDescription(ShipDescription ship, String name, boolean left, boolean inbox) {
+ this(ship, name, left, inbox, false);
+ }
+ DockDescription(ShipDescription ship, String name, boolean left, boolean inbox, boolean isDockless) {
+ this.left = left;
+ this.ship = ship;
+ this.name = name;
+ this.inbox = inbox;
+ this.isDockless = isDockless;
+ }
+
+ public String getName() { return name; }
+ public boolean isInputDock() { return inbox; }
+ public boolean isOutputDock() { return !inbox; }
+ public boolean isDockless() { return isDockless; }
+
+ /** Indicates if this dock should be drawn on the "left hand side" of the ship for visual purposes */
+ boolean isLeft() { return left; }
+
+ /** 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); }
+}
--- /dev/null
+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(); }
+
+
+}
--- /dev/null
+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; i<Math.min(bv.length(),bv2.length()); i++)
+ bv2.set(i, bv.get(i));
+ instr = DISPATCH_PATH.setval(instr, bv2);
+ }
+
+ boolean dl = false;
+ Instruction pi = d;
+ if (!pi.looping) instr = OS.set(instr);
+ switch(pi.predicate) {
+ case IgnoreFlagD: instr = P_ALWAYS.set(instr); break;
+ case FlagD: instr = P_OLC_ZERO.set(instr); break;
+ case Default: instr = P_OLC_NONZERO.set(instr); break;
+ case FlagA: instr = P_A.set(instr); break;
+ case FlagB: instr = P_B.set(instr); break;
+ case NotFlagA: instr = P_NOT_A.set(instr); break;
+ case NotFlagB: instr = P_NOT_B.set(instr); break;
+ default: throw new RuntimeException("error!");
+ }
+
+ if (d instanceof Tail) {
+ instr = TAIL.set(instr);
+
+ } else if (d instanceof Head) {
+ instr = HEAD.set(instr);
+
+ } else if (d instanceof Shift) {
+ Shift shift = (Shift)d;
+ instr = SHIFT.set(instr);
+ instr = SHIFT.setval(instr, shift.immediate);
+
+ } else if (d instanceof Flush) {
+ instr = FLUSH.set(instr);
+
+ } else if (d instanceof Abort) {
+ instr = ABORT.set(instr);
+
+ } else if (d instanceof Set) {
+ Set s = (Set)d;
+ switch(s.dest) {
+ case InnerLoopCounter:
+ switch(s.source) {
+ case DataLatch:
+ instr = SET_ILC_FROM_DATA_LATCH.set(instr);
+ break;
+ case Immediate:
+ instr = SET_ILC_FROM_IMMEDIATE.setval(SET_ILC_FROM_IMMEDIATE.set(instr), s.immediate);
+ break;
+ case Infinity:
+ instr = SET_ILC_FROM_INFINITY.set(instr);
+ break;
+ }
+ break;
+ case OuterLoopCounter:
+ switch(s.source) {
+ case Decrement:
+ instr = SET_OLC_FROM_OLC_MINUS_ONE.set(instr);
+ break;
+ case DataLatch:
+ instr = SET_OLC_FROM_DATA_LATCH.set(instr);
+ break;
+ case Immediate:
+ instr = SET_OLC_FROM_IMMEDIATE.setval(SET_OLC_FROM_IMMEDIATE.set(instr), s.immediate);
+ break;
+ }
+ break;
+ case Flags: {
+ instr = SET_FLAGS.set(instr);
+ instr = SET_FLAGS_A.setval(instr, flagFunctionToLong(s.newFlagA));
+ instr = SET_FLAGS_B.setval(instr, flagFunctionToLong(s.newFlagB));
+ break;
+ }
+ case DataLatch: {
+ instr = SET_IMMEDIATE.set(instr);
+ instr = SET_IMMEDIATE_EXTEND.setval(instr, s.immediate < 0 ? 1 : 0);
+ instr = SET_IMMEDIATE.setval(instr, s.immediate & ~(-1L << DataLatch_WIDTH));
+ break;
+ }
+ }
+
+ } else if (d instanceof Move) {
+ Move inst = (Move)d;
+ instr = MOVE.set(instr);
+ if (inst.tokenIn) instr = TI.set(instr);
+ if (inst.dataIn) instr = DI.set(instr);
+ if (hack) {
+ if (!inst.latchData) instr = DC.set(instr);
+ System.err.println("WARNING: employing inverted-Dc-bit hack -- DO NOT FORGET TO DISABLE THIS WHEN THE NETLIST GETS UPDATED!");
+ } else {
+ if (inst.latchData) instr = DC.set(instr);
+ }
+ if (inst.dataOut) instr = DO.set(instr);
+ if (inst.tokenOut) instr = TO.set(instr);
+ if (!inst.interruptible) instr = NOT_INTERRUPTIBLE.set(instr);
+
+ if (inst.latchPath) instr = PATH_DATA.set(instr);
+ else if (inst.path!=null) {
+ instr = PATH_IMMEDIATE.set(instr);
+ BitVector bv = getDestAddr(inst.path);
+ BitVector bv2 = new BitVector(PATH_IMMEDIATE.valmaskwidth);
+ for(int i=0; i<Math.min(bv.length(),bv2.length()); i++)
+ bv2.set(i, bv.get(i));
+ instr = PATH_IMMEDIATE.setval(instr, bv2);
+ } else {
+ instr = PATH_NOCHANGE.set(instr);
+ }
+
+ } else {
+ throw new RuntimeException("unrecognized instruction " + d.getClass().getName());
+
+ }
+ return instr;
+ }
+
+ private 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;
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet.two;
+import java.util.*;
+import edu.berkeley.fleet.api.Path;
+
+/**
+ * Represents a path through the switch fabric, from a Dock (source)
+ * to a Destination, plus an optional "signal" value.
+ */
+public abstract class FleetTwoPath extends Path {
+
+}
--- /dev/null
+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 <tt>Dock</tt>s */
+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!");
+ }
+}
--- /dev/null
+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<DockDescription> {
+
+ private String name;
+ private LinkedHashMap<String,DockDescription> docks = new LinkedHashMap<String,DockDescription>();
+ private LinkedHashMap<String,DockDescription> ports = new LinkedHashMap<String,DockDescription>();
+ private HashMap<String,String> sections = new HashMap<String,String>();
+ private HashMap<String,Constant> constants = new HashMap<String,Constant>();
+
+ public String getName() { return name; }
+ public String getSection(String sectionName) { return sections.get(sectionName); }
+ public DockDescription getDockDescription(String name) { return docks.get(name); }
+ public Iterator<DockDescription> iterator() { return docks.values().iterator(); }
+ public Iterable<DockDescription> ports() {
+ return ports.values();
+ }
+
+ //public final LinkedList<PercolatedPort> percolatedPorts = new LinkedList<PercolatedPort>();
+
+ 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<<i); break;
+ case '1': setbits |= (1<<i); break;
+ case '.': break;
+ case 's': signExtend = true; numberOffset = i; numberWidth++; break;
+ case 'u': signExtend = false; numberOffset = i; numberWidth++; break;
+ }
+ }
+ } else {
+ setbits = Long.parseLong(s);
+ clearbits = ~setbits;
+ }
+ }
+ }
+
+}
--- /dev/null
+package edu.berkeley.fleet.util;
+import edu.berkeley.fleet.api.*;
+import edu.berkeley.fleet.*;
+import java.io.*;
+
+/** useful functions for manipulating bit fields within longs */
+public class BitManipulations {
+ public static boolean getBit(int bit, long val) { return ((val & (1L << bit)) != 0); }
+ public static long getSignedField(int highBit, int lowBit, long val) {
+ long ret = getField(highBit, lowBit, val);
+ if ((ret & (1L << ((highBit-lowBit)+1-1))) != 0)
+ ret |= 0xffffffffffffffffL << ((highBit-lowBit)+1);
+ return ret;
+ }
+ public static int getIntField(int highBit, int lowBit, long val) {
+ if (highBit-lowBit+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);
+ }
+}
--- /dev/null
+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<targ.length(); i++)
+ if (targ.get(i))
+ in |= (1L << i);
+ return (in & valmask) >>> 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<s.length(); i++) {
+ char c = s.charAt(s.length()-1-i);
+ switch(c) {
+ case '.': break;
+ case '0': mask |= (1L<<i); val |= (0L<<i); break;
+ case '1': mask |= (1L<<i); val |= (1L<<i); break;
+ case 'v': valmask |= (1L<<i); valmaskmin = Math.min(valmaskmin,i); valmaskmax = Math.max(valmaskmax,i); break;
+ default: throw new Error(""+c);
+ }
+ if (c!='.') allmax = Math.max(allmax,i);
+ }
+ this.mask = mask;
+ this.val = val;
+ this.valmask = valmask;
+ this.valmaskmin = valmaskmin;
+ this.valmaskmax = valmaskmax;
+ this.allmax = allmax+1;
+ this.valmaskwidth = 1 + valmaskmax - valmaskmin;
+ }
+
+ public static long signExtend(long input, int wordWidth) {
+ if ((input & (1L << (wordWidth-1)))!=0)
+ input |= (-1L) << wordWidth;
+ return input;
+ }
+
+}