test script updates
[fleet.git] / testCode / com / sun / vlsi / chips / marina / test / Marina.java
index 43f1b5f..8c9cced 100644 (file)
@@ -5,241 +5,434 @@ import com.sun.async.test.ChainControl;
 import com.sun.async.test.ChipModel;
 import com.sun.async.test.JtagTester;
 import com.sun.async.test.NanosimModel;
+import com.sun.async.test.VerilogModel;
+
+import edu.berkeley.fleet.api.Instruction;
+import edu.berkeley.fleet.marina.MarinaPath;
 
 /** The Marina object will eventually represent the Marina test chip.  
  * Right now, it doesn't do much of anything. It just helps me exercise
  * my test infrastructure. */
 public class Marina {
-    private static final String DATA_CHAIN =    "marina.marina_data";      
-    private static final String CONTROL_CHAIN = "marina.marina_control";
-       private static final String REPORT_CHAIN =  "marina.marina_report";
-       
-       private static final String OLC_PATH = MarinaTest.NEW ?
-                       "dataPath@0.ringSkip@0.skipCoun@0.scanKx6@0" 
-               :
-                       "dataPath@0.ringSkip@0.skipCoun@0.scanKx6@0"; 
-       private static final String ILC_PATH = MarinaTest.NEW ?
-                       "dataPath@0.ringSkip@0.skipCoun@0.scanKx9@0"
-               :
-                       "dataPath@0.ringSkip@0.skipCoun@0.scanKx9@0";
-       private static final String FLAGS_PATH = MarinaTest.NEW ?
-                       "dataPath@0.ringSkip@0.skipCoun@0.scanKx2@0"
-               :
-                       "dataPath@0.ringSkip@0.skipCoun@0.scanKx2@0";
-       private static final String INSTR_RING_CONTROL_PATH = MarinaTest.NEW ?
-                       "southFif@0.tapPropS@0.tapStage@1"
-               :
-                       "southFif@0.tapPropS@0.tapStage@1";
-       private static final String TOK_FIFO_PATH = "tokenFIF@0";
-       private static final String TOK_PRED_PATH = "dataPath@0.ringSkip@0.moveLit@1.scanKhx5@0.scanCell@5";
-       private static final String INSTRUCTION_COUNTER_PATH = "southFif@0.tapPropS@0";
-       private static final String DATA_COUNTER_PATH = "northFif@0.fillDrai@0";
-       private static final int COUNTER_LENGTH = 34;
-       private static final int INSTRUCTION_SEND_NDX = MarinaTest.NEW ? 1 : 1;
-       private static final int INSTRUCTION_RECIRCULATE_NDX = 0;
-       
-       private static final int A_FLAG_NDX = MarinaTest.NEW ? 0 : 0;
-       private static final int B_FLAG_NDX = MarinaTest.NEW ? 1 : 1;
-       
-       public static final int SOUTH_RING_CAPACITY = 11;
-       
-       // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
-       public class Ilc {
-               // value is bit reversed and complemented
-               private int value;
-               private Ilc() {
-               shiftReport(true, false);
-               value = (int) cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH).bitReverse().not().toLong();
-               }
-           /** Get the inner loop counter done bit. */
-           public boolean getDone() {
-                       return (value & 0x100) != 0;
-           }
-           /** Get the inner loop counter infinity bit */
-               public boolean getInfinity() {
-                       return (value & 0x80) == 0;
-               }
-           /** Get the inner loop counter zero bit. If the zero bit is true
-            * then the hardware considers the inner loop counter to be zero
-            * regardless of the state of the count bits */
-               public boolean getZero() {
-                       return (value & 0x40) != 0;
-               }
-               /** Get the 6 bits of count of the inner loop counter */
-               public int getCount() {
-                       return value & 0x3f;
-               }
-       }
-       
-       private final Indenter indenter;
-
-       // The name of the scan chain
-       // The instance path, from the top cell of the netlist, of the instance of infinityWithCover 
-    private final ChainControl cc;           // specifies the scan chain
+
+    public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE  = 5;
+    public static final int INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO = MarinaPath.SIGNAL_BIT_INDEX;
+
+    public static final String DATA_CHAIN =    "marina.marina_data";      
+    public static final String CONTROL_CHAIN = "marina.marina_control";
+    public static final String REPORT_CHAIN =  "marina.marina_report";
+        
+    private static String prefix = "marinaGu@0.outDockW@3.marinaOu@1.";
+
+    private static final String OLC_PATH_EVEN = 
+        prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@1"; // bits 2,4,6
+    private static final String OLC_PATH_ODD = 
+        prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.scanEx3h@2"; // bits 1,3,5
+    private static final String OLC_PATH_KESSEL = 
+        prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.counte@0.adamScan@1.scanEx6h@";
+    private static final String ILC_PATH_ODD = 
+        prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@0"; // bits 1,3,5,7
+    private static final String ILC_PATH_EVEN = 
+        prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx4h@1"; // bits 2,4,6,8
+    private static final String FLAGS_PATH = 
+        prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.scanEx3h@0";
+
+    private static final String INSTR_RING_CONTROL_PATH = 
+        prefix+"southFif@1.tapPropS@1.tapStage@2";
+    private static final String TOK_FIFO_PATH =
+        prefix+"tokenFIF@1";
+    private static final String INSTRUCTION_COUNTER_PATH =
+        prefix+"southFif@1.tapPropS@1.instruct@0";
+    private static final String DATA_COUNTER_PATH =
+        prefix+"northFif@1.fillDrai@1.instruct@0";
+    private static final String TOK_PRED_PATH =
+        prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.scanEx2h@0.scanCell@10";
+
+    private static final int COUNTER_LENGTH = 34;
+    private static final int INSTRUCTION_SEND_NDX = 1;
+    private static final int INSTRUCTION_RECIRCULATE_NDX = 0;
+
+    public static final int INSTRUCTION_LENGTH = 36;
+        
+    private static final int A_FLAG_NDX = 0;
+    private static final int B_FLAG_NDX = 1;
+        
+    public static final int SOUTH_RING_CAPACITY = 11;
+        
+    // ILC appears in scan chain as "count[1:6], zLo, i, dLo"
+    public class Ilc {
+        // value is bit reversed and complemented
+        private int value;
+        private Ilc() {
+            shiftReport(true, false);
+            BitVector odd  = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_ODD).bitReverse().not();
+            BitVector even = cc.getOutBits(REPORT_CHAIN+"."+ILC_PATH_EVEN).bitReverse().not();
+            BitVector ret  = new BitVector(8, "olc");
+            for(int i=0; i<4; i++) {
+                ret.set(i*2+1, odd.get(i));
+                ret.set(i*2,   even.get(i));
+            }
+            value = (int)ret.toLong();
+        }
+        /** Get the inner loop counter done bit. */
+        public boolean getDone() {
+            return (value & 0x40) != 0;
+        }
+        /** Get the inner loop counter infinity bit */
+        public boolean getInfinity() {
+            return (value & 0x80) != 0;
+        }
+        /** Get the 6 bits of count of the inner loop counter */
+        public int getCount() {
+            return value & 0x3f;
+        }
+        public String toString() {
+            return "[ilc, count="+getCount()+", infinity="+getInfinity()+", done="+getDone()+"]";
+        }
+    }
+        
+    private final Indenter indenter;
+
+    // The name of the scan chain
+    // The instance path, from the top cell of the netlist, of the instance of infinityWithCover 
+    private final ChainControls cc;           // specifies the scan chain
     private final ChipModel model;
     public final ProperStopper data;
     public final InstructionStopper instrIn;
     
-       private void prln(String msg) {indenter.prln(msg);}
-       private void pr(String msg) {indenter.pr(msg);}
+    private void prln(String msg) {indenter.prln(msg);}
+    private void pr(String msg) {indenter.pr(msg);}
     
     /** Shift the report scan chain */
-       private void shiftReport(boolean readEnable, boolean writeEnable) {
-         cc.shift(REPORT_CHAIN, readEnable, writeEnable);
-       }
+    private void shiftReport(boolean readEnable, boolean writeEnable) {
+        cc.shift(REPORT_CHAIN, readEnable, writeEnable);
+    }
     
     /** Shift the report scan chain */
-       private void shiftControl(boolean readEnable, boolean writeEnable) {
-         cc.shift(CONTROL_CHAIN, readEnable, writeEnable);
-       }
-       
-       /** Shift the data scan chain */
-       private void shiftData(boolean readEnable, boolean writeEnable) {
-         cc.shift(DATA_CHAIN, readEnable, writeEnable);
-       }
-
-       public Marina(ChainControl cc, ChipModel model, Indenter indenter) {
+    private void shiftControl(boolean readEnable, boolean writeEnable) {
+        cc.shift(CONTROL_CHAIN, readEnable, writeEnable);
+    }
+        
+    /** Shift the data scan chain */
+    private void shiftData(boolean readEnable, boolean writeEnable) {
+        cc.shift(DATA_CHAIN, readEnable, writeEnable);
+    }
+
+    public Marina(ChainControls cc, ChipModel model, boolean clockHack, Indenter indenter) {
         this.cc = cc;
         this.model = model;
         this.indenter = indenter;
-        data = new ProperStopper("northFif@0.fillDrai@0.properSt@0",
-                                         CONTROL_CHAIN, 
-                                         DATA_CHAIN,  
-                                         REPORT_CHAIN,
-                                         cc, model, indenter);
-        instrIn = new InstructionStopper("southFif@0.tapPropS@0.properSt@0", 
-                                     CONTROL_CHAIN,
-                                     DATA_CHAIN,
-                                     REPORT_CHAIN,
-                                     cc, model, indenter);
-    }
-    public void masterClear(JtagTester tester) {
-       final double WIDTH = 10; // ns
-       NanosimModel nModel = (NanosimModel) model;
-               // Put a high going pulse on the internal chip master clear signal
-        nModel.setNodeVoltage("sid[9]",1.0);
-        nModel.setNodeVoltage("sic[9]",1.0);
-        nModel.setNodeVoltage("sir[9]",1.0);
-        nModel.waitNS(WIDTH);
-        nModel.setNodeVoltage("sid[9]",0.0);
-        nModel.setNodeVoltage("sic[9]",0.0);
-        nModel.setNodeVoltage("sir[9]",0.0);
-        nModel.waitNS(1);
+        data = new ProperStopper("north fifo",
+                                 prefix+"northFif@1.fillDrai@1.properSt@1",
+                                 CONTROL_CHAIN, 
+                                 DATA_CHAIN,  
+                                 REPORT_CHAIN,
+                                 cc, model, clockHack, indenter);
+        instrIn = new InstructionStopper("south fifo",
+                                         prefix+"southFif@1.tapPropS@1.properSt@1", 
+                                         CONTROL_CHAIN,
+                                         DATA_CHAIN,
+                                         REPORT_CHAIN,
+                                         cc, model, clockHack, indenter);
+    }
+    public void masterClear() {
+        final double WIDTH = 10; // ns
+        // Put a high going pulse on the internal chip master clear signal
+        if (model instanceof VerilogModel) {
+
+            data.clear();
+            instrIn.clear();
+
+            VerilogModel vm = (VerilogModel)model;
+            //
+            // In real life the flags come up with some undefined
+            // value.  In verilog we need to prevent the X'es from
+            // propagating, so we force the flags to a known value
+            //
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_", 0);
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_", 1);
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_", 0);
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_", 1);
+
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_", 1);
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_", 0);
+
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50", 0);       // A
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50", 0);       // B
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_", 0); // C
+
+            // possible C-flag inputs
+            vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]", 0);
+            vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]", 0);
+
+            // force the OLC to zero
+            if (!kesselsCounter)
+                for(int i=1; i<=6; i++)
+                    vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]", (i==1)?0:1);
+
+            // set the ILC input to 1
+            for(int i=1; i<=8; i++) {
+                if (i!=7)
+                    vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"]", (i==1)?0:1);
+            }
+
+            vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 1);
+            model.waitNS(1000);
+            vm.setNodeState(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire", 0);
+            model.waitNS(1000);
+
+            vm.setNodeState("sid[9]", 1);
+            vm.setNodeState("sic[9]", 1);
+            vm.setNodeState("sir[9]", 1);
+            model.waitNS(1000);
+            vm.setNodeState("sid[9]", 0);
+            vm.setNodeState("sic[9]", 0);
+            vm.setNodeState("sir[9]", 0);
+            model.waitNS(1000);
+
+            // pulse ilc[load] and olc[load]
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_", 1);
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_", 1);
+            vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_", 1);
+            if (!kesselsCounter)
+                vm.setNodeState(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_", 1);
+            model.waitNS(100);
+            model.waitNS(1);
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_load_");
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_decLO_");
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.ilc_torpLO_");
+            if (!kesselsCounter)
+                vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.olc_load_");
+
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__set_");
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_A__clr_");
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__set_");
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_B__clr_");
+
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__set_");
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flag_D__clr_");
+
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@0.net_50");
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.flags@0.aFlag@1.net_50");
+
+            // Every move instruction, even those with Ti=0,Di=0,
+            // loads the C-flag.  It will get loaded with an "X",
+            // which will then leak into the flags and from there the
+            // predicate.
+            vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.litDandP@0.latch2in@0.hi2inLat@0.latchKee@0.out_B_");
+            vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE+1)+"]");
+            vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.ain["+(INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO+1)+"]");
+            vm.releaseNode(prefix+"northFif@1.upDown8w@2.weakStag@22.addr1in2@0.fire");
+
+            for(int i=1; i<=8; i++) {
+                if (i!=7)
+                    vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.ilcMoveO@0.ilc@0.\\inLO["+i+"] ");
+            }
+            model.waitNS(1000);
+
+            if (!kesselsCounter)
+                for(int i=1; i<=6; i++)
+                    vm.releaseNode(prefix+"outputDo@0.outM1Pre@0.outDockP@0.outDockC@0.olcWcont@0.olc@0.inLO["+i+"]");
+
+            // the proper stopper states come up in an undefined ("X")
+            // state, so under Verilog we need to force them to a
+            // known state
+
+            data.idle();
+            instrIn.idle();
+
+        } else {
+            NanosimModel nModel = (NanosimModel) model;
+            /*
+            nModel.setNodeVoltage(prefix+"sid[9]",1.0);
+            nModel.setNodeVoltage(prefix+"sic[9]",1.0);
+            nModel.setNodeVoltage(prefix+"sir[9]",1.0);
+            nModel.waitNS(WIDTH);
+            nModel.setNodeVoltage(prefix+"sid[9]",0.0);
+            nModel.setNodeVoltage(prefix+"sic[9]",0.0);
+            nModel.setNodeVoltage(prefix+"sir[9]",0.0);
+            nModel.waitNS(1);
+            */
+            nModel.setNodeVoltage("mc",1.0);
+            nModel.waitNS(WIDTH);
+            nModel.setNodeVoltage("mc",0.0);
+            nModel.waitNS(1);
+        }
         resetAfterMasterClear();
     }
     private void resetAfterMasterClear() {
-       // The following call to ChainControl.resetInBits() is vital!
-       // If you forget, then the inBits member initializes 
-       // with random data. Then when you do your first write,
-       // some bits are written randomly.
-       cc.resetInBits();
-
-       // For reset, I want to clear all the stoppers simultaneously
-       data.clear();
-       //tokOut.clear();
-       instrIn.clear();
-       
-       data.stop();
-       //tokOut.stop();
-       instrIn.stop();
-       
-       data.resetAfterMasterClear();
-       //tokOut.resetAfterMasterClear();
-       instrIn.resetAfterMasterClear();
+        // The following call to ChainControl.resetInBits() is vital!
+        // If you forget, then the inBits member initializes 
+        // with random data. Then when you do your first write,
+        // some bits are written randomly.
+        cc.resetInBits();
+
+        // For reset, I want to clear all the stoppers simultaneously
+        data.clear();
+        //tokOut.clear();
+        instrIn.clear();
+        
+        data.stop();
+        //tokOut.stop();
+        instrIn.stop();
+        
+        data.resetAfterMasterClear();
+        //tokOut.resetAfterMasterClear();
+        instrIn.resetAfterMasterClear();
     }
+    public static boolean kesselsCounter = true;
+
     /** Get the 6 bit outer loop counter. */
     public int getOLC() {
-       shiftReport(true, false);
-       return (int) cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH).bitReverse().not().toLong();
+        shiftReport(true, false);
+        if (kesselsCounter) {
+            BitVector bits = null;
+            for(int i=0; i<4; i++) {
+                BitVector x = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_KESSEL+i);
+                //System.out.println("bits are: " + x);
+                bits = bits==null ? x : bits.cat(x);
+            }
+            //System.out.println("kesselsCounter = " + bits);
+            int first = 0;
+            int second = 0;
+            for(int i=0; i<6; i++) first  |= bits.get(4+i*3)   ? (1<<i) : 0;
+            for(int i=0; i<6; i++) second |= bits.get(4+i*3+2) ? (1<<i) : 0;
+            return (first+second);
+        } else {
+            BitVector odd = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_ODD).bitReverse();
+            BitVector even = cc.getOutBits(REPORT_CHAIN+"."+OLC_PATH_EVEN).bitReverse();
+            odd = odd.not();
+            even = even.not();
+            BitVector bv = new BitVector(6, "olc");
+            for(int i=0; i<3; i++) {
+                bv.set(i*2,   odd.get(i));
+                bv.set(i*2+1, even.get(i));
+            }
+            return (int)bv.toLong();
+        }
     }
     /** Get the 7 bit inner loop counter. The MSB is the zero bit.
      * The low order 6 bits are the count */
     public Ilc getILC() {
-       return new Ilc();
+        return new Ilc();
     }
-       /** Get the A flag */
+    /** Get the A flag */
     public boolean getFlagA() {
-       shiftReport(true, false);
-       return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(A_FLAG_NDX);
+        shiftReport(true, false);
+        return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(A_FLAG_NDX);
     }
     /** Get the B flag */
     public boolean getFlagB() {
-       shiftReport(true, false);
-       return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(B_FLAG_NDX);
+        shiftReport(true, false);
+        return cc.getOutBits(REPORT_CHAIN+"."+FLAGS_PATH).get(B_FLAG_NDX);
     }
-    /** Get the D register */
-    public BitVector getDRegister() {
-        throw new RuntimeException("please implement this!");
-    }
-    /** return value of instruction counter. Instruction counter is in south ring
-     * after the proper stopper. Caution: instruction counter is written by all scans, 
+    /** return value of instruction counter. Instruction counter counts 
+     * the instructions flowing through 1/2 of alternating FIFO.
+     * Caution: instruction counter is written by all scans, 
      * regardless of readEnable or writeEnable! */
     public long getInstructionCounter() {
-       shiftData(true, false);
-       BitVector count = cc.getOutBits(REPORT_CHAIN+"."+INSTRUCTION_COUNTER_PATH);
-       int sz = count.getNumBits(); 
-       MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
-                            " expected: "+COUNTER_LENGTH);
-       return count.bitReverse().toLong();
-    }
-    /** return value of data counter. Data counter is in north ring
-     * after the proper stopper. Caution: data counter is written by all scans, 
+        shiftData(true, false);
+        BitVector count = cc.getOutBits(DATA_CHAIN+"."+INSTRUCTION_COUNTER_PATH);
+        int sz = count.getNumBits(); 
+        MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
+                         " expected: "+COUNTER_LENGTH);
+        return count.bitReverse().toLong();
+    }
+    /** return value of data counter. Data counter counts items flowing
+     * through drain stage of data proper stopper. 
+     * Caution: data counter is written by all scans, 
      * regardless of readEnable or writeEnable! */
     public long getDataCounter() {
-       shiftData(true, false);
-       BitVector count = cc.getOutBits(REPORT_CHAIN+"."+DATA_COUNTER_PATH);
-       int sz = count.getNumBits(); 
-       MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
-                            " expected: "+COUNTER_LENGTH);
-       return count.bitReverse().toLong();
+        shiftData(true, false);
+        BitVector count = cc.getOutBits(DATA_CHAIN+"."+DATA_COUNTER_PATH);
+        int sz = count.getNumBits(); 
+        MarinaTest.fatal(sz!=COUNTER_LENGTH, "wrong number of counter bits: "+sz+
+                         " expected: "+COUNTER_LENGTH);
+        return count.bitReverse().toLong();
+    }
+    /** Fill the "North" Fifo ring */
+    public void fillNorthProperStopper() {
+        BitVector data = new BitVector(37, "empty");
+        BitVector addr = new BitVector(14, "empty");
+        for(int i=0; i<data.getNumBits(); i++) data.set(i, false);
+        for(int i=0; i<addr.getNumBits(); i++) addr.set(i, false);
+        fillNorthProperStopper(new MarinaPacket(data, false, addr));
     }
     /** Fill the "North" Fifo ring */
-    public void fillNorthProperStopper(BitVector data, boolean tokenhood, BitVector address) {
-        int len = 37+1+14;
-        BitVector bv = new BitVector(len, "empty");
-        for(int i=0; i<37; i++) bv.set(i, data.get(i));
-        bv.set(37, !tokenhood);
-        for(int i=38; i<38+14; i++) bv.set(i, address.get(i-38));
-        this.data.fill(bv);
+    public void fillNorthProperStopper(MarinaPacket mp) {
+        prln("inserting into north: " + mp);
+        this.data.fill(mp.toSingleBitVector());
     }
     /** Enable the transmission of instructions from the instruction
      * ring test structure to the EPI FIFO. */
     public void enableInstructionSend(boolean b) {
-       BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
-       bv.set(INSTRUCTION_SEND_NDX, b);
-       cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
-       shiftControl(false, true);
+        BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
+        bv.set(INSTRUCTION_SEND_NDX, b);
+        cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
+        shiftControl(false, true);
     } 
     /** Enable the recirculation of instructions within the South FIFO */
     public void enableInstructionRecirculate(boolean b) {
-       BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
-       bv.set(INSTRUCTION_RECIRCULATE_NDX, b);
-       cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
-       shiftControl(false, true);
+        BitVector bv = cc.getInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH);
+        bv.set(INSTRUCTION_RECIRCULATE_NDX, b);
+        cc.setInBits(CONTROL_CHAIN+"."+INSTR_RING_CONTROL_PATH, bv); 
+        shiftControl(false, true);
     }
     /** get the number of tokens in the token FIFO.
      * This includes the Token successor wire, the token FIFO wires,
      * and Token predecessor wire.
      * Master clear clears the token FIFO. */
     public int getNumTokens() {
-       shiftReport(true, false);
-       // get the token successor and token FIFO wires
-       BitVector bv = cc.getOutBits(REPORT_CHAIN+"."+TOK_FIFO_PATH);
-       int sz = bv.getNumBits();
-       MarinaTest.fatal(sz!=3, "wrong token FIFO size: "+sz+" expected: 3");
-       
-       // get the token predecessor wire
-       BitVector pred = cc.getOutBits(REPORT_CHAIN+"."+TOK_PRED_PATH);
-       sz = pred.getNumBits();
-       MarinaTest.fatal(sz!=1, "wrong token predecessor size: "+sz+" expected: 1");
-
-       // concatenate them
-       bv = bv.cat(pred);
-       sz = bv.getNumBits();
-       prln("Token state wires: "+bv.getState());
-       
-       int nbTok = 0;
-       for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
-       return nbTok;
+        shiftReport(true, false);
+        // get the token successor and token FIFO wires
+        BitVector bv = cc.getOutBits(REPORT_CHAIN+"."+TOK_FIFO_PATH);
+        int sz = bv.getNumBits();
+        MarinaTest.fatal(sz!=3, "wrong token FIFO size: "+sz+" expected: 3");
+        
+        // get the token predecessor wire
+        BitVector pred = cc.getOutBits(REPORT_CHAIN+"."+TOK_PRED_PATH);
+        sz = pred.getNumBits();
+        MarinaTest.fatal(sz!=1, "wrong token predecessor size: "+sz+" expected: 1");
+
+        // concatenate them
+        bv = bv.cat(pred);
+        sz = bv.getNumBits();
+        prln("Token state wires: "+bv.getState());
+        
+        int nbTok = 0;
+        for (int i=0; i<sz; i++) if (bv.get(i)) nbTok++;
+        return nbTok;
+    }
+    /** Configure the test probe so it measures the throughput of
+     * the north data FIFO. The test probe frequency is 8192 
+     * times slower than the FIFO throughput. This control has
+     * highest priority. */
+    public void probeDataCounter(Boolean b) {
+        data.setGeneralPurposeOutput(b);
     }
+    /** Configure the test probe so it measures the throughput of
+     * the alternating instruction FIFO. The test probe frequency is
+     * 1/16384 of the FIFO throughput. This control has second
+     * highest priority. Thus the following two calls probe the
+     * instruction counter: 
+     *      probeDataCounter(false);
+     *      probeInstructionCounter(true)
+     */
+    public void enableInstructionCounter(Boolean b) {
+        instrIn.setGeneralPurposeOutput(b);
+    }
+
+    public void fillSouthProperStopper(Instruction[] instructions) { fillSouthProperStopper(instructions, false); }
+    public void fillSouthProperStopper(Instruction[] instructions, boolean repeat) {
+        enableInstructionSend(false);
+        enableInstructionRecirculate(true);
+        for(Instruction i : instructions)
+            if (i!=null)
+                instrIn.fill(i);
+        enableInstructionRecirculate(repeat);
+        enableInstructionSend(true);
+        instrIn.run();
+    }
+
+    
 }