<> <> <> <> DIRECTORY Commander, CommandTool, Convert, Core, IO, Ports, Random, Rosemary, RosemaryUser, MTSVector; ALS652: CEDAR PROGRAM IMPORTS Commander, CommandTool, Convert, IO, Ports, Random, Rosemary, RosemaryUser, MTSVector = BEGIN controlledClocks: BOOL _ FALSE; ALS652Wires: TYPE = {A, B, nGBA, GAB, CBA, CAB, SBA, SAB}; ALS652WireNames: ARRAY ALS652Wires OF IO.ROPE = ["A", "B", "nGBA", "GAB", "CBA", "CAB", "SBA", "SAB"]; State: TYPE = REF StateRec _ NIL; StateRec: TYPE = RECORD [ cellType: Core.CellType _ NIL, p: Ports.Port _ NIL, pi: ARRAY ALS652Wires OF NAT _ ALL[0], -- indexes in cellType.public Vdd, Gnd: NAT _ 0, AVal, BVal: ARRAY [0..8) OF Ports.Level _ ALL[X] ]; CreateState: PROC [cellType: Core.CellType, p: Ports.Port] RETURNS [ st: State ] = { st _ NEW[StateRec _ [cellType: cellType, p: p]]; [st.Vdd, st.Gnd] _ Ports.PortIndexes[st.cellType.public, "Vdd", "Gnd"]; FOR aw: ALS652Wires IN ALS652Wires DO [st.pi[aw]] _ Ports.PortIndexes[st.cellType.public, ALS652WireNames[aw]]; ENDLOOP; }; RunTest: PROC [st: State, eval: RosemaryUser.TestEvalProc, mts: MTSVector.Capture ] = { ENABLE UNWIND => MTSVector.CloseCapture[mts]; Eval: PROC = { MTSVector.EvalAndCapture[capture: mts, Eval: eval, memory: FALSE]; }; EvalIgnoreX: PROC = { Eval[ ! Rosemary.Stop => IF reason = $BoolWireHasX THEN RESUME ELSE REJECT ]; }; <> <> <> st.p[st.pi[CAB]].d _ st.p[st.pi[CBA]].d _ drive; st.p[st.pi[CAB]].b _ st.p[st.pi[CBA]].b _ FALSE; st.p[st.pi[nGBA]].d _ st.p[st.pi[GAB]].d _ drive; st.p[st.pi[nGBA]].b _ TRUE; st.p[st.pi[GAB]].b _ FALSE; st.p[st.pi[SAB]].d _ st.p[st.pi[SBA]].d _ drive; st.p[st.pi[SAB]].b _ st.p[st.pi[SBA]].b _ FALSE; st.p[st.pi[A]].d _ st.p[st.pi[B]].d _ drive; FOR i: NAT IN [0..8) DO st.p[st.pi[A]].ls[i] _ st.p[st.pi[B]].ls[i] _ st.AVal[i] _ st.BVal[i] _ L; ENDLOOP; EvalIgnoreX[]; <<-->> st.p[st.pi[CAB]].b _ st.p[st.pi[CBA]].b _ TRUE; -- clear internal flipflops EvalIgnoreX[]; <<-->> st.p[st.pi[CAB]].b _ st.p[st.pi[CBA]].b _ FALSE; EvalIgnoreX[]; <<-->> st.p[st.pi[A]].d _ st.p[st.pi[B]].d _ force; Eval[]; <<-->> FOR i: NAT IN [0..8) DO st.p[st.pi[A]].ls[i] _ st.p[st.pi[B]].ls[i] _ st.AVal[i] _ st.BVal[i] _ H; ENDLOOP; Eval[]; <<-->> FOR i: NAT IN [0..8) DO st.p[st.pi[A]].ls[i] _ st.p[st.pi[B]].ls[i] _ st.AVal[i] _ st.BVal[i] _ L; ENDLOOP; st.p[st.pi[A]].d _ st.p[st.pi[B]].d _ drive; Eval[]; <<-->> FOR i: NAT IN [0..2000) DO SimulateALS652Data: PROC = { FOR i: NAT IN [0..8) DO baMux: Ports.Level _ (SELECT TRUE FROM st.p[st.pi[SBA]].b => st.BVal[i], NOT st.p[st.pi[GAB]].b => st.p[st.pi[B]].ls[i], st.p[st.pi[SAB]].b => st.AVal[i], st.p[st.pi[nGBA]].b => st.p[st.pi[A]].ls[i], ENDCASE => ERROR -- logical loop -- ); abMux: Ports.Level _ (SELECT TRUE FROM st.p[st.pi[SAB]].b => st.AVal[i], st.p[st.pi[nGBA]].b => st.p[st.pi[A]].ls[i], st.p[st.pi[SBA]].b => st.BVal[i], NOT st.p[st.pi[GAB]].b => st.p[st.pi[B]].ls[i], ENDCASE => ERROR -- logical loop -- ); IF st.p[st.pi[GAB]].b THEN st.p[st.pi[B]].ls[i] _ abMux; IF NOT st.p[st.pi[nGBA]].b THEN st.p[st.pi[A]].ls[i] _ baMux; ENDLOOP; }; gba, gab, sba, sab, cba, cab: BOOL; didEval: BOOL _ FALSE; <> DO gba _ NOT st.p[st.pi[nGBA]].b; gab _ st.p[st.pi[GAB]].b; sba _ st.p[st.pi[SBA]].b; sab _ st.p[st.pi[SAB]].b; cba _ st.p[st.pi[CBA]].b; cab _ st.p[st.pi[CAB]].b; SELECT genRS.ChooseInt[max: 8] FROM 0 => gba _ NOT gba; 1 => gab _ NOT gab; 2 => sba _ NOT sba; 3 => sab _ NOT sab; 4 => cba _ NOT cba; 5 => cab _ NOT cab; ENDCASE => NULL; <> IF NOT gba OR NOT gab OR sba OR sab THEN EXIT; -- it's OK ENDLOOP; <> SELECT TRUE FROM st.p[st.pi[GAB]].b AND NOT gab => { -- device port B turning off, tester drives the same value for one vector st.p[st.pi[GAB]].b _ FALSE; st.p[st.pi[B]].d _ drive; Eval[]; }; NOT st.p[st.pi[GAB]].b AND gab => { -- device port B turning on st.p[st.pi[GAB]].b _ TRUE; SimulateALS652Data[]; <
> st.p[st.pi[GAB]].b _ FALSE; Eval[]; st.p[st.pi[GAB]].b _ TRUE; -- now turn device port B on Eval[]; st.p[st.pi[B]].d _ expect; -- now disable tester drive }; NOT st.p[st.pi[nGBA]].b AND NOT gba => { -- device port A turning off, tester drives the same value for one vector st.p[st.pi[nGBA]].b _ NOT FALSE; st.p[st.pi[A]].d _ drive; Eval[]; }; st.p[st.pi[nGBA]].b AND gba => { -- device port A turning on st.p[st.pi[nGBA]].b _ NOT TRUE; SimulateALS652Data[]; <
> st.p[st.pi[nGBA]].b _ NOT FALSE; Eval[]; st.p[st.pi[nGBA]].b _ NOT TRUE; -- now turn device port A on Eval[]; st.p[st.pi[A]].d _ expect; -- now disable tester drive }; NOT st.p[st.pi[CAB]].b AND cab => { -- clock A->B rising st.p[st.pi[CAB]].b _ TRUE; FOR i: NAT IN [0..8) DO st.AVal[i] _ st.p[st.pi[A]].ls[i]; ENDLOOP; SimulateALS652Data[]; Eval[]; IF controlledClocks THEN { st.p[st.pi[CAB]].b _ FALSE; -- for clock edge noise immunity Eval[]; }; }; NOT st.p[st.pi[CBA]].b AND cba => { -- clock B->A rising st.p[st.pi[CBA]].b _ TRUE; FOR i: NAT IN [0..8) DO st.BVal[i] _ st.p[st.pi[B]].ls[i]; ENDLOOP; SimulateALS652Data[]; Eval[]; IF controlledClocks THEN { st.p[st.pi[CBA]].b _ FALSE; -- for clock edge noise immunity Eval[]; }; }; ENDCASE => { st.p[st.pi[SAB]].b _ sab; st.p[st.pi[SBA]].b _ sba; st.p[st.pi[CAB]].b _ cab; st.p[st.pi[CBA]].b _ cba; FOR i: NAT IN [0..8) DO IF st.p[st.pi[A]].d = drive THEN -- tester is driving port A st.p[st.pi[A]].ls[i] _ (IF genRS.ChooseInt[max: 1] < 1 THEN H ELSE L); IF st.p[st.pi[B]].d = drive THEN -- tester is driving port B st.p[st.pi[B]].ls[i] _ (IF genRS.ChooseInt[max: 1] < 1 THEN H ELSE L); ENDLOOP; SimulateALS652Data[]; Eval[]; }; ENDLOOP; MTSVector.CloseCapture[mts]; }; RandomCapture: RosemaryUser.TestProc ~ { RunTest[CreateState[cellType, p], Eval, MTSVector.CreateCapture[cellType]]; }; RandomTest: RosemaryUser.TestProc ~ { RunTest[CreateState[cellType, p], Eval, NIL]; }; lastGenSeed: INT _ 1354117939; genRS: Random.RandomStream _ NIL; SetupSeed: PROC [ seed: INT _ 0 ] RETURNS [ IO.ROPE ] = { IF seed = 0 THEN seed _ lastGenSeed; genRS _ Random.Create[seed: seed]; lastGenSeed _ genRS.seed; RETURN[IO.PutFR["New ALS652 random number seed is %d.\n", IO.int[lastGenSeed]]]; }; ALS652RandSeedProc: PROC [ cmd: Commander.Handle ] RETURNS [ result: REF _ NIL, msg: IO.ROPE _ NIL ] -- Commander.CommandProc -- = { seed: INT _ 0; argv: CommandTool.ArgumentVector = CommandTool.Parse[cmd]; IF argv.argc > 1 THEN seed _ Convert.IntFromRope[ argv[1] ! Convert.Error => CONTINUE ]; cmd.out.PutRope[SetupSeed[seed]]; }; Commander.Register["ALS652RandSeed", ALS652RandSeedProc, "Reseeds the random number generator for the ALS652 simulation. Usage is\n ALS652RandSeed n\n where n is an integer. 0 recovers the previous seed."]; RosemaryUser.RegisterTestProc["ALS652Random", RandomTest]; RosemaryUser.RegisterTestProc["ALS652RandomCapture", RandomCapture]; END.