better debugging messages on ProperStopper
[fleet.git] / testCode / com / sun / vlsi / chips / marina / test / ProperStopper.java
index bc08c7e..484ac8e 100644 (file)
@@ -7,234 +7,241 @@ import com.sun.async.test.ChainControl;
 import com.sun.async.test.ChipModel;
 import com.sun.async.test.Infrastructure;
 import com.sun.async.test.NanosimModel;
+import com.sun.async.test.VerilogModel;
 import com.sun.vlsi.chips.marina.test.MarinaUtils.StateWireState;
 
 public class ProperStopper {
-       // position of strobes in the control chain
-       private static final int BLOCK_STROBE_NDX = 0;
-       private static final int FILL_STROBE_NDX = 1;
-       private static final int GO_STROBE_NDX = 2;
-       private static final int SILENT_STROBE_NDX = 3;
-       private static final int CLEAR_STROBE_NDX = 4;
-       private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
-       
-       // position of inputs in report chain
-       private static final int PREV_STATE_IN_NDX = 0;
-       private static final int FILL_STROBE_IN_NDX = 1;
-       private static final int FILL_STATE_IN_NDX = 2;
-       private static final int STOPPED_IN_NDX = 3;
-       
-       private final String name;
-    private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
+    // position of strobes in the control chain
+    private static final int BLOCK_STROBE_NDX = 0;
+    private static final int FILL_STROBE_NDX = 1;
+    private static final int GO_STROBE_NDX = 2;
+    private static final int SILENT_STROBE_NDX = 3;
+    private static final int CLEAR_STROBE_NDX = 4;
+    private static final int GENERAL_PURPOSE_STROBE_NDX = 5;
+        
+    // position of inputs in report chain
+    private static final int PREV_STATE_IN_NDX = 0;
+    private static final int FILL_STROBE_IN_NDX = 1;
+    private static final int FILL_STATE_IN_NDX = 2;
+    private static final int STOPPED_IN_NDX = 3;
+        
+    private final String name;
+    //private final String captureClockRelPath = "fillStag@1.gaspFill@0.fillScan@1";
+    private final String captureClockRelPath = "fillStag@1";
     // test library direct write mode doesn't understand per register write 
     // enables. We get simulation to work by toggling write clock.
     private final boolean clockHack;
-    private final String captureClockName = "si[4]";
+    private final String captureClockName = "sx[4]";
 
+    /*
     private boolean traceFill = true;
-       private boolean traceDrain = true;
-       
+    private boolean traceDrain = true;
+    */
+    private boolean traceFill = false;
+    private boolean traceDrain = false;
+        
     private final String controlChain, controlPath, 
-                         dataChain, dataPath, 
-                         reportChain, reportPath;
+        dataChain, dataPath, 
+        reportChain, reportPath;
     private final String captureClock;
     private final ChainControls cc;
     private final ChipModel model;
-       private final Indenter indenter;
-
-       protected static void fatal(boolean pred, String msg) {
-               if (pred) Infrastructure.fatal(msg);
-       }
-       private void prln(String msg) {indenter.prln(msg);}
-       private void adjustIndent(int n) {indenter.adjustIndent(n);}
-       
-       /** NanosimModel.setNodeState() requires special path names.  
-        * Each instance name in the path must begin with the character 'x'.
-        * Return a path with the added X's. */
-       private String prefixInstNamesInPathWithX(String path) {
-               StringBuffer sb = new StringBuffer();
-               sb.append('x');
-               for (int i=0; i<path.length(); i++) {
-                       char c = path.charAt(i);
-                       sb.append(c);
-                       if (c=='.')  sb.append('x');
-               }
-               return sb.toString();
-       }
-
-    private BitVector getDatTokAdr() {
-       // strip the two write enable bits
-       return cc.getOutBits(dataPath).get(2, 52);
-    }
-    
+    private final Indenter indenter;
+
+    protected static void fatal(boolean pred, String msg) { MarinaUtils.fatal(pred, msg); }
+    private void prln(String msg) { indenter.prln(msg); }
+    private void adjustIndent(int n) { indenter.adjustIndent(n); }
+        
+    /** NanosimModel.setNodeState() requires special path names.  
+     * Each instance name in the path must begin with the character 'x'.
+     * Return a path with the added X's. */
+    private String prefixInstNamesInPathWithX(String path) {
+        if (model==null) throw new RuntimeException();
+        if (!(model instanceof NanosimModel)) return path;
+        StringBuffer sb = new StringBuffer();
+        sb.append('x');
+        for (int i=0; i<path.length(); i++) {
+            char c = path.charAt(i);
+            sb.append(c);
+            if (c=='.')  sb.append('x');
+        }
+        return sb.toString();
+    }
+  
     private void shiftControl(boolean readEnable, boolean writeEnable) {
-       cc.shift(controlChain, readEnable, writeEnable);
+        //System.out.println("start shiftcontrol");
+        cc.shift(controlChain, readEnable, writeEnable);
+        //System.out.println("  end shiftcontrol");
     }
     private void shiftData(boolean readEnable, boolean writeEnable) {
-       cc.shift(dataChain, readEnable, writeEnable);
-       if (writeEnable) {
-            System.out.println("shiftData(): clockHack="+(clockHack)+
-                               ", (model instanceof NanosimModel)="+(model instanceof NanosimModel));
-               if (clockHack && model instanceof NanosimModel) {
-                       NanosimModel nanoModel = (NanosimModel) model;
-                       nanoModel.setNodeState(captureClock, 1);
-                       nanoModel.waitNS(1);
-                       nanoModel.setNodeState(captureClock, 0);
-               }
-       }
+        //System.out.println("start shiftdata");
+        cc.shift(dataChain, readEnable, writeEnable);
+        if (writeEnable) {
+            if (clockHack && model instanceof NanosimModel) {
+                NanosimModel nanoModel = (NanosimModel) model;
+                nanoModel.setNodeState(captureClock, 1);
+                nanoModel.waitNS(1);
+                nanoModel.setNodeState(captureClock, 0);
+            } else if (clockHack && model instanceof VerilogModel) {
+                VerilogModel nanoModel = (VerilogModel) model;
+                nanoModel.setNodeState(captureClock, 1);
+                nanoModel.waitNS(1);
+                nanoModel.setNodeState(captureClock, 0);
+            }
+        }
+        //System.out.println("  end shiftdata");
     }
     private void shiftReport(boolean readEnable, boolean writeEnable) {
-       cc.shift(reportChain, readEnable, writeEnable);
+        //System.out.println("start shiftreport");
+        cc.shift(reportChain, readEnable, writeEnable);
+        //System.out.println("  end shiftreport");
     }
 
     private StateWireState boolToState(boolean b) {
-       return b ? StateWireState.FULL : StateWireState.EMPTY;
+        return b ? StateWireState.FULL : StateWireState.EMPTY;
     }
     // The first 5 bits of the control chain control the fill and drain stages
     private void setFillDrainControl(BitVector fdCtl) {
-       fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
-       BitVector val = cc.getInBits(controlPath);
-       for (int i=0; i<fdCtl.getNumBits(); i++) {
-               val.set(i, fdCtl.get(i));
-       }
-       cc.setInBits(controlPath, val);
-       shiftControl(false, true);
+        fatal(fdCtl.getNumBits()!=6, "expect 6 proper stopper control bits");
+        BitVector val = cc.getInBits(controlPath);
+        for (int i=0; i<fdCtl.getNumBits(); i++) {
+            val.set(i, fdCtl.get(i));
+        }
+        cc.setInBits(controlPath, val);
+        shiftControl(false, true);
     }
     // The last bit of the control chain controls the general purpose
     // output
     public void setGeneralPurposeOutput(Boolean b) {
-       BitVector val = cc.getInBits(controlPath);
-       val.set(GENERAL_PURPOSE_STROBE_NDX,b);
-       shiftControl(false, true);
+        BitVector val = cc.getInBits(controlPath);
+        val.set(GENERAL_PURPOSE_STROBE_NDX,b);
+        shiftControl(false, true);
     }
     
     //-------------------------- public methods ----------------------------
-    
-    /** Allow subclasses to override the formating of the data. For example,
-     * the Instruction stopper only uses the 37 bits of data so it only 
-     * wants to print the 37 instruction bits */
-    public String formatDataTokAddr(BitVector dta) {
-       return MarinaUtils.formatDataTokAddr(dta);
-    }
 
     /** Put stopper in RUN state */
     public void run() {
-       setFillDrainControl(MarinaUtils.RingIfc.RUN.bits());
+        setFillDrainControl(CommandCodes.RUN.bits());
     }
     /** Put stopper in IDLE state */
     public void idle() {
-       setFillDrainControl(MarinaUtils.RingIfc.IDLE.bits());
+        setFillDrainControl(CommandCodes.IDLE.bits());
     }
     /** Put stopper in FILL state */
     public void fill() {
-       setFillDrainControl(MarinaUtils.RingIfc.FILL.bits());
+        setFillDrainControl(CommandCodes.FILL.bits());
     }
     /** Put stopper in BLOCK state */
     public void block() {
-       setFillDrainControl(MarinaUtils.RingIfc.BLOCK.bits());
+        setFillDrainControl(CommandCodes.BLOCK.bits());
     }
     /** Put stopper in STOP state */
     public void stop() {
-       setFillDrainControl(MarinaUtils.RingIfc.STOP.bits());
+        setFillDrainControl(CommandCodes.STOP.bits());
     }
     /** Put stopper in CLEAR state */
     public void clear() {
-       setFillDrainControl(MarinaUtils.RingIfc.CLEAR.bits());
+        setFillDrainControl(CommandCodes.CLEAR.bits());
     }
     /** Put stopper in SOURCE state */
     public void source() {
-       setFillDrainControl(MarinaUtils.RingIfc.SOURCE.bits());
+        setFillDrainControl(CommandCodes.SOURCE.bits());
     }
     /** Put stopper in STOPSOURCE state */
     public void stopSource() {
-       setFillDrainControl(MarinaUtils.RingIfc.STOPSOURCE.bits());
+        setFillDrainControl(CommandCodes.STOPSOURCE.bits());
     }
     /** Put stopper in SINK state */
     public void sink() {
-       setFillDrainControl(MarinaUtils.RingIfc.SINK.bits());
+        setFillDrainControl(CommandCodes.SINK.bits());
     }
     /** Put stopper in STOPSINK state */
     public void stopSink() {
-       setFillDrainControl(MarinaUtils.RingIfc.STOPSINK.bits());
+        setFillDrainControl(CommandCodes.STOPSINK.bits());
     }
+
     /** Stop a running stopper in order to add items.  Ensure that we don't
      * lose the item in the fill stage.  
      * Exit state: block */
     public void stopToFill() {
-       stop();                                 // go = 0
-       idle();                                 // block = 1
-       block();                                // go = 1
-//     idle();                                 // go = 0
+        stop();                                 // go = 0
+        idle();                                 // block = 1
+        block();                                // go = 1
+        //      idle();                                 // go = 0
     }
+
     /** get value of the state wire preceding the fill stage */
     public StateWireState getPrevStateWire() {
-       shiftReport(true, false);
-       BitVector b = cc.getOutBits(reportPath);
-       int n = b.getNumBits(); 
-       fatal(n!=4, "Bad number of Stopper report bits: "+n);
-       return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
+        shiftReport(true, false);
+        BitVector b = cc.getOutBits(reportPath);
+        int n = b.getNumBits(); 
+        fatal(n!=4, "Bad number of Stopper report bits: "+n);
+        return boolToState(cc.getOutBits(reportPath).get(PREV_STATE_IN_NDX));
     }
+
     /** get the value of drain stage fill wire.
      * The fill wire will be interesting if we doubt that the
      * scan chain works. */
     public boolean getFillStrobe() {
-       shiftReport(true, false);
-       return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
+        shiftReport(true, false);
+        return cc.getOutBits(reportPath).get(FILL_STROBE_IN_NDX);
     }
+
     /** get value of state wire between the fill and drain stages */
     public StateWireState getFillStateWire() {
-       shiftReport(true, false);
-       return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
+        shiftReport(true, false);
+        return boolToState(cc.getOutBits(reportPath).get(FILL_STATE_IN_NDX));
     }
+
     /** get value of drain stage stopped wire */
     public boolean getStopped() {
-       shiftReport(true, false);
+        shiftReport(true, false);
         return cc.getOutBits(reportPath).get(STOPPED_IN_NDX);
     }
+
     public String getReportString() {
-       StringBuffer sb = new StringBuffer();
-       sb.append("Stopper's prev state: ");
-       sb.append(getPrevStateWire()+"\n");
-       sb.append("Stopper's fill stage: ");
-       sb.append(getFillStateWire()+"\n");
-       sb.append("Stopper's stopped: ");
-       sb.append(getStopped()+"\n");
-       return sb.toString();
+        StringBuffer sb = new StringBuffer();
+        sb.append("Stopper's prev state: ");
+        sb.append(getPrevStateWire()+"\n");
+        sb.append("Stopper's fill stage: ");
+        sb.append(getFillStateWire()+"\n");
+        sb.append("Stopper's stopped: ");
+        sb.append(getStopped()+"\n");
+        return sb.toString();
     }
+
     /** construct a ProperStopper */
-    public ProperStopper(String propInst,
-                                        String controlChain, String dataChain, 
-                            String reportChain,
-                            ChainControls cc, ChipModel model,
-                            boolean clockHack,
-                            Indenter indenter) {
-       this.name = propInst;
-       this.controlChain = controlChain;
-       this.controlPath = controlChain+'.'+propInst;
-       this.dataChain = dataChain;
-       this.dataPath = dataChain+'.'+propInst;
-       this.reportChain = reportChain;
-       this.reportPath = reportChain+'.'+propInst;
-       this.captureClock = 
-               prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
-               +'.'+captureClockName;
-       this.cc = cc;
-       this.model = model;
-       this.clockHack = clockHack;
-       this.indenter = indenter;
+    public ProperStopper(String name,
+                         String propInst,
+                         String controlChain, String dataChain, 
+                         String reportChain,
+                         ChainControls cc, ChipModel model,
+                         boolean clockHack,
+                         Indenter indenter) {
+        this.name = name;
+        this.controlChain = controlChain;
+        this.controlPath = controlChain+'.'+propInst;
+        this.dataChain = dataChain;
+        this.dataPath = dataChain+'.'+propInst;
+        this.reportChain = reportChain;
+        this.reportPath = reportChain+'.'+propInst;
+        this.model = model;
+        this.captureClock = 
+            prefixInstNamesInPathWithX(propInst+'.'+captureClockRelPath)
+            +'.'+captureClockName;
+        this.cc = cc;
+        this.clockHack = clockHack;
+        this.indenter = indenter;
     }
+
     /** Reset ProperStopper after the JTAG TRST has been pulsed */
     public void resetAfterMasterClear() {
-       BitVector we = new BitVector(2, "write enable");
-       BitVector data = new BitVector(37, "data");
-       BitVector tag = new BitVector(1, "tag");
-       BitVector addr = new BitVector(14, "addr");
-       we.setFromLong(0);
-       data.setFromLong(0);
-       tag.setFromLong(0);
-       addr.setFromLong(0);
-       BitVector wdta = we.cat(data).cat(tag).cat(addr);
-       
+        BitVector we = new BitVector(2, "write enable");
+        BitVector packet = new BitVector(MarinaPacket.PACKET_WIDTH, "packet");
+        we.setFromLong(0);
+        packet.setFromLong(0);
+        BitVector wdta = we.cat(packet);
         cc.setInBits(dataPath, wdta);
     }
     
@@ -242,141 +249,177 @@ public class ProperStopper {
      * Fill stage must be empty. 
      * You must stop stopper before calling fill.
      * exit state: block */
-    public void fill(BitVector dta) {
-       if (traceFill) prln("Begin fill. stopper="+name);
-       adjustIndent(2);
-       
-       int n = dta.getNumBits();
-       fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
-       
-       // make sure fill stage is empty
-       StateWireState myState = getFillStateWire();
-       fatal(myState!=StateWireState.EMPTY, 
-                 "fill: fill stage already full");
-       
-       if (traceFill) prln("writing data: "+formatDataTokAddr(dta));
-       
-       idle();                                 // block = 1, go = 0
-
-       BitVector wrEn = new BitVector(2, "write enable");
-       wrEn.setFromLong(3);
-        BitVector bv1 = wrEn.cat(dta);
-       cc.setInBits(dataPath, bv1);
-        prln("first shift");
-       shiftData(false, true);
-
-        BitVector bv0 = new BitVector(bv1.getNumBits(), "");
-        for(int i=0; i<bv0.getNumBits(); i++) bv0.set(i, false);
-       cc.setInBits(dataPath, bv0);
-        prln("second shift");
-       shiftData(false, false);
-
-        prln("third shift");
-       shiftData(true, false);
-       BitVector bv2 = cc.getOutBits(dataPath);
-        System.out.println("bv1 = " + bv1);
-        System.out.println("bv2 = " + bv2);
-       
-       fill();                                 // fill = 1
-       idle();                                 // fill = 0
-       block();                                // go = 1
-//     idle();
-       
-       model.waitNS(5);
-
-       // debugging
-       if (traceFill) prln(getReportString());
-       
-       // if data chain is shifted in the future, don't write!
-       wrEn.setFromLong(0);
-       cc.setInBits(dataPath, wrEn.cat(dta));
-       
-       adjustIndent(-2);
-       if (traceFill) prln("End fill");
+    private void fill_(BitVector dta) {
+        adjustIndent(2);
+        
+        int n = dta.getNumBits();
+        fatal(n!=(37+1+14), "fill: wrong num bits: "+n);
+        
+        // make sure fill stage is empty
+        StateWireState myState = getFillStateWire();
+        fatal(myState!=StateWireState.EMPTY, "fill: fill stage already full");
+        
+        idle();                                 // block = 1, go = 0
+
+        BitVector wrEn = new BitVector(2, "write enable");
+        wrEn.setFromLong(3);
+        cc.setInBits(dataPath, wrEn.cat(dta));
+        shiftData(false, true);
+        
+        fill();                                 // fill = 1
+        idle();                                 // fill = 0
+        block();                                // go = 1
+        //      idle();
+        
+        model.waitNS(5);
+
+        // debugging
+        if (traceFill) prln(getReportString());
+        
+        // if data chain is shifted in the future, don't write!
+        wrEn.setFromLong(0);
+        cc.setInBits(dataPath, wrEn.cat(dta));
+        
+        adjustIndent(-2);
+        if (traceFill) prln("End fill");
     }
+
+    public void fill(BitVector dat) {
+        if (traceFill) prln("Begin fill. stopper="+name);
+        if (traceFill) prln("writing data: "+new MarinaPacket(dat));
+        fill_(dat);
+    }
+
+    public void fill(MarinaPacket mp) {
+        if (traceFill) prln("Begin fill. stopper="+name);
+        if (traceFill) prln("writing data: "+mp);
+        fill_(mp.toSingleBitVector());
+    }
+
     /** Insert items from a list, one by one. 
      * You must stop stopper before calling fillMany()
      * exit state: block */
     public void fillMany(List<BitVector> data) {
-       prln("Begin fillMany. stopper="+name+" numWords="+data.size());
-       adjustIndent(2);
-       int cnt = 0;
-       for (BitVector bv : data) {
-               if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
-               fill(bv);
-       }
-       adjustIndent(-2);
-       prln("end fillMany");
+        prln("Begin fillMany. stopper="+name+" numWords="+data.size());
+        adjustIndent(2);
+        int cnt = 0;
+        for (BitVector bv : data) {
+            if (traceFill) prln("fillStopperMany: writing word number: "+cnt++);
+            fill(bv);
+        }
+        adjustIndent(-2);
+        prln("end fillMany");
     }
+
     /** Remove one item from fill stage. Return that item.
      * An item must be available.
      * drain() will stop cleanly.
      * exit state: stop */
     public BitVector drain() {
-       stop();                                 // all zero, block = 0, go = 0
-       
-       // make sure an item is available
-       StateWireState myState=getFillStateWire();
-       fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
+        stop();                                 // all zero, block = 0, go = 0
+        
+        // make sure an item is available
+        StateWireState myState=getFillStateWire();
+        fatal(myState==StateWireState.EMPTY, "drain: fill stage empty");
 
-       return drainNoCheck();
+        return drainNoCheck();
     }
+
     /** Remove one item from fill stage. Return that item.
      * Assume that an item is available. 
      * entry state: stop
      * exit state: stop */
     private BitVector drainNoCheck() {
-       shiftData(true, false);
-       BitVector ans = getDatTokAdr();
+        shiftData(true, false);
 
-       idle();                                 // block = 1
-       clear();                                // clear = 1
-       idle();                                 // clear = 0
-       stop();                                 // block = 0
+        // strip the two write enable bits
+        BitVector ans = cc.getOutBits(dataPath).get(2, 52);
 
-       if (traceDrain) prln("drain stopper="+name+" data="+formatDataTokAddr(ans));
-       return ans;
+        idle();                                 // block = 1
+        clear();                                // clear = 1
+        idle();                                 // clear = 0
+        stop();                                 // block = 0
+
+        if (traceDrain) prln("drain stopper="+name+" data="+new MarinaPacket(ans));
+        return ans;
     }
+
     /** Remove as many items as possible from the fill stage.
      * drainStopperMany() will stop cleanly.
      * exit state: stop */
     public List<BitVector> drainMany() {
-       return drainMany(Integer.MAX_VALUE);
+        return drainMany(Integer.MAX_VALUE);
     }
 
     /** Remove up to maxNbItems items from the fill stage.
      * drainStopperMany() will stop cleanly.
      * exit state: stop */
     public List<BitVector> drainMany(int maxNbItems) {
-       prln("begin drainMany. stopper="+name);
-       adjustIndent(2);
-       
-       stop();
-       
-       List<BitVector> ans = new ArrayList<BitVector>();
-       
-       int cnt = 0;
-       while (true) {
-               StateWireState myState=getFillStateWire();
-
-               // debugging
-               if (traceDrain) prln(getReportString());
-
-               if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
-               
-               if (traceDrain) prln("drainMany: reading word number: "+cnt++);
-               
-               BitVector d = drainNoCheck();
-
-               ans.add(d);
-       }
-       
-       adjustIndent(-2);
-       prln("end drainMany, got "+ans.size()+" items");
-       
-       return ans;
+        adjustIndent(2);
+        
+        stop();
+        
+        List<BitVector> ans = new ArrayList<BitVector>();
+        
+        int cnt = 0;
+        while (true) {
+            StateWireState myState=getFillStateWire();
+
+            // debugging
+            if (traceDrain) prln(getReportString());
+
+            if (myState==StateWireState.EMPTY || cnt>=maxNbItems) break;
+                
+            cnt++;
+            indenter.pr("  drain"+(maxNbItems==0?"":"Many")+
+                        ": reading word"+(maxNbItems==0?":":" number "+cnt+
+                        "/"+(maxNbItems==Integer.MAX_VALUE
+                             ?"unlimited":("at-most-"+maxNbItems))+": "));
+
+            BitVector d = drainNoCheck();
+            if (maxNbItems>1)
+                prln("  got "+new MarinaPacket(d));
+
+            ans.add(d);
+        }
+        
+        prln("end drainMany, got "+ans.size()+" items");
+        adjustIndent(-2);
+        
+        return ans;
     }
 
 
+    /**
+     * (Note by Bill and Adam: Ivan has struck again!)
+     * As of 05 March 2009 the new bits are:
+     *    Block Extra Fill Go Clear Silent
+     *      => Note: "Extra" gets fed to the mux in the counter
+     *         that selects the frequency output that goes off-chip
+     *
+     * Caution: Ivan changes the order of the ProperStopper control bits 
+     * from chip to chip.  Here is the current order for Marina
+     * as of 14 Aug 2008: 
+     *  Block, Fill, Go, Silent, Clear
+     *
+     *  The old bit order for Infinity was: Fill, Block, Clear, Silent, Go
+     */
+    private static enum CommandCodes {
+        RUN        ("000100"),
+            IDLE       ("100000"),
+            FILL       ("101000"),
+            BLOCK      ("100100"),
+            STOP       ("000000"),
+            CLEAR      ("100010"),
+            SOURCE     ("001100"),
+            STOPSOURCE ("001000"),
+            SINK       ("000101"),
+            STOPSINK   ("000001");
+        private BitVector scanBits;
+        CommandCodes(String bits) {
+            scanBits = new BitVector(bits,"CommandCodes");
+        }
+        public BitVector bits() {return scanBits;}
+    }
 
 }