--- /dev/null
+package com.sun.vlsi.chips.marina.test;
+/* -*- tab-width: 4 -*- */
+import java.util.ArrayList;
+import java.util.List;
+
+import com.sun.async.test.BitVector;
+import com.sun.async.test.ChainControl;
+import com.sun.async.test.ChainG;
+import com.sun.async.test.ChainTest;
+import com.sun.async.test.ChipModel;
+import com.sun.async.test.HP34401A;
+import com.sun.async.test.Infrastructure;
+import com.sun.async.test.JtagSubchainTesterModel;
+import com.sun.async.test.JtagTester;
+import com.sun.async.test.ManualPowerChannel;
+import com.sun.async.test.NanosimModel;
+import com.sun.async.test.HsimModel;
+import com.sun.async.test.VerilogModel;
+import com.sun.async.test.Netscan4;
+import com.sun.async.test.PowerChannel;
+import com.sun.async.test.Pst3202Channel;
+import com.sun.async.test.SiliconChip;
+import com.sun.async.test.SimulationModel;
+import com.sun.async.test.VoltageReadable;
+import com.sun.vlsi.chips.marina.test.Marina.Ilc;
+import com.sun.vlsi.chips.marina.test.CmdArgs;
+import com.sun.vlsi.chips.marina.test.CmdArgs.Mode;
+
+import edu.berkeley.fleet.api.Dock;
+import edu.berkeley.fleet.api.Instruction;
+import edu.berkeley.fleet.api.Predicate;
+import edu.berkeley.fleet.api.Instruction.Set.SetDest;
+import edu.berkeley.fleet.api.Instruction.Set.SetSource;
+import edu.berkeley.fleet.marina.MarinaFleet;
+import edu.berkeley.fleet.marina.MarinaPath;
+
+/**
+ * Tests for Marina
+ */
+public class MarinaTest {
+ public static final MarinaFleet marinaFleet = new MarinaFleet();
+ public static final Dock dock = marinaFleet.getOnlyInputDock();
+
+ //-------------------------- constants -----------------------------------
+ private static final String SCAN_CHAIN_XML = "marina.xml";
+ private static final String NET_LIST = "marina.spi";
+
+ public static final int INSTR_SZ = 36;
+
+
+ public static final Instruction.Set.FlagFunction CLEAR_FLAG
+ = Instruction.Set.FlagFunction.ZERO;
+ public static final Instruction.Set.FlagFunction SET_FLAG
+ = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA)
+ .add(Predicate.NotFlagA);
+ public static final Instruction.Set.FlagFunction A_FLAG
+ = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA);
+
+ public static final Instruction.Set.FlagFunction B_FLAG
+ = Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagB);
+
+ // COLUMN_LATENCY is a delay that is larger than the latency through an Infinity column
+ private static final int COLUMN_LATENCY = 10; // nanoseconds
+
+
+ // Officially, this should be the number of requeueing no-ops that
+ // can be inserted into an idle dock whose OLC is nonzero.
+ //
+ // Less formally, this is roughly the number of stages of
+ // buffering between the instruction insertion point and the
+ // instruction ring, plus the capacity of the instruction ring.
+ private static final int INSTRUCTION_IN_SATURATION_AMOUNT = 19;
+
+ // This is some number which is significantly greater than
+ // INSTRUCTION_IN_SATURATION_AMOUNT. Increasing it may slow the tests down, but
+ // will never cause them to operate incorrectly.
+ private static final int MORE_THAN_INSTRUCTION_IN_SATURATION_AMOUNT = 25;
+
+ // This is the number of items which can be in the instruction
+ // fifo ring WITHOUT causing it to stop circulating.
+ private static final int INSTRUCTION_RING_CAPACITY = 13;
+
+ // Officially, this should be the number of data items which can
+ // be sent from the dock while the "data" proper stopper is in
+ // the "stopped" state
+ //
+ // Less formally, this is roughly the number of stages of
+ // buffering between the dock's data successor and the "data"
+ // proper stopper
+ /*
+ FIXME: what is the correct value here?
+ private static final int DATA_OUT_SATURATION_AMOUNT = XXX;
+ */
+
+ // This is some number which is greater than
+ // DATA_OUT_SATURATION_AMOUNT, but less than the capacity of the
+ // instruction fifo.
+ private static final int MORE_THAN_DATA_OUT_SATURATION_AMOUNT = 10;
+
+ // Nominal cycle time assuming 4 GHz throughput
+ public static double CYCLE_TIME_NS;
+
+ //-------------------------------- types ---------------------------------
+
+ //-------------------------- private data --------------------------------
+ private static long startTime;
+
+ public static Indenter indenter = new Indenter();
+ private Marina marina;
+ private ChipModel model;
+ //private ChainControl cc;
+ //private JtagTester tester;
+ private CmdArgs cmdArgs;
+ private PowerChannel corePowerSupply, padsPowerSupply;
+ private VoltageReadable coreVoltmeter, voltmeterForCurrent;
+
+ private ChainTest ctD, ctR, ctC, ct;
+ private ChainControl ccD, ccR, ccC, cc;
+
+ //-------------------------- private methods -----------------------------
+ /** @return true if simulation. Return false if we're testing silicon. */
+ private boolean sim() {return model instanceof SimulationModel;}
+
+ private void prln(String msg) {indenter.prln(msg);}
+ private void pr(String msg) {indenter.pr(msg);}
+ private void adjustIndent(int n) {indenter.adjustIndent(n);}
+
+ public static void fatal(boolean pred, String msg) { MarinaUtils.fatal(pred, msg); }
+
+ public static void fatalIfBitVectorsDoNotMatch(BitVector bv1, BitVector bv2) {
+ // FIXME: better error reporting needed here
+
+ fatal(bv1.getNumBits()!=bv2.getNumBits(), "lengths do not match");
+
+ boolean mismatch = false;
+ String err = "";
+ for(int i=0; i<bv1.getNumBits(); i++) {
+ if (bv1.get(i) != bv2.get(i)) {
+ mismatch = true;
+ err += ""+i+", ";
+ }
+ }
+ fatal(mismatch, "bit vectors do not match on bits " + err + "\n "+bv1+"\n "+bv2);
+ }
+
+ private static void printTestTime() {
+ long endTime = System.currentTimeMillis();
+ System.out.println("Test took: "+(endTime-startTime)/1000.0+" sec");
+ }
+
+ // Tell user what we're about to do
+ private static void reportTask(CmdArgs args) {
+ System.out.println("Begin testing Marina");
+ switch (args.mode) {
+ case WHOLE_CHIP_SCHEMATIC_PARASITICS:
+ System.out.println(" Simulate whole chip, schematic parasitics");
+ break;
+ case WHOLE_CHIP_LAYOUT_PARASITICS:
+ System.out.println(" Simulate whole chip, layout parasitics");
+ break;
+ case TEST_SILICON:
+ System.out.println(" Test silicon");
+ break;
+ default:
+ fatal(true, "unrecognized CmdArgs.Mode");
+ return;
+ }
+ }
+ private void setUpSuppliesAndMeters(Station station) {
+ // set up power supplies and meters
+ if (!sim()) {
+ prln("Testing station: "+station);
+ Infrastructure.gpibControllers = new int[] {0};
+ switch (cmdArgs.station) {
+ case ONE:
+ corePowerSupply = new Pst3202Channel("ch1", "HPST3202", 1);
+ padsPowerSupply = new Pst3202Channel("ch2", "HPST3202", 2);
+ break;
+ case TWO:
+ corePowerSupply = new Pst3202Channel("ch1", "HPST3202B", 1);
+ padsPowerSupply = new Pst3202Channel("ch2", "HPST3202B", 2);
+ break;
+ default:
+ fatal(true, "Unrecognized station: "+cmdArgs.station);
+ }
+ corePowerSupply.setCurrent((float)1.7);
+ corePowerSupply.setVoltageWait((float)1.0);
+
+ padsPowerSupply.setCurrent((float)0.100);
+ padsPowerSupply.setVoltageWait((float)1.8);
+
+ coreVoltmeter = new HP34401A(station.coreVoltmeter);
+ voltmeterForCurrent = new HP34401A(station.currentVoltmenter);
+ }
+ }
+
+ private MarinaTest(String[] args) {
+ cmdArgs = new CmdArgs(args);
+ reportTask(cmdArgs);
+ if (cmdArgs.mode==Mode.TEST_SILICON) doSilicon(); else doSim();
+ }
+
+ private void doSim() {
+ String netListName;
+ switch (cmdArgs.mode) {
+ case WHOLE_CHIP_SCHEMATIC_PARASITICS:
+ netListName = NET_LIST;
+ break;
+ case WHOLE_CHIP_LAYOUT_PARASITICS:
+ netListName = "marina_pads_guts.spi";
+ break;
+ default:
+ fatal(true, "unrecognized CmdArgs.Mode");
+ return;
+ }
+ model = cmdArgs.useVerilog
+ ? new VerilogModel()
+ : cmdArgs.useHsim
+ ? new HsimModel()
+ : new NanosimModel();
+
+ ((SimulationModel)model).setOptimizedDirectReadsWrites(true);
+
+ CYCLE_TIME_NS = cmdArgs.useVerilog ? (100*20) : 0.250;
+ int khz = model instanceof VerilogModel ? 100000 : cmdArgs.jtagShift ? 20000 : 1000000;
+
+ prln("constructing jtag controller");
+ JtagTester tester = ((SimulationModel)model).createJtagTester("TCK", "TMS", "TRSTb", "TDI", "TDO");
+ tester.printInfo = false;
+
+ ChainControls ccs = new ChainControls();
+ PowerChannel pc = new ManualPowerChannel("pc", false);
+ /*
+ JtagTester testerD, testerR, testerC;
+ testerD = ((SimulationModel)model).createJtagSubchainTester("sid[1:9]", null);
+ testerR = ((SimulationModel)model).createJtagSubchainTester("sir[1:9]", null);
+ testerC = ((SimulationModel)model).createJtagSubchainTester("sic[1:9]", null);
+ testerD.printInfo = testerR.printInfo = testerC.printInfo = false;
+
+ ccD = new ChainControl(SCAN_CHAIN_XML, testerD, 1.8f, khz);
+ ccR = new ChainControl(SCAN_CHAIN_XML, testerR, 1.8f, khz);
+ ccC = new ChainControl(SCAN_CHAIN_XML, testerC, 1.8f, khz);
+ ccD.noTestSeverity = ccR.noTestSeverity = ccC.noTestSeverity = Infrastructure.SEVERITY_NOMESSAGE;
+
+
+ ctD = new ChainTest(ccD, pc);
+ ctR = new ChainTest(ccR, pc);
+ ctC = new ChainTest(ccC, pc);
+ */
+ /*
+ ccs.addChain(Marina.DATA_CHAIN, ccD);
+ ccs.addChain(Marina.REPORT_CHAIN, ccR);
+ ccs.addChain(Marina.CONTROL_CHAIN, ccC);
+ */
+
+ cc = new ChainControl(SCAN_CHAIN_XML, tester, 1.8f, khz);
+ cc.noTestSeverity = Infrastructure.SEVERITY_NOMESSAGE;
+ ct = new ChainTest(cc, pc);
+ ccs.addChain(Marina.DATA_CHAIN, cc);
+ ccs.addChain(Marina.REPORT_CHAIN, cc);
+ ccs.addChain(Marina.CONTROL_CHAIN, cc);
+
+ marina = new Marina(ccs, model, !cmdArgs.jtagShift, indenter);
+
+ if (model instanceof VerilogModel)
+ ((SimulationModel)model).start("verilog", "marina.v", VerilogModel.DUMPVARS, !cmdArgs.jtagShift);
+ else if (model instanceof HsimModel)
+ ((SimulationModel)model).start("hsim64", netListName, 0, !cmdArgs.jtagShift);
+ else
+ ((SimulationModel)model).start("nanosim -c cfg", netListName, 0, !cmdArgs.jtagShift);
+
+ /*
+ ccC.resetInBits();
+ ccC.shift(Marina.CONTROL_CHAIN, false, true);
+ */
+
+ cc.resetInBits();
+ cc.shift(Marina.CONTROL_CHAIN, false, true);
+
+ doOneTest(cmdArgs.testNum);
+
+ ((SimulationModel)model).finish();
+ }
+ private void doSilicon() {
+ model = new SiliconChip();
+ String ip = cmdArgs.station.ipAddr;
+ JtagTester tester = new Netscan4(ip, cmdArgs.station.jtagChannel);
+ tester.printInfo = false;
+ int khz = 1000;
+ ChainControl cc = new ChainControl("???", tester, 1.8f, khz);
+ cc.noTestSeverity = Infrastructure.SEVERITY_NOMESSAGE;
+ ChainControls ccs = new ChainControls();
+ ccs.addChain(Marina.DATA_CHAIN, cc);
+ ccs.addChain(Marina.REPORT_CHAIN, cc);
+ ccs.addChain(Marina.CONTROL_CHAIN, cc);
+ marina = new Marina(ccs, model, false, indenter);
+ PowerChannel pc = new ManualPowerChannel("pc", false);
+ ChainTest ct = new ChainTest(cc, pc);
+ ct.testAllChains("marina", Infrastructure.SEVERITY_WARNING);
+ doOneTest(cmdArgs.testNum);
+ setUpSuppliesAndMeters(cmdArgs.station);
+ }
+
+ /** In the absence of looping, the longest path through Infinity is 4 column delays */
+ private void waitUntilQuiescent() {
+ model.waitNS(4*COLUMN_LATENCY);
+ }
+
+ private double readCurrent() {
+ return voltmeterForCurrent.readVoltage() / cmdArgs.station.ammeterShuntResistance;
+ }
+
+ /** Generate List of BitVectors where Token=true, high 25 data bits
+ * are alternating ones and zeros, low 12 data bits increment from
+ * zero, and address is given by addr. */
+ private List<BitVector> makeIncrDataConstAdr(int num, int addr) {
+ List<BitVector> ans = new ArrayList<BitVector>();
+ BitVector dHi = new BitVector(25, "dataHi");
+ BitVector dLo = new BitVector(12, "dataLo");
+ BitVector t = new BitVector("1", "token");
+ BitVector a = new BitVector(14, "addr");
+ dHi.setFromLong(0x00aaaaa);
+ a.setFromLong(addr);
+ for (int i=0; i<num; i++) {
+ dLo.setFromLong(i);
+ ans.add(dHi.cat(dLo).cat(t).cat(a));
+ dHi = dHi.not();
+ }
+ return ans;
+ }
+ private void stopToStop(ProperStopper s1, ProperStopper s2,
+ Counter ctr,
+ List<BitVector> din) {
+ prln("Begin stopToStop");
+ adjustIndent(2);
+
+ s1.stop();
+
+ long ctrStart = ctr==null ? 0 : ctr.getCount();
+
+ s1.fillMany(din);
+ waitUntilQuiescent();
+
+ List<BitVector> dout = s2.drainMany();
+
+ MarinaUtils.compareItemsOrdered(din, dout);
+
+ if (ctr!=null) {
+ long ctrEnd = ctr.getCount();
+ long delta = ctrEnd - ctrStart;
+ long expect = din.size();
+ fatal(delta!=expect,
+ "counter delta wrong: expected delta: "+expect+
+ " counter before:"+ctrStart+" counter after:"+ctrEnd);
+ }
+
+ adjustIndent(-2);
+ prln("End stopToStop");
+ }
+ /** Burst data from src to dst. gate is stopped while loading src. gate
+ * is then run to allow the burst to flow. */
+ private void stopToStopBurst(ProperStopper src, ProperStopper gate,
+ ProperStopper dst,
+ Counter ctr,
+ List<BitVector> din) {
+ prln("Begin stopToStopBurst test");
+ adjustIndent(2);
+
+ src.stop();
+ gate.stop();
+
+ long ctrStart = ctr==null ? 0 : ctr.getCount();
+
+ src.fillMany(din);
+ waitUntilQuiescent();
+
+ // open the gate to start the burst
+ gate.run();
+ waitUntilQuiescent();
+
+ List<BitVector> dout = dst.drainMany();
+
+ MarinaUtils.compareItemsOrdered(din, dout);
+
+ if (ctr!=null) {
+ long ctrEnd = ctr.getCount();
+ long delta = ctrEnd - ctrStart;
+
+ long expectA = din.size();
+ fatal(delta!=expectA,
+ "counter delta wrong: expected delta: "+expectA+
+ " counter before:"+ctrStart+" counter after:"+ctrEnd);
+ }
+
+ adjustIndent(-2);
+ prln("End stopToStopBurst test");
+ }
+
+ private void stopToStopOne(ProperStopper s1, ProperStopper s2,
+ Counter ctr, int adr) {
+ prln("Begin stopToStopOne");
+ adjustIndent(2);
+
+ List<BitVector> din = makeIncrDataConstAdr(1, adr);
+ stopToStop(s1, s2, ctr, din);
+
+ adjustIndent(-2);
+ prln("End stopToStopOne");
+ }
+
+ private void stopToStopThree(ProperStopper s1, ProperStopper s2,
+ Counter ctr, int adr) {
+ prln("Begin stopToStopOne");
+ adjustIndent(2);
+
+ List<BitVector> din = makeIncrDataConstAdr(3, adr);
+ stopToStop(s1, s2, ctr, din);
+
+ adjustIndent(-2);
+ prln("End stopToStopOne");
+ }
+
+ private int indexOf(BitVector o, List<BitVector> dIn) {
+ for (int i=0; i<dIn.size(); i++) {
+ if (o.equals(dIn.get(i))) return i;
+ }
+ return -1;
+ }
+ private String ringDump(List<BitVector> dIn, List<BitVector> dOut) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(" ring dump: ");
+ for (BitVector o : dOut) {
+ sb.append(indexOf(o, dIn)+" ");
+ }
+ return sb.toString();
+ }
+
+ private int[][] makeIntArray2D(int a, int b) {
+ int[][] ans = new int[a][];
+ for (int i=0; i<a; i++) ans[i] = new int[b];
+ return ans;
+ }
+
+ //=========================================================================
+ // Put top level tests here
+
+ private void testChains(Marina marina) {
+ if (ctC!=null) {
+ prln("Testing control chain...");
+ ctC.testOneChain(Marina.CONTROL_CHAIN, Infrastructure.SEVERITY_WARNING);
+ ccC.resetInBits();
+ ccC.shift(Marina.CONTROL_CHAIN, false, true);
+ }
+
+ if (ctD!=null) {
+ prln("Testing data chain...");
+ ctD.testOneChain(Marina.DATA_CHAIN, Infrastructure.SEVERITY_WARNING);
+ //ccD.resetInBits();
+ //ccD.shift(Marina.DATA_CHAIN, false, true);
+ }
+
+ if (ctR!=null) {
+ prln("Testing report chain...");
+ ctR.testOneChain(Marina.REPORT_CHAIN, Infrastructure.SEVERITY_WARNING);
+ //ccR.resetInBits();
+ //ccR.shift(Marina.REPORT_CHAIN, false, true);
+ }
+
+ if (ct!=null) {
+ prln("Testing control chain...");
+ ct.testOneChain(Marina.CONTROL_CHAIN, Infrastructure.SEVERITY_WARNING);
+ cc.resetInBits();
+ cc.shift(Marina.CONTROL_CHAIN, false, true);
+ prln("Testing data chain...");
+ ct.testOneChain(Marina.DATA_CHAIN, Infrastructure.SEVERITY_WARNING);
+ prln("Testing report chain...");
+ ct.testOneChain(Marina.REPORT_CHAIN, Infrastructure.SEVERITY_WARNING);
+ }
+ }
+
+ private void testProperStoppers(Marina marina) {
+ prln("Begin testProperStoppers");
+ adjustIndent(2);
+
+ for(ProperStopper ps : new ProperStopper[] { marina.data, marina.instrIn }) {
+
+ prln("testing " + (ps == marina.data ? "data" : "instruction") + " stopper");
+ adjustIndent(2);
+
+ prln("un-stopping stopper");
+ ps.run();
+ fatal( ps.getStopped(), "stopper should not have been stopped, but was");
+
+ prln("stopping stopper");
+ ps.stop();
+ fatal( !ps.getStopped(), "stopper should have been stopped, but was not");
+
+ adjustIndent(-2);
+ }
+
+ adjustIndent(-2);
+ }
+
+ private void sendInstructions(Marina marina) {
+ prln("Begin sendInstructions");
+ adjustIndent(2);
+
+ List<BitVector> din = new ArrayList<BitVector>();
+
+ BitVector count = new BitVector(MarinaPacket.WORD_WIDTH,"count");
+ BitVector one = new BitVector(MarinaPacket.WORD_WIDTH, "one");
+ count.setFromLong(0);
+ one.setFromLong(1);
+ for (int i=0; i<3; i++) {
+ din.add(count);
+ count = count.add(one);
+ }
+
+ for(BitVector d : din)
+ marina.instrIn.fill(new MarinaPacket(d, false, MarinaPacket.null_path));
+
+ adjustIndent(-2);
+ prln("End sendInstructions");
+ }
+
+ private void sendToken(Marina marina) {
+ prln("Begin sendToken");
+ adjustIndent(2);
+
+ //getCtrsFlags(marina);
+
+ int nbToks = marina.getNumTokens();
+ fatal(nbToks!=0, "Expected no tokens on initialization but got: "+nbToks+" tokens");
+
+ marina.instrIn.fill(setIlc(1));
+ marina.instrIn.fill(SEND_TOKEN);
+ nbToks = marina.getNumTokens();
+ fatal(nbToks!=1, "Expected one token to emerge but got: "+nbToks+" tokens");
+
+ adjustIndent(-2);
+ prln("End sendToken");
+ }
+
+ private void sendData(Marina marina) {
+ prln("Begin sendData");
+ adjustIndent(2);
+
+ edu.berkeley.fleet.api.BitVector bv = new edu.berkeley.fleet.api.BitVector(13);
+ for(int i=0; i<bv.length(); i+=2) bv.set(i, false);
+ MarinaPath path = new MarinaPath((MarinaFleet)dock.getShip().getFleet(), bv);
+
+ marina.instrIn.fill(setIlc(1));
+ marina.instrIn.fill(SEND_DATA);
+
+ List<BitVector> dataItems = marina.data.drainMany();
+ fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
+
+ MarinaPacket mp = new MarinaPacket(dataItems.get(0));
+ fatal(mp.tokenhood, "Expected tokenhood=data, but got tokenhood=token");
+
+ adjustIndent(-2);
+ prln("End sendData");
+ }
+
+ private void sendDataIlcInfinite(Marina marina) {
+ prln("Begin sendDataIlcInfinite");
+ adjustIndent(2);
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,SetSource.Infinity),
+ SEND_DATA,
+ });
+
+ // more than MAX_ILC
+ int howmany = 70;
+ List<BitVector> dataItems = marina.data.drainMany(howmany);
+ fatal(dataItems.size()!=howmany,
+ "Expected an unending supply of data items to emerge but only got got: "+dataItems.size());
+
+ adjustIndent(-2);
+ prln("End sendDataIlcInfinite");
+ }
+
+ private Instruction setOlc(int olc) {
+ return new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, olc);
+ }
+ private Instruction setOlcIfZero(int olc) {
+ return new Instruction.Set(dock,Predicate.Default,SetDest.OuterLoopCounter, olc);
+ }
+ private Instruction setIlc(int ilc) {
+ return new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, ilc);
+ }
+
+ private void testFlagD(Marina marina) {
+ prln("Begin testFlagD");
+ adjustIndent(2);
+
+ List<BitVector> toks;
+
+ Predicate only_if_olc_zero = Predicate.FlagD;
+ Predicate only_if_olc_nonzero = Predicate.Default;
+
+ marina.instrIn.fill(setIlc(1));
+
+ for(int olc : new int[] { 1, 0 }) {
+ for(boolean predicate_olc_nonzero : new boolean[] { true, false }) {
+ prln("Attempting send data item with "+
+ "olc=="+olc+" and "+
+ "predicate olc"+(predicate_olc_nonzero?"!=0":"==0"));
+ adjustIndent(2);
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ setOlc(olc),
+ new Instruction.Move(dock,
+ predicate_olc_nonzero // predicate
+ ? only_if_olc_nonzero
+ : only_if_olc_zero
+ ,
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ true, // dataOut
+ false // tokenOut
+ ),
+ });
+ expectNorthFifoExactly((predicate_olc_nonzero == (olc!=0)) ? 1 : 0);
+
+ for(int i=0; i<olc; i++)
+ marina.instrIn.fill(DEC);
+
+ adjustIndent(-2);
+ }
+ }
+ adjustIndent(-2);
+ prln("End testFlagD");
+ }
+
+ private void testPredicationOnAB(Marina marina) {
+ prln("Begin testPredicationOnAB");
+ adjustIndent(2);
+
+ List<BitVector> dItems;
+
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 1));
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, 1));
+
+ for(boolean flag_a : new boolean[] { false, true }) {
+ for(boolean flag_b : new boolean[] { false, true }) {
+ prln("Setting flags, a="+flag_a+" b="+flag_b);
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,
+ flag_a
+ ? Instruction.Set.FlagFunction.ONE
+ : Instruction.Set.FlagFunction.ZERO,
+ flag_b
+ ? Instruction.Set.FlagFunction.ONE
+ : Instruction.Set.FlagFunction.ZERO
+ ));
+ getCtrsFlags(marina);
+
+ adjustIndent(2);
+ for(Predicate predicate : new Predicate[] {
+ Predicate.Default,
+ Predicate.FlagA,
+ Predicate.FlagB,
+ Predicate.NotFlagA,
+ Predicate.NotFlagB,
+ }) {
+
+ prln("Attempting send data with a="+flag_a+", b="+flag_b+", predicate="+predicate);
+ adjustIndent(2);
+ marina.instrIn.fill(new Instruction.Move(dock,
+ predicate, // predicate
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ true, // dataOut
+ false // tokenOut
+ ));
+ adjustIndent(-2);
+ dItems = marina.data.drainMany();
+ int expected = predicate.evaluate(flag_a, flag_b, false, false) ? 1 : 0;
+ fatal(dItems.size()!=expected, "Expected "+expected+" data items to emerge but got: "+
+ dItems.size()+" items(s)");
+ }
+ adjustIndent(-2);
+ }
+ }
+ adjustIndent(-2);
+ prln("End testPredicationOnAB");
+ }
+
+
+ private void showOlc() {
+ prln("OLC=="+marina.getOLC());
+ }
+ private void expectOlc(int x) {
+ int olc = marina.getOLC();
+ fatal(x!=olc, "expected OLC=="+x+", but scanned out OLC=="+olc);
+ }
+
+ private void getCtrsFlags(Marina marina) {
+ prln("begin getCtrsFlags");
+ adjustIndent(2);
+
+ showOlc();
+ Ilc ilc = marina.getILC();
+ prln("ILC.done=="+ilc.getDone()+
+ " ILC.infinity=="+ilc.getInfinity()+
+ " ILC.count=="+ilc.getCount());
+ prln("flagA=="+marina.getFlagA());
+ prln("flagB=="+marina.getFlagB());
+ adjustIndent(-2);
+ prln("end getCtrsFlags");
+ }
+
+ private void walkOneOLC(Marina marina) {
+ prln("Begin walkOneOLC");
+ adjustIndent(2);
+ for (int i=0; i<6; i++) {
+
+ if (marina.kesselsCounter) {
+ System.out.println("master-clearing...");
+ // master clear on each iteration; otherwise we'd need to "run down" the olc
+ marina.masterClear();
+ marina.enableInstructionSend(true);
+ }
+
+ int inOlc = i==-1 ? 0 : (1<<i);
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, inOlc));
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+
+ expectOlc(inOlc);
+ prln("walkOneOLC: "+inOlc+" checks out");
+ }
+ adjustIndent(-2);
+ prln("End walkOneOLC");
+ }
+ private void walkOneILC(Marina marina) {
+ prln("Begin walkOneILC");
+ adjustIndent(2);
+ for (int i=0; i<6; i++) {
+ // Mask off the "zero" bit position
+ int inIlc = 1 << i;
+ prln("inIlc="+inIlc);
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, inIlc));
+ Ilc ilc = marina.getILC();
+ int outIlc = ilc.getCount();
+ fatal(outIlc!=inIlc, "bad ILC count: "+outIlc+" expected: "+inIlc);
+ fatal(ilc.getInfinity(), "bad Infinity bit: true");
+ }
+ prln("Now test the infinity bit");
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, SetSource.Infinity));
+ Ilc ilc = marina.getILC();
+ fatal(!ilc.getInfinity(), "bad Infinity bit: false");
+ adjustIndent(-2);
+ prln("End walkOneILC");
+ }
+ private void countIlc(Marina marina) {
+ final int maxIlc = 63;
+ prln("Begin countIlc");
+ adjustIndent(2);
+
+ marina.instrIn.fill(new
+ Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, maxIlc));
+
+ int ilc = marina.getILC().getCount();
+ fatal(ilc!=maxIlc, "bad ILC count: "+ilc+" expected: "+maxIlc);
+
+ prln("execute a move instruction that does nothing except decrement the ILC to zero");
+ marina.instrIn.fill(
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, // predicate
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ false, // dataOut
+ false // tokenOut
+ ));
+
+ // wait for ILC to count from 63 to 0
+ model.waitNS(128 * CYCLE_TIME_NS);
+ //model.waitNS(10000);
+
+ prln("Check that ILC==0");
+ ilc = marina.getILC().getCount();
+ fatal(ilc!=0, "bad ILC count: "+ilc+" expected: "+0);
+
+ adjustIndent(-2);
+ prln("End countIlc");
+ }
+ // Note: countOlc takes 44 minutes to run on nanosim
+ private void countOlc(Marina marina) {
+ int maxOlc = 63;
+ prln("Begin countOlc");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setOlc(maxOlc));
+
+ for (int i=maxOlc; i>=0; i--) {
+ model.waitNS(128 * CYCLE_TIME_NS);
+ prln("OLC should be: "+i);
+ expectOlc(i);
+ marina.instrIn.fill(new
+ Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, SetSource.Decrement));
+ }
+
+ adjustIndent(-2);
+ prln("End countOlc");
+ }
+ private void loadEveryValueOLC(Marina marina) {
+ adjustIndent(2);
+ for (int i=0; i<(1<<6); i++) {
+
+ if (marina.kesselsCounter) {
+ System.out.println("master-clearing...");
+ // master clear on each iteration; otherwise we'd need to "run down" the olc
+ marina.masterClear();
+ marina.enableInstructionSend(true);
+ }
+
+ int inOlc = i;
+ marina.fillSouthProperStopper(new Instruction[] {
+
+ // to ensure that instruction is bubble-limited
+ RECV_DATA,
+
+ // the Set-OLC instruction
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, inOlc),
+
+ // put a Set-ILC instruction right behind it with inverted bits to be sure we're
+ // not capturing the instruction-latch value too late in the cycle
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, (inOlc ^ (~(-1<<6)))),
+
+ });
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+ marina.fillNorthProperStopper();
+ model.waitNS(128 * CYCLE_TIME_NS);
+
+ expectOlc(inOlc);
+ prln("loadEveryValueOLC: "+inOlc+" checks out");
+ }
+ adjustIndent(-2);
+ }
+
+ private void saturateInstructionFifo(Marina marina, Instruction instruction, int quantity, boolean expect_it_to_jam_up) {
+ prln("Inserting "+quantity+" copies of \"" + instruction + "\"");
+ adjustIndent(2);
+ int i=0;
+ for(i=0; i<quantity; i++) {
+ prln("Inserting instruction " + (i+1) +"/"+ quantity);
+ marina.instrIn.fill(instruction);
+ boolean jammed = (marina.instrIn.getFillStateWire()==MarinaUtils.StateWireState.FULL);
+ if (jammed && expect_it_to_jam_up) {
+ prln("Stopper remained full after inserting instruction; this was expected; we are happy.");
+ adjustIndent(-2);
+ return;
+ }
+ fatal(jammed, "Instruction stopper did not drain after inserting " + (i+1) + " instructions; not good!");
+ }
+ fatal(expect_it_to_jam_up, "Expected instruction stopper to jam up, but it did not");
+ adjustIndent(-2);
+ prln("Successfully inserted " + i + " instructions");
+ }
+
+ private static MarinaPath null_path = new MarinaPath((MarinaFleet)dock.getShip().getFleet(),
+ MarinaUtils.sunToBerk(MarinaPacket.null_path));
+
+ private static final Instruction DEC =
+ new Instruction.Set(dock,Predicate.Default,SetDest.OuterLoopCounter, SetSource.Decrement);
+
+ private static final Instruction FLAG_NOP =
+ new Instruction.Set(dock, Predicate.IgnoreFlagD,
+ CLEAR_FLAG.add(Predicate.FlagA),
+ CLEAR_FLAG.add(Predicate.FlagB));
+
+ private static final Instruction NOP =
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ null, /* path */
+ false, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ false, /* dataOut */
+ false /* tokenOut */
+ );
+
+ private static final Instruction SEND_DATA =
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ null_path, /* path */
+ false, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ true, /* dataOut */
+ false /* tokenOut */
+ );
+
+ private static final Instruction SEND_DATA_IF_D_NOT_SET =
+ new Instruction.Move(dock,
+ Predicate.Default, /* predicate */
+ false, /* torpedoable */
+ null_path, /* path */
+ false, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ true, /* dataOut */
+ false /* tokenOut */
+ );
+
+ private static final Instruction SEND_DATA_IF_D_SET =
+ new Instruction.Move(dock,
+ Predicate.FlagD, /* predicate */
+ false, /* torpedoable */
+ null_path, /* path */
+ false, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ true, /* dataOut */
+ false /* tokenOut */
+ );
+
+ private static final Instruction TORPEDOABLE_RECV_DATA =
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ true, /* torpedoable */
+ null, /* path */
+ false, /* tokenIn */
+ true, /* dataIn */
+ true, /* latchData */
+ false, /* latchPath */
+ false, /* dataOut */
+ false /* tokenOut */
+ );
+
+ private static final Instruction RECV_DATA =
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ null, /* path */
+ false, /* tokenIn */
+ true, /* dataIn */
+ true, /* latchData */
+ false, /* latchPath */
+ false, /* dataOut */
+ false /* tokenOut */
+ );
+
+ private static final Instruction SEND_TOKEN =
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ null_path, /* path */
+ false, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ false, /* dataOut */
+ true /* tokenOut */
+ );
+
+ private static final Instruction RECV_TOKEN =
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ null, /* path */
+ true, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ false, /* dataOut */
+ false /* tokenOut */
+ );
+
+
+ private void expectNorthFifoNoMoreThan(int num) {
+ model.waitNS(128 * CYCLE_TIME_NS);
+ List<BitVector> dataItems = marina.data.drainMany(num+1);
+ fatal(dataItems.size()>num,
+ "Expected no more than "+num+
+ " data items to emerge but got at least: "+dataItems.size());
+ }
+ private void expectNorthFifoExactly(int num) {
+ model.waitNS(128 * CYCLE_TIME_NS);
+ List<BitVector> dataItems = marina.data.drainMany(num+1);
+ fatal(dataItems.size()!=num,
+ "Expected exactly "+num+
+ " data items to emerge but got at least: "+dataItems.size());
+ }
+ private void expectNorthFifoAtLeast(int num) {
+ model.waitNS(128 * CYCLE_TIME_NS);
+ List<BitVector> dataItems = marina.data.drainMany(num);
+ fatal(dataItems.size()<num,
+ "Expected at least "+num+
+ " data items to emerge but got only: "+dataItems.size());
+ }
+ private void expectTokensNoMoreThan(int num) {
+ int x = marina.getNumTokens();
+ List<BitVector> dataItems = marina.data.drainMany(num+1);
+ fatal(x>num,
+ "Expected no more than "+num+
+ " tokens to emerge but got at least: "+x);
+ }
+ private void expectTokensExactly(int num) {
+ int x = marina.getNumTokens();
+ fatal(x!=num,
+ "Expected exactly "+num+
+ " tokens but got at least: "+x);
+ }
+
+ private void testFlagDRecomputationTime(Marina marina) {
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ RECV_DATA,
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,0),
+ SEND_DATA_IF_D_NOT_SET
+ });
+ marina.fillNorthProperStopper();
+ expectNorthFifoNoMoreThan(0);
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ RECV_DATA,
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,1),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,SetSource.Decrement),
+ SEND_DATA_IF_D_NOT_SET
+ });
+ marina.fillNorthProperStopper();
+ expectNorthFifoNoMoreThan(0);
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ RECV_DATA,
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,2),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,SetSource.Decrement),
+ SEND_DATA_IF_D_NOT_SET
+ });
+ marina.fillNorthProperStopper();
+ expectNorthFifoExactly(1);
+ marina.instrIn.fill(DEC);
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ RECV_DATA,
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,0),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,1),
+ SEND_DATA_IF_D_NOT_SET
+ });
+ marina.fillNorthProperStopper();
+ expectNorthFifoExactly(1);
+ }
+
+ private void testTailWaitsForHead(Marina marina) {
+ marina.instrIn.fill(setIlc(1));
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63));
+
+ marina.enableInstructionSend(false);
+ marina.enableInstructionRecirculate(true);
+
+ marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
+ marina.instrIn.fill(new Instruction.Head(dock));
+ marina.instrIn.fill(SEND_DATA);
+ marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
+ marina.instrIn.fill(SEND_TOKEN);
+ marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
+ marina.instrIn.fill(new Instruction.Tail(dock));
+ marina.instrIn.fillTorpedo();
+
+ marina.enableInstructionRecirculate(false);
+ marina.enableInstructionSend(true);
+ marina.instrIn.run();
+
+ expectNorthFifoNoMoreThan(0);
+ prln("inserting into north proper stopper");
+ marina.fillNorthProperStopper();
+ expectNorthFifoExactly(1);
+ int nbToks = marina.getNumTokens();
+ fatal(nbToks!=1, "Expected one token to emerge but got: "+nbToks+" tokens");
+ }
+
+ /*
+ marina.instrIn.fill(setIlc(1));
+ marina.instrIn.fill(setOlc(1));
+
+ // this makes the head wait for the torpedo
+ marina.instrIn.fill(TORPEDOABLE_RECV_DATA);
+
+ // the head should wait for the tail
+ marina.instrIn.fill(new Instruction.Head(dock));
+ marina.instrIn.fill(NOP);
+ marina.instrIn.fill(SEND_DATA);
+ marina.instrIn.fill(RECV_DATA);
+
+ expectNorthFifoNoMoreThan(0);
+
+ marina.instrIn.fillTorpedo();
+ expectNorthFifoNoMoreThan(0);
+
+ marina.instrIn.fill(new Instruction.Tail(dock));
+ expectNorthFifoExactly(1);
+ */
+
+ private void testTailWithoutHead(Marina marina) {
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63),
+ new Instruction.Tail(dock),
+ SEND_DATA,
+ });
+ List<BitVector> dataItems = marina.data.drainMany(1);
+ fatal(dataItems.size()!=0, "Expected exactly no data items to emerge but got at least: "+dataItems.size());
+ }
+
+ private void testHeadWaitsForTail(Marina marina) {
+ List<BitVector> dataItems;
+
+ prln("Begin testHeadWaitsForTail");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63),
+ new Instruction.Head(dock),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
+ SEND_DATA,
+ });
+
+ expectNorthFifoExactly(0);
+ marina.instrIn.fill(new Instruction.Tail(dock));
+ expectNorthFifoAtLeast(1);
+
+ adjustIndent(-2);
+ prln("End testHeadWaitsForTail");
+ }
+
+ private void testNonTorpedoableMoveDoesNotResetDFlag(Marina marina) {
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,63),
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, // predicate
+ true, // torpedoable
+ null, // path
+ true, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ false, // dataOut
+ false // tokenOut
+ ),
+ new Instruction.Move(dock,
+ Predicate.FlagD, // predicate
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ true, // dataOut
+ false // tokenOut
+ ),
+ });
+ marina.instrIn.fillTorpedo();
+ expectNorthFifoExactly(1);
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Move(dock,
+ Predicate.Default, // predicate
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ true, // dataOut
+ false // tokenOut
+ ),
+ });
+ expectNorthFifoNoMoreThan(0);
+ }
+
+ private void testAbort(Marina marina) {
+
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.DataLatch,1),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,2),
+ SEND_DATA_IF_D_NOT_SET,
+ new Instruction.Head(dock),
+ SEND_DATA_IF_D_NOT_SET,
+ new Instruction.Set(dock,Predicate.Default,SetDest.DataLatch,2),
+ new Instruction.Abort(dock, Predicate.FlagD),
+ new Instruction.Set(dock,Predicate.Default,SetDest.OuterLoopCounter,SetSource.Decrement),
+ new Instruction.Tail(dock),
+ }, true);
+
+ for(int i=0; i<4; i++) {
+ BitVector bv;
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+ bv = new MarinaPacket(marina.data.drain()).data.bitReverse();
+ fatal(bv==null, "no data item found");
+ prln("got " + bv.toLong());
+ fatal(bv.toLong()!=1, "expected 1, got " + bv.toLong());
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+ bv = new MarinaPacket(marina.data.drain()).data.bitReverse();
+ fatal(bv==null, "no data item found");
+ prln("got " + bv.toLong());
+ fatal(bv.toLong()!=1, "expected 1, got " + bv.toLong());
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+ bv = new MarinaPacket(marina.data.drain()).data.bitReverse();
+ fatal(bv==null, "no data item found");
+ prln("got " + bv.toLong());
+ fatal(bv.toLong()!=2, "expected 2, got " + bv.toLong());
+
+ }
+ }
+
+ private void testAbortOutsideOfLoop(Marina marina) {
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ // ensure that an abort doesn't cause problems if no loop is in progress
+ new Instruction.Abort(dock, Predicate.IgnoreFlagD),
+ SEND_DATA,
+ });
+ expectNorthFifoExactly(1);
+ }
+
+ private void testFlagAB(Marina marina) {
+ prln("Begin testFlagAB");
+ adjustIndent(2);
+
+ Instruction.Set.FlagFunction zero = Instruction.Set.FlagFunction.ZERO;
+ Instruction.Set.FlagFunction one = zero;
+
+
+ // we should be able to use any pair of FlagX+NotFlagX,
+ // but we toss them all in to maximize the chances of the
+ // test passing (later we will try the individual
+ // combinations to maximize the chances of failure).
+ one = one.add(Predicate.FlagA);
+ one = one.add(Predicate.NotFlagA);
+ one = one.add(Predicate.FlagB);
+ one = one.add(Predicate.NotFlagB);
+ one = one.add(Predicate.FlagC);
+ one = one.add(Predicate.NotFlagC);
+
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1));
+ for(boolean fast : new boolean[] { true, false }) {
+ // clear the flags to a known state, then check both 0->1 and 1->0 transitions
+ for(boolean b : new boolean[] { false, true, false }) {
+ prln("state: a="+marina.getFlagA()+", b="+marina.getFlagB());
+ prln((b?"Setting":"Clearing")+" flags");
+
+ Instruction inst = new Instruction.Set(dock,Predicate.IgnoreFlagD,
+ b ? one : zero,
+ b ? one : zero
+ );
+ if (fast) {
+ marina.fillSouthProperStopper(new Instruction[] {
+ RECV_DATA,
+ inst,
+ NOP,
+ });
+ model.waitNS(64 * CYCLE_TIME_NS);
+ marina.fillNorthProperStopper();
+ } else {
+ marina.instrIn.fill(inst);
+ }
+
+ fatal(marina.getFlagA()!=b,
+ "after "+(b?"setting":"clearing")+" FlagA, it was still "+(b?"clear":"set"));
+ fatal(marina.getFlagB()!=b,
+ "after "+(b?"setting":"clearing")+" FlagB, it was still "+(b?"clear":"set"));
+ }
+ }
+
+ adjustIndent(-2);
+ prln("End testFlagAB");
+ }
+
+ /**
+ * WARNING: this is a very, very, very long test case -- it goes
+ * through 216 iterations.
+ */
+ private void testFlagTruthTable(Marina marina) {
+ prln("Begin testFlagTruthTable");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+ Instruction.Set.FlagFunction zero = Instruction.Set.FlagFunction.ZERO;
+ Instruction.Set.FlagFunction one = zero.add(Predicate.FlagA).add(Predicate.NotFlagA);
+
+ for(Predicate a_input : new Predicate[] { null, Predicate.FlagA, Predicate.NotFlagA })
+ for(Predicate b_input : new Predicate[] { null, Predicate.FlagB, Predicate.NotFlagB })
+ for(Predicate c_input : new Predicate[] { null, Predicate.FlagC, Predicate.NotFlagC })
+ for(boolean a_state : new boolean[] { false, true })
+ for(boolean b_state : new boolean[] { false, true })
+ for(boolean c_state : new boolean[] { false, true }) {
+ for(boolean which : new boolean[] { false, true }) {
+
+ prln("before instruction: a="+a_state+", b="+b_state+", c="+c_state);
+ // set A,B flags to a_state and b_state
+ marina.instrIn.fill(new
+ Instruction.Set(dock,Predicate.IgnoreFlagD,
+ a_state ? one : zero,
+ b_state ? one : zero
+ ));
+
+ // set C flag to c_state
+ 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);
+ addr.set(Marina.INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE, c_state);
+ marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
+ marina.instrIn.fill(RECV_DATA);
+
+ Instruction.Set.FlagFunction func = zero;
+ if (a_input!=null) func = func.add(a_input);
+ if (b_input!=null) func = func.add(b_input);
+ if (c_input!=null) func = func.add(c_input);
+
+ Instruction inst = new
+ Instruction.Set(dock,Predicate.IgnoreFlagD,
+ !which ? func : zero.add(Predicate.FlagA),
+ which ? func : zero.add(Predicate.FlagB)
+ );
+
+ marina.instrIn.fill(inst);
+
+ boolean expected_a = !which ? func.evaluate(a_state, b_state, c_state, false) : a_state;
+ boolean expected_b = which ? func.evaluate(a_state, b_state, c_state, false) : b_state;
+ fatal(expected_a != marina.getFlagA(),
+ "expected A="+expected_a+", but got "+marina.getFlagA());
+ fatal(expected_b != marina.getFlagB(),
+ "expected B="+expected_b+", but got "+marina.getFlagB());
+ }
+ }
+ adjustIndent(-2);
+ prln("End testFlagTruthTable");
+ }
+
+ private void recvData(Marina marina) {
+ prln("Begin recvData");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG),
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, // predicate
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ true, // dataIn
+ false, // latchData
+ false, // latchPath
+ false, // dataOut
+ false // tokenOut
+ ),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD, SET_FLAG, SET_FLAG),
+ });
+ model.waitNS(64 * CYCLE_TIME_NS);
+
+ prln("checking to confirm that A flag is cleared");
+ fatal(marina.getFlagA(), "bad A flag: "+marina.getFlagA());
+
+ prln("inserting data item in north fifo ring");
+ 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);
+ marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
+ model.waitNS(64 * CYCLE_TIME_NS);
+
+ prln("checking to see if A flag got set");
+ fatal(!marina.getFlagA(), "bad A flag: "+marina.getFlagA());
+
+ adjustIndent(-2);
+ prln("End recvData");
+ }
+
+
+ private void testRecvAndSendWalkingOne(Marina marina) {
+ prln("Begin testRecvAndSendWalkingOne");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+
+ List<BitVector> dataItems;
+ for(int bit=0; bit<37; bit++) {
+
+ 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);
+ data.set(bit, true);
+ prln("testing with bit pattern " + data);
+
+ prln("inserting data item into north fifo ring");
+ marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
+
+ prln("stopping the north proper stopper");
+ marina.data.stop();
+
+ dataItems = marina.data.drainMany(1);
+ fatal(dataItems.size()!=0,
+ "found a data item waiting in the north proper stopper, but should not have");
+
+ marina.instrIn.fill(new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, // predicate
+ false, // torpedoable
+ null_path, // path
+ false, // tokenIn
+ true, // dataIn
+ true, // latchData
+ false, // latchPath
+ true, // dataOut
+ false // tokenOut
+ ));
+
+ dataItems = marina.data.drainMany(2);
+ fatal(dataItems.size()!=1,
+ "found "+dataItems.size()+" data items in north fifo; expected one");
+ MarinaPacket mp = new MarinaPacket(dataItems.get(0));
+ fatalIfBitVectorsDoNotMatch(mp.data, data);
+ }
+
+ adjustIndent(-2);
+ prln("End testRecvAndSendWalkingOne");
+ }
+
+
+
+ private void setOlcFromDataLatch(Marina marina) {
+ prln("Begin setOlcFromDataLatch");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+
+ // walk a bit from 0 to 5
+ for(int bit=0; bit<6; bit++) {
+ prln("inserting data item in north fifo ring");
+ 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);
+ data.set(bit, true);
+ marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ RECV_DATA,
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,SetSource.DataLatch),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.DataLatch,-1),
+ });
+
+ model.waitNS(CYCLE_TIME_NS * 64);
+
+ expectOlc(1<<bit);
+
+ if (marina.kesselsCounter) {
+ // master clear on each iteration; otherwise we'd need to "run down" the olc
+ marina.masterClear();
+ marina.enableInstructionSend(true);
+ }
+ }
+
+ adjustIndent(-2);
+ prln("End setOlcFromDataLatch");
+ }
+
+ private void setIlcFromDataLatch(Marina marina) {
+ prln("Begin setIlcFromDataLatch");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+
+ // walk a bit from 0 to 5
+ for(int bit=5; bit>=0; bit--) {
+ prln("inserting data item in north fifo ring");
+ 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);
+ data.set(bit, true);
+ marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
+ RECV_DATA,
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,SetSource.DataLatch),
+ });
+ model.waitNS(CYCLE_TIME_NS * 64);
+
+ int ilc = marina.getILC().getCount();
+ fatal(ilc != (1<<bit), "expected ilc to be " + (1<<bit) + ", but got " + ilc);
+ }
+
+ adjustIndent(-2);
+ prln("End setIlcFromDataLatch");
+ }
+
+ private void testSendAndRecvToken(Marina marina) {
+ prln("Begin testSendAndRecvToken");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+ marina.fillSouthProperStopper(new Instruction[] {
+ SEND_TOKEN,
+ RECV_TOKEN,
+ SEND_DATA,
+ });
+ expectNorthFifoExactly(1);
+
+ adjustIndent(-2);
+ prln("End testSendAndRecvToken");
+ }
+
+ private void testSignExtendedLiteral(Marina marina) {
+ prln("Begin testSignExtendedLiteral");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+ for(long val : new long[] { (-1L << 14), -1, 0, 1 }) {
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,
+ Instruction.Set.SetDest.DataLatch,
+ val),
+ SEND_DATA,
+ });
+ model.waitNS(CYCLE_TIME_NS * 64);
+
+ List<BitVector> dataItems = marina.data.drainMany(3);
+ fatal(dataItems.size()!=1, "expected exactly one data item, got " + dataItems.size());
+
+ MarinaPacket mp = new MarinaPacket(dataItems.get(0));
+ BitVector bv = mp.data;
+ prln("got back " + mp);
+
+ boolean mismatch = false;
+ String err = "";
+ for(int i=0; i<37; i++) {
+ if (bv.get(i) != ( (val & (1L << i)) != 0 )) {
+ mismatch = true;
+ err += ""+i+", ";
+ }
+ }
+ fatal(mismatch, "data read back did not match inserted literal; mismatch on bits " + err);
+ }
+
+ adjustIndent(-2);
+ prln("End testSignExtendedLiteral");
+ }
+
+ private void testShiftedLiteral(Marina marina) {
+ prln("Begin testShiftedLiteral");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,
+ Instruction.Set.SetDest.DataLatch,
+ 0));
+
+ BitVector dreg = new BitVector(37, "what we think is in the d-register");
+ for(int i=0; i<37; i++) dreg.set(i, false);
+
+ for(long val : new long[] { -1, 0, 1, (-1L << 18) }) {
+
+ edu.berkeley.fleet.api.BitVector immediate =
+ new edu.berkeley.fleet.api.BitVector(19);
+ for(int i=0; i<immediate.length(); i++)
+ immediate.set(i, (val & (1L << i)) != 0);
+
+ // shift over 19 LSB's towards MSB
+ for(int i=0; i<19; i++)
+ if (i+19 <= 36) dreg.set(i+19, dreg.get(i));
+ for(int i=0; i<19; i++)
+ dreg.set(i, immediate.get(i));
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Shift(dock,Predicate.IgnoreFlagD,immediate),
+ SEND_DATA,
+ });
+
+ model.waitNS(CYCLE_TIME_NS * 64);
+ List<BitVector> dataItems = marina.data.drainMany(3);
+ fatal(dataItems.size()!=1, "expected exactly one data item, got " + dataItems.size());
+
+ BitVector bv = new MarinaPacket(dataItems.get(0)).data;
+ fatal(!bv.equals(dreg), "data read back did not match inserted literal.\n" +
+ "got: "+bv.bitReverse().getState()+"\n"+
+ "expected:"+dreg.bitReverse().getState());
+ }
+
+ adjustIndent(-2);
+ prln("End testShiftedLiteral");
+ }
+
+ private void testFlagC(Marina marina) {
+ prln("Begin testFlagC");
+ adjustIndent(2);
+
+ // Russell says:
+ // addr[14] == sigS
+ // addr[1] == sigA
+ //
+ // Adam says:
+ // Dc=1 => sigS is copied into C-flag
+ // Dc=0 => sigA is copied into C-flag
+
+ marina.instrIn.fill(setIlc(1));
+ for(boolean dc : new boolean[] { false, true }) {
+ for(boolean c_flag : new boolean[] { true, false, true }) {
+
+ prln("");
+ prln("****** checking case where dc="+dc+", cflag="+c_flag);
+ 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);
+
+ int whichbit = dc
+ ? Marina.INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ONE
+ : Marina.INDEX_OF_ADDRESS_BIT_COPIED_TO_C_FLAG_WHEN_DC_EQUALS_ZERO;
+ prln("setting addr["+whichbit+"] to "+(c_flag?"1":"0"));
+ addr.set(whichbit, c_flag);
+
+ prln("... and filling north fifo proper stopper");
+ marina.fillNorthProperStopper(new MarinaPacket(data, false, addr));
+
+ prln("clearing flags");
+ prln("executing recv data with Dc="+dc);
+ prln("copying c-flag to a-flag");
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG),
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ true, /* torpedoable */
+ null, /* path */
+ false, /* tokenIn */
+ true, /* dataIn */
+ dc, /* latchData */
+ false, /* latchPath */
+ false, /* dataOut */
+ false /* tokenOut */
+ ),
+ FLAG_NOP,
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,
+ Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagC),
+ CLEAR_FLAG
+ ),
+ });
+
+ model.waitNS(CYCLE_TIME_NS * 64);
+
+ prln("checking to confirm that A flag is " + c_flag);
+ fatal(marina.getFlagA()!=c_flag, "bad A flag: "+marina.getFlagA());
+ }
+ }
+ adjustIndent(-2);
+ prln("End testFlagC");
+ }
+
+ private void sendDataWithPath(Marina marina) {
+ prln("Begin sendDataWithPath");
+ adjustIndent(2);
+
+ edu.berkeley.fleet.api.BitVector bv = new edu.berkeley.fleet.api.BitVector(13);
+ marina.instrIn.fill(setIlc(1));
+
+ // alternating ones and zeroes
+ for(int i=0; i<bv.length(); i+=2)
+ bv.set(i, true);
+ // and then ones in the lower four bits so it's not symmetric
+ for(int i=0; i<4; i++)
+ bv.set(i, true);
+
+ MarinaPath path = new MarinaPath((MarinaFleet)dock.getShip().getFleet(), bv);
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ path, /* path */
+ false, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ true, /* dataOut */
+ false /* tokenOut */
+ ),
+ });
+
+ List<BitVector> dataItems;
+ MarinaPacket mp;
+
+ dataItems = marina.data.drainMany();
+ fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
+ mp = new MarinaPacket(dataItems.get(0));
+
+ // the 14th bit of the outbound address cannot be set by the
+ // ship, so we don't care about it
+ fatalIfBitVectorsDoNotMatch(MarinaUtils.berkToSun(bv), mp.path.get(0,13));
+
+ prln("send data with no change to path");
+ marina.instrIn.fill(new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ null, /* path */
+ false, /* tokenIn */
+ false, /* dataIn */
+ false, /* latchData */
+ false, /* latchPath */
+ true, /* dataOut */
+ false /* tokenOut */
+ ));
+
+ dataItems = marina.data.drainMany();
+ fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
+ mp = new MarinaPacket(dataItems.get(0));
+
+ // the 14th bit of the outbound address cannot be set by the
+ // ship, so we don't care about it
+ fatalIfBitVectorsDoNotMatch(MarinaUtils.berkToSun(bv), mp.path.get(0,13));
+
+ adjustIndent(-2);
+ prln("End sendDataWithPath");
+ }
+
+ private void recvPath(Marina marina) {
+ prln("Begin recvPath");
+ adjustIndent(2);
+
+ marina.instrIn.fill(setIlc(1));
+ for(int bit=0; bit<11; bit++) {
+ BitVector packet_data = new BitVector(37, "inbound data item");
+ for(int i=0; i<37; i++) packet_data.set(i, false);
+ packet_data.set(27+bit, true);
+ BitVector packet_path = new BitVector(14, "inbound data item");
+ for(int i=0; i<14; i++) packet_path.set(i, false);
+
+ marina.fillNorthProperStopper(new MarinaPacket(packet_data, false, packet_path));
+
+ prln("recv path, send data (using recv'd path)");
+ marina.instrIn.fill(new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, /* predicate */
+ false, /* torpedoable */
+ null, /* path */
+ false, /* tokenIn */
+ true, /* dataIn */
+ true, /* latchData */
+ true, /* latchPath */
+ true, /* dataOut */
+ false /* tokenOut */
+ ));
+
+ List<BitVector> dataItems = marina.data.drainMany();
+ fatal(dataItems.size()!=1, "Expected one data item to emerge but got: "+dataItems.size()+" data items");
+ MarinaPacket mp = new MarinaPacket(dataItems.get(0));
+
+ fatalIfBitVectorsDoNotMatch(packet_data.get(25,11), mp.path.get(0,11));
+ fatalIfBitVectorsDoNotMatch(packet_data, mp.data);
+ }
+
+ adjustIndent(-2);
+ prln("End recvPath");
+ }
+
+ private void testILC(Marina marina) {
+ prln("Begin testILC");
+ adjustIndent(2);
+
+ for(int bit=0; bit<6; bit++) {
+ int ilc = bit<0 ? 0 : (1<<bit);
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,ilc),
+ SEND_DATA,
+ });
+ List<BitVector> dataItems = marina.data.drainMany();
+ fatal(dataItems.size()!=ilc, "Expected "+ilc+" data item(s) to emerge but got: "+dataItems.size()+" data items");
+ }
+
+ adjustIndent(-2);
+ prln("End testILC");
+ }
+
+ private void testILCZero(Marina marina) {
+ adjustIndent(2);
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,0),
+ SEND_DATA,
+ SEND_TOKEN,
+ });
+ expectNorthFifoNoMoreThan(0);
+ expectTokensExactly(1);
+ adjustIndent(-2);
+ }
+
+ private void sendTorpedo(Marina marina) {
+ prln("Begin sendTorpedo");
+ adjustIndent(2);
+ marina.instrIn.fill(setIlc(1));
+ marina.instrIn.fill(setOlc(63));
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+ expectOlc(63);
+
+ marina.instrIn.fill(new
+ Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG));
+ fatal(marina.getFlagA(), "bad A flag: true");
+ fatal(marina.getFlagB(), "bad B flag: true");
+
+ prln("execute a move instruction that does nothing but loops until torpedo arrives");
+ prln("A=1, B=B This instruction should not execute because D-flag is set");
+ prln("Set A=A, B=1 This instruction should execute because D-flag is set");
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, SetSource.Infinity),
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, // predicate
+ true, // torpedoable
+ null, // path
+ false, // tokenIn
+ true, // dataIn
+ false, // latchData
+ false, // latchPath
+ false, // dataOut
+ false // tokenOut
+ ),
+ new Instruction.Set(dock,Predicate.Default,
+ SET_FLAG,
+ Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagB)
+ ),
+ new Instruction.Set(dock, Predicate.FlagD,
+ Instruction.Set.FlagFunction.ZERO.add(Predicate.FlagA),
+ SET_FLAG
+ ),
+ });
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+
+ prln("send torpedo. This should clear the OLC");
+ marina.instrIn.fillTorpedo();
+ model.waitNS(128 * CYCLE_TIME_NS);
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+
+ prln("A should remain false, B should be true");
+ fatal(marina.getFlagA(), "bad A flag: true");
+ fatal(!marina.getFlagB(), "bad B flag: false");
+
+ model.waitNS(128 * CYCLE_TIME_NS);
+
+ prln("Reload OLC after torpedo, clears D-flag");
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 63));
+
+ // FIXME: find another way to test this
+ model.waitNS(128 * CYCLE_TIME_NS);
+ expectOlc(63);
+
+ prln("Set A=1, B=1 This instruction should execute because OLC!=0");
+ marina.instrIn.fill(new
+ Instruction.Set(dock,Predicate.Default, SET_FLAG, SET_FLAG));
+
+ prln("A and B should be true");
+ fatal(!marina.getFlagA(), "bad A flag: false");
+ fatal(!marina.getFlagB(), "bad B flag: false");
+
+ adjustIndent(-2);
+ prln("End sendTorpedo");
+ }
+
+ private void testTorpedoOnAnInfinite(Marina marina) {
+ prln("Begin testTorpedoOnAnInfinite");
+ adjustIndent(2);
+
+ List<BitVector> dataItems;
+
+ marina.instrIn.fill(setIlc(1));
+ for(boolean torpedoable : new boolean[] { true, false }) {
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, // predicate
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ false, // dataOut
+ true // tokenOut
+ ),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,SetSource.Infinity),
+ new Instruction.Move(dock,
+ Predicate.IgnoreFlagD, // predicate
+ torpedoable, // torpedoable
+ null, // path
+ true, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ false, // dataOut
+ true // tokenOut
+ ),
+ // FIXME: this probably should be removed, unless Ivan doesn't want to change the behavior
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
+
+ SEND_DATA,
+ });
+
+ // expect nothing to come out, because the NOP is executing
+ dataItems = marina.data.drainMany(2);
+ fatal(dataItems.size()!=0, "Expected no data item(s) to emerge but got at least: "+dataItems.size()+" data items");
+
+ marina.instrIn.fillTorpedo();
+
+ int expected = torpedoable?1:0;
+ dataItems = marina.data.drainMany(2);
+ fatal(dataItems.size()!=expected, "Expected "+expected+" item to emerge but got: "+dataItems.size()+" data items");
+
+ fatal(!marina.getILC().getDone(), "Expected ilc=done, but got "+marina.getILC());
+ }
+
+ adjustIndent(-2);
+ prln("End testTorpedoOnAnInfinite");
+ }
+
+ private void testDFlagWhenTorpedoLyingInWait(Marina marina) {
+ marina.fillSouthProperStopper(new Instruction[] {
+ RECV_DATA,
+ TORPEDOABLE_RECV_DATA,
+ marina.kesselsCounter ? null : FLAG_NOP,
+ SEND_DATA_IF_D_SET,
+ });
+ marina.instrIn.fillTorpedo();
+ model.waitNS(64 * CYCLE_TIME_NS);
+ marina.fillNorthProperStopper();
+ model.waitNS(64 * CYCLE_TIME_NS);
+ expectNorthFifoExactly(1);
+ }
+
+ private void testSetOlcFollowedByDPredicated(Marina marina) {
+ for(boolean d_set : new boolean[] { false, true }) {
+ prln("");
+ marina.fillSouthProperStopper(new Instruction[] {
+ setOlc(0),
+ marina.kesselsCounter ? null : FLAG_NOP,
+ d_set ? SEND_DATA_IF_D_SET : SEND_DATA_IF_D_NOT_SET,
+ });
+ expectNorthFifoExactly(d_set ? 1 : 0);
+
+ prln("");
+ marina.fillSouthProperStopper(new Instruction[] {
+ setOlc(32),
+ marina.kesselsCounter ? null : FLAG_NOP,
+ d_set ? SEND_DATA_IF_D_SET : SEND_DATA_IF_D_NOT_SET,
+ });
+ expectNorthFifoExactly(d_set ? 0 : 1);
+
+ if (marina.kesselsCounter) {
+ marina.masterClear();
+ marina.enableInstructionSend(true);
+ }
+ }
+ }
+
+ private void testOlcDecrementAtHighSpeed(Marina marina) {
+ prln("Begin testOlcDecrementAtHighSpeed");
+ adjustIndent(2);
+
+ List<BitVector> dataItems;
+
+ // Each element of the following pair of arrays is one "test".
+ // The OLC will be loaded with olcs[i] and then decremented
+ // decr_amounts[i] times; after that has happened the zeroness
+ // of the OLC will be checked by executing a MOVE with
+ // [olc!=0] as the predicate.
+
+ int[] olcs = new int[] { 3, 3, 3, 10, 41 };
+ int[] decr_amounts = new int[] { 2, 3, 4, 9, 9 };
+
+ for(int which=0; which<olcs.length; which++) {
+ int olc = olcs[which];
+ int decr_amount = decr_amounts[which];
+
+ prln("inserting set olc="+olc);
+ prln("inserting set ilc=1");
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter,1),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter,olc),
+ });
+
+ // commenting the following four lines causes this test to pass
+
+ prln("inserting: "+decr_amount+" olc-- instructions");
+ prln("inserting: [!d] send data");
+ Instruction[] instructions = new Instruction[decr_amount+1];
+ for(int i=0; i<decr_amount; i++)
+ instructions[i] =
+ new Instruction.Set(dock,
+ Predicate.Default,
+ SetDest.OuterLoopCounter,
+ SetSource.Decrement);
+ instructions[instructions.length-1] =
+ new Instruction.Move(dock,
+ Predicate.Default, // predicate
+ false, // torpedoable
+ null, // path
+ false, // tokenIn
+ false, // dataIn
+ false, // latchData
+ false, // latchPath
+ true, // dataOut
+ false // tokenOut
+ );
+
+ marina.fillSouthProperStopper(instructions);
+ model.waitNS(64 * CYCLE_TIME_NS);
+
+ int expected = decr_amount>=olc ? 0 : 1;
+ dataItems = marina.data.drainMany(2);
+ fatal(dataItems.size()!=expected, "Expected "+expected+" item to emerge but got: "+dataItems.size()+" data items");
+
+ if (marina.kesselsCounter) {
+ // master clear on each iteration; otherwise we'd need to "run down" the olc
+ marina.masterClear();
+ marina.enableInstructionSend(true);
+ }
+ }
+
+ adjustIndent(-2);
+ prln("End testOlcDecrementAtHighSpeed");
+ }
+
+ private void flipIlcBit(Marina marina) {
+ prln("Begin flipIlcBit");
+ adjustIndent(2);
+ prln("Using the set ILC instruction, toggle a single bit between zero and one. \n" +
+ "Check correct setting of the ILC zero bit");
+
+ for (int i=0; i<6; i++) {
+ int notZero = 1<<i;
+
+ prln("Then immediately set ILC="+notZero);
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, 0),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, notZero),
+ });
+
+ model.waitNS(64 * CYCLE_TIME_NS);
+
+ prln("Verify ILC using scan chain");
+ Ilc ilc = marina.getILC();
+ int ilcCount = ilc.getCount();
+ fatal(ilcCount!=notZero, "bad ILC count: "+ilcCount+" expected: "+notZero);
+ fatal(ilc.getInfinity(), "bad ILC Infinity bit: true");
+
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, notZero),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.InnerLoopCounter, 0),
+ });
+
+ model.waitNS(64 * CYCLE_TIME_NS);
+
+ prln("Verify ILC using scan chain");
+ ilc = marina.getILC();
+ ilcCount = ilc.getCount();
+ fatal(ilcCount!=0, "bad ILC count: "+ilcCount+" expected: 0");
+ fatal(ilc.getInfinity(), "bad ILC Infinity bit: true");
+ }
+
+ adjustIndent(-2);
+ prln("End flipIlcBit");
+ }
+ private void flipOlcBit(Marina marina) {
+ prln("Begin flipOlcBit");
+ adjustIndent(2);
+ prln("Using the set OLC instruction, toggle a single bit between zero and one. \n" +
+ "Check correct setting of the OLC zero bit");
+
+ marina.instrIn.fill(new Instruction.Set(dock,Predicate.IgnoreFlagD, CLEAR_FLAG, CLEAR_FLAG));
+
+ for (int i=0; i<6; i++) {
+ int notZero = 32 >> i;
+
+ if (marina.kesselsCounter) {
+ // master clear on each iteration; otherwise we'd need to "run down" the olc
+ marina.masterClear();
+ marina.enableInstructionSend(true);
+ }
+
+ int outOlc;
+ prln("Set OLC=0");
+ prln("Then immediately set OLC="+notZero);
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 0),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, notZero),
+ });
+
+ model.waitNS(64 * CYCLE_TIME_NS);
+ prln("Verify OLC count using scan chain");
+ expectOlc(notZero);
+
+ if (!marina.kesselsCounter) {
+ prln("Set OLC="+notZero);
+ prln("Then immediately set OLC=0");
+ marina.fillSouthProperStopper(new Instruction[] {
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, notZero),
+ new Instruction.Set(dock,Predicate.IgnoreFlagD,SetDest.OuterLoopCounter, 0),
+ });
+
+ model.waitNS(64 * CYCLE_TIME_NS);
+ prln("Verify OLC count using scan chain");
+ expectOlc(0);
+ }
+ }
+
+ adjustIndent(-2);
+ prln("End flipOlcBit");
+ }
+ private void testSouthRecirculate(Marina marina, int AMOUNT) {
+ prln("Begin testSouthRecirculate("+AMOUNT+")");
+ adjustIndent(2);
+
+ marina.enableInstructionSend(false);
+ marina.enableInstructionRecirculate(true);
+
+ prln("Completely fill south ring");
+ adjustIndent(2);
+ for (int i=0; i<AMOUNT; i++) {
+ prln("inserting item " + (i+1) + " / " + AMOUNT);
+ BitVector path = new BitVector(MarinaPacket.PATH_WIDTH, "path");
+ BitVector data = new BitVector(MarinaPacket.WORD_WIDTH, "path");
+ path.set(0, MarinaPacket.PATH_WIDTH, false);
+ data.setFromLong(i+9);
+ marina.instrIn.fill(new MarinaPacket(data, false, path));
+ }
+ adjustIndent(-2);
+
+ prln("Drain south ring and check contents");
+ adjustIndent(2);
+ List<BitVector> out = marina.instrIn.drainMany();
+ boolean bad = false;
+ for (int i=0; i<AMOUNT; i++) {
+ prln("extracting item " + (i+1) + " / " + AMOUNT);
+ //int expect = (i+Marina.SOUTH_RING_CAPACITY-1) % Marina.SOUTH_RING_CAPACITY;
+ int expect = i+9;
+ long got = new MarinaPacket(out.get(i)).data.toLong();
+ if (got!=expect) {
+ bad = true;
+ prln(" bad instruction: "+got+" expected: "+expect);
+ } else {
+ prln(" good instruction.");
+ }
+ }
+ fatal(bad, "data inserted does not match data retrieved");
+ adjustIndent(-2);
+
+ for (int i=0; i<5; i++) {}
+
+ adjustIndent(-2);
+ prln("End testSouthRecirculate("+AMOUNT+")");
+ }
+
+
+ private void testOverfillTokens(Marina marina) {
+ prln("Begin testOverfillTokens");
+ adjustIndent(2);
+
+ for(int i=0; i<marina.TOKEN_FIFO_CAPACITY + 3; i++)
+ marina.instrIn.fill(SEND_TOKEN);
+ marina.instrIn.fill(SEND_DATA);
+ expectNorthFifoExactly(0);
+
+ adjustIndent(-2);
+ prln("End testSouthRecirculate");
+ }
+
+
+
+ private void doOneTest(int testNum) {
+ prln("");
+ prln("============================================================");
+ prln("MarinaTest: performing test: "+testNum);
+
+ if (testNum!=0) {
+ marina.masterClear();
+ marina.enableInstructionSend(true);
+ }
+
+ try {
+ switch (testNum) {
+ case 0: {
+
+ doOneTest(1); // passes extracted parasitics
+ doOneTest(2); // passes extracted parasitics
+ doOneTest(3); // passes extracted parasitics
+ doOneTest(4); // passes extracted parasitics
+ doOneTest(5); // passes extracted parasitics
+ doOneTest(6);
+
+ doOneTest(1000); // passes extracted parasitics
+ doOneTest(1001); // passes extracted parasitics
+ doOneTest(1003); // passes extracted parasitics
+ doOneTest(1005);
+ doOneTest(3000); // passes extracted parasitics
+ doOneTest(3001); // passes extracted parasitics
+ doOneTest(3003); // passes extracted parasitics
+ doOneTest(3004); // passes extracted parasitics
+ doOneTest(3005); // passes extracted parasitics
+ doOneTest(3006); // passes extracted parasitics
+ doOneTest(3007); // passes extracted parasitics
+ doOneTest(3008); // passes extracted parasitics
+ doOneTest(3009); // passes extracted parasitics
+ doOneTest(3010); // passes extracted parasitics
+ doOneTest(3011); // passes extracted parasitics
+ doOneTest(3012); // passes extracted parasitics
+ doOneTest(3013); // passes extracted parasitics
+ doOneTest(3014); // passes extracted parasitics
+ doOneTest(3015); // passes extracted parasitics
+ doOneTest(3019); // passes extracted parasitics
+ doOneTest(3020); // passes extracted parasitics
+ doOneTest(3022); // passes extracted parasitics
+ doOneTest(3023); // passes extracted parasitics
+ doOneTest(3025); // passes extracted parasitics
+ doOneTest(3026); // passes extracted parasitics
+ doOneTest(3027); // passes extracted parasitics
+ doOneTest(3028); // passes extracted parasitics
+ doOneTest(3029); // passes extracted parasitics
+ doOneTest(3030); // passes extracted parasitics
+ doOneTest(3031); // passes extracted parasitics
+
+ // these tests take a while and usually pass
+ doOneTest(1002);
+ doOneTest(1004);
+ doOneTest(1005);
+ doOneTest(1006);
+ doOneTest(3002);
+ doOneTest(3016);
+ doOneTest(3021);
+ doOneTest(3024);
+ doOneTest(3025);
+ doOneTest(3040);
+
+ // this takes an insanely long time
+ doOneTest(3017);
+ break;
+ }
+ case 1: testChains(marina); break; // passes, 24-Mar (+verilog)
+ case 2: testProperStoppers(marina); break; // passes, 24-Mar (+verilog)
+ case 3: testSouthRecirculate(marina, 1); break; // passes, 24-Mar (+verilog)
+ case 4: getCtrsFlags(marina); break; // 20-Apr (+verilog)
+ case 5: sendInstructions(marina); break; // passes, 24-Mar (+verilog)
+ case 6: walkOneOLC(marina); break; // 21-Apr (+verilog)
+
+ // Russell's tests begin with 1000
+ case 1000: walkOneILC(marina); break; // 20-Apr (+verilog)
+ case 1001: countIlc(marina); break; // 20-Apr (+verilog)
+ case 1002: countOlc(marina); break; // 23-Apr (+verilog)
+
+ case 1003: sendTorpedo(marina); break; // 23-Apr (+verilog) [with wor-hack]
+
+ case 1004: flipIlcBit(marina); break; // 20-Apr (+verilog)
+ case 1005: flipOlcBit(marina); break; // 21-Apr (+verilog)
+
+ case 1006: testSouthRecirculate(marina, Marina.SOUTH_RING_CAPACITY-1); break; // passes, 24-Mar (+verilog)
+
+ // Adam's tests begin with 3000
+ case 3000: sendToken(marina); break; // passes, 24-Mar (+verilog)
+ case 3001: testFlagAB(marina); break; // passes, 08-Apr (+verilog)
+ case 3002: testPredicationOnAB(marina); break; // 22-Apr (+verilog)
+ case 3003: testFlagC(marina); break; // 23-Apr (+verilog)
+ case 3004: testFlagD(marina); break; // 23-Apr (+verilog)
+ case 3005: testFlagDRecomputationTime(marina); break;
+
+ case 3006: testTailWaitsForHead(marina); break;
+ case 3007: testTailWithoutHead(marina); break;
+ case 3008: testHeadWaitsForTail(marina); break; // 22-Apr (+verilog)
+ case 3009: testAbort(marina); break; // 22-Apr (+verilog)
+
+ case 3010: sendData(marina); break; // passes, 24-Mar (+verilog)
+ case 3011: recvData(marina); break; // 21-Apr (+verilog)
+ case 3012: sendDataWithPath(marina); break; // passes, 13-Apr (+verilog)
+
+ case 3013: testSignExtendedLiteral(marina); break; // 20-Apr (+verilog)
+ case 3014: testShiftedLiteral(marina); break; // 20-Apr (+verilog)
+ case 3015: testSendAndRecvToken(marina); break; // 21-Apr (+verilog)
+
+ case 3016: sendDataIlcInfinite(marina); break; // 22-Apr (+verilog)
+ case 3017: testFlagTruthTable(marina); break; // 23-Apr (+verilog)
+
+ case 3019: setOlcFromDataLatch(marina); break; // 23-Apr (+verilog)
+ case 3020: setIlcFromDataLatch(marina); break; // 23-Apr (+verilog)
+ case 3021: recvPath(marina); break; // 22-Apr (+verilog)
+ case 3022: testILC(marina); break; // 23-Apr (+verilog)
+ case 3023: testTorpedoOnAnInfinite(marina); break; // 23-Apr (+verilog)
+ case 3024: testRecvAndSendWalkingOne(marina); break; // 21-Apr (+verilog)
+ case 3025: testOlcDecrementAtHighSpeed(marina); break; // 23-Apr (+verilog)
+
+ case 3026: testNonTorpedoableMoveDoesNotResetDFlag(marina); break; // 23-Apr (+verilog)
+ case 3027: testILCZero(marina); break;
+ case 3028: testAbortOutsideOfLoop(marina); break;
+ case 3029: testDFlagWhenTorpedoLyingInWait(marina); break;
+ case 3030: testSetOlcFollowedByDPredicated(marina); break;
+ case 3031: testOverfillTokens(marina); break;
+
+ case 3040: loadEveryValueOLC(marina); break;
+
+ default:
+ fatal(true, "Test number: "+testNum+" doesn't exist.");
+ break;
+ }
+ // If we get here then test passed
+ prln("Test Result: Passed");
+ printTestTime();
+ //Infrastructure.exit(0);
+ } catch (MarinaUtils.FailureException fe) {
+ System.out.println("******************************************************************************");
+ System.out.println("******************************************************************************");
+ System.out.println("******************************************************************************");
+ System.out.println("******************************************************************************");
+ fe.printStackTrace();
+ }
+ }
+
+
+ //============================ for public use =============================
+
+ /** Exit codes:
+ * 0: test detected success
+ * 2: test detected failure
+ * 1: test crashed
+ */
+ public static void main(String[] args) {
+ startTime = System.currentTimeMillis();
+ new MarinaTest(args);
+ }
+
+}