eliminate need for adam.jar
authorAdam Megacz <adam.megacz@sun.com>
Tue, 3 Mar 2009 20:37:49 +0000 (20:37 +0000)
committerAdam Megacz <adam.megacz@sun.com>
Tue, 3 Mar 2009 20:37:49 +0000 (20:37 +0000)
21 files changed:
testCode/edu/berkeley/fleet/api/BitVector.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/Destination.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/Dock.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/Fleet.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/FleetProcess.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/Instruction.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/Path.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/Predicate.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/api/Ship.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/marina/MarinaDock.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/marina/MarinaFleet.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/marina/MarinaPath.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/marina/MarinaShip.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/two/DockDescription.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/two/FleetTwoDock.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/two/FleetTwoFleet.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/two/FleetTwoPath.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/two/FleetTwoShip.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/two/ShipDescription.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/util/BitManipulations.java [new file with mode: 0644]
testCode/edu/berkeley/fleet/util/Mask.java [new file with mode: 0644]

diff --git a/testCode/edu/berkeley/fleet/api/BitVector.java b/testCode/edu/berkeley/fleet/api/BitVector.java
new file mode 100644 (file)
index 0000000..8b08fc6
--- /dev/null
@@ -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; 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;
+    }
+}
+
+
diff --git a/testCode/edu/berkeley/fleet/api/Destination.java b/testCode/edu/berkeley/fleet/api/Destination.java
new file mode 100644 (file)
index 0000000..238db4f
--- /dev/null
@@ -0,0 +1,21 @@
+package edu.berkeley.fleet.api;
+
+/**
+ *  A physical destination on the switch fabric -- may have multiple
+ *  paths to it from any particular source.
+ */
+public abstract class Destination {
+
+    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();
+
+}            
diff --git a/testCode/edu/berkeley/fleet/api/Dock.java b/testCode/edu/berkeley/fleet/api/Dock.java
new file mode 100644 (file)
index 0000000..be4d558
--- /dev/null
@@ -0,0 +1,48 @@
+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(); }
+}            
diff --git a/testCode/edu/berkeley/fleet/api/Fleet.java b/testCode/edu/berkeley/fleet/api/Fleet.java
new file mode 100644 (file)
index 0000000..ce0cfb2
--- /dev/null
@@ -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
+ *  <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()");
+    }
+}
diff --git a/testCode/edu/berkeley/fleet/api/FleetProcess.java b/testCode/edu/berkeley/fleet/api/FleetProcess.java
new file mode 100644 (file)
index 0000000..1db837f
--- /dev/null
@@ -0,0 +1,55 @@
+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();
+}
diff --git a/testCode/edu/berkeley/fleet/api/Instruction.java b/testCode/edu/berkeley/fleet/api/Instruction.java
new file mode 100644 (file)
index 0000000..7c0719f
--- /dev/null
@@ -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 <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;"; }
+    }
+
+}
diff --git a/testCode/edu/berkeley/fleet/api/Path.java b/testCode/edu/berkeley/fleet/api/Path.java
new file mode 100644 (file)
index 0000000..5de20fb
--- /dev/null
@@ -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 (file)
index 0000000..2556e47
--- /dev/null
@@ -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 (file)
index 0000000..f5eafa4
--- /dev/null
@@ -0,0 +1,37 @@
+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() + "";
+    }
+}
diff --git a/testCode/edu/berkeley/fleet/marina/MarinaDock.java b/testCode/edu/berkeley/fleet/marina/MarinaDock.java
new file mode 100644 (file)
index 0000000..05a301a
--- /dev/null
@@ -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 (file)
index 0000000..192e9b6
--- /dev/null
@@ -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<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;
+    }
+}
diff --git a/testCode/edu/berkeley/fleet/marina/MarinaPath.java b/testCode/edu/berkeley/fleet/marina/MarinaPath.java
new file mode 100644 (file)
index 0000000..0c9ba58
--- /dev/null
@@ -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 (file)
index 0000000..c2b8aad
--- /dev/null
@@ -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<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"; }
+}
+
diff --git a/testCode/edu/berkeley/fleet/two/DockDescription.java b/testCode/edu/berkeley/fleet/two/DockDescription.java
new file mode 100644 (file)
index 0000000..eccbe6e
--- /dev/null
@@ -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<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); }
+}
diff --git a/testCode/edu/berkeley/fleet/two/FleetTwoDock.java b/testCode/edu/berkeley/fleet/two/FleetTwoDock.java
new file mode 100644 (file)
index 0000000..3990c1d
--- /dev/null
@@ -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 (file)
index 0000000..e446dd0
--- /dev/null
@@ -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; 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;
+    }
+
+}
diff --git a/testCode/edu/berkeley/fleet/two/FleetTwoPath.java b/testCode/edu/berkeley/fleet/two/FleetTwoPath.java
new file mode 100644 (file)
index 0000000..67065d9
--- /dev/null
@@ -0,0 +1,11 @@
+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 {
+
+}            
diff --git a/testCode/edu/berkeley/fleet/two/FleetTwoShip.java b/testCode/edu/berkeley/fleet/two/FleetTwoShip.java
new file mode 100644 (file)
index 0000000..5a89616
--- /dev/null
@@ -0,0 +1,33 @@
+package edu.berkeley.fleet.two;
+import edu.berkeley.fleet.api.*;
+import java.util.*;
+
+/** A ship in a Fleet; each ship consists of a collection of <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!");
+    }
+}
diff --git a/testCode/edu/berkeley/fleet/two/ShipDescription.java b/testCode/edu/berkeley/fleet/two/ShipDescription.java
new file mode 100644 (file)
index 0000000..dbc682e
--- /dev/null
@@ -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<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;
+            }
+        }
+    }
+
+}
diff --git a/testCode/edu/berkeley/fleet/util/BitManipulations.java b/testCode/edu/berkeley/fleet/util/BitManipulations.java
new file mode 100644 (file)
index 0000000..3ce48c3
--- /dev/null
@@ -0,0 +1,51 @@
+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);
+    }
+}
diff --git a/testCode/edu/berkeley/fleet/util/Mask.java b/testCode/edu/berkeley/fleet/util/Mask.java
new file mode 100644 (file)
index 0000000..f252430
--- /dev/null
@@ -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<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;
+    }
+
+}