<> <> <> <> <> <> <> <<>> DIRECTORY BitOps, Core, CoreFlat, Dragon, DragOpsCross, EUArith, ICTest, IO, Rope, Rosemary, RosemaryUser, Ports, TerminalIO; EUSim: CEDAR PROGRAM IMPORTS BitOps, CoreFlat, EUArith, ICTest, IO, Rosemary, RosemaryUser, Ports, TerminalIO = BEGIN <> ROPE: TYPE = Rope.ROPE; nbPhases: INT _ 0; Vdd, Gnd, PadVdd, PadGnd, PhA, PhB, DPRejectB, DPData, -- 32 bits KBus, -- 32 bits EURdFromPBus3AB, EUWriteToPBus3AB, EUAluOp2AB, -- 4 bits EUCondSel2AB, -- 4 bits EUCondition2B, DShA, DShB, DShRd, DShWt, DShIn, DShOut, DHold, DStAd: NAT _ LAST[NAT]; REProc: TYPE = PROC [memory: BOOL _ TRUE]; Initialize: PROC [p: Ports.Port, public: Core.Wire] = { InitializePublic[public]; p[DPRejectB].b _ FALSE; p[DShA].b _ p[DShB].b _ FALSE; p[DShRd].b _ p[DShWt].b _ p[DShIn].b _ p[DHold].b _ FALSE; p[DStAd].c _ 0; p[EUCondSel2AB].c _ 0; -- false p[EUAluOp2AB].c _ ORD[Dragon.ALUOps[Or]]; -- 0 p[EURdFromPBus3AB].b _ FALSE; -- don't read data from PBus p[EUWriteToPBus3AB].b _ FALSE; -- and don't write onto PBus during PhB p[DShOut].b _ FALSE; p[DShOut].d _ none; p[EUCondition2B].b _ FALSE; p[EUCondition2B].d _ none; p[KBus].d _ none; p[DPData].d _ none; }; InitializePublic: PROC [public: Core.Wire] = { [Vdd, Gnd, PadVdd, PadGnd, PhA, PhB, DPRejectB, DPData] _ Ports.PortIndexes[public, "Vdd", "Gnd", "PadVdd", "PadGnd", "PhA", "PhB", "DPRejectB", "DPData"]; [KBus, EURdFromPBus3AB, EUWriteToPBus3AB, EUAluOp2AB, EUCondSel2AB, EUCondition2B] _ Ports.PortIndexes[public, "KBus", "EURdFromPBus3AB", "EUWriteToPBus3AB", "EUAluOp2AB", "EUCondSel2AB", "EUCondition2B"]; [DShA, DShB, DShRd, DShWt, DShIn, DShOut, DHold, DStAd] _ Ports.PortIndexes[public, "DShA", "DShB", "DShRd", "DShWt", "DShIn", "DShOut", "DHold", "DStAd"]; [] _ Rosemary.SetFixedWire[public[Vdd], H]; [] _ Rosemary.SetFixedWire[public[Gnd], L]; [] _ Rosemary.SetFixedWire[public[PadVdd], H]; [] _ Rosemary.SetFixedWire[public[PadGnd], L]; [] _ Ports.InitTesterDrive[public[PhA], force]; [] _ Ports.InitTesterDrive[public[PhB], force]; [] _ Ports.InitTesterDrive[public[DPRejectB], force]; [] _ Ports.InitPort[public[DPData], lc]; [] _ Ports.InitTesterDrive[public[DPData], expect]; [] _ Ports.InitPort[public[KBus], lc]; [] _ Ports.InitTesterDrive[public[KBus], force]; [] _ Ports.InitTesterDrive[public[EURdFromPBus3AB], force]; [] _ Ports.InitTesterDrive[public[EUWriteToPBus3AB], force]; [] _ Ports.InitPort[public[EUAluOp2AB], c]; [] _ Ports.InitTesterDrive[public[EUAluOp2AB], force]; [] _ Ports.InitPort[public[EUCondSel2AB], c]; [] _ Ports.InitTesterDrive[public[EUCondSel2AB], force]; [] _ Ports.InitTesterDrive[public[EUCondition2B], expect]; [] _ Ports.InitTesterDrive[public[DShA], force]; [] _ Ports.InitTesterDrive[public[DShB], force]; [] _ Ports.InitTesterDrive[public[DShRd], force]; [] _ Ports.InitTesterDrive[public[DShWt], force]; [] _ Ports.InitTesterDrive[public[DShIn], force]; [] _ Ports.InitTesterDrive[public[DHold], force]; [] _ Ports.InitPort[public[DStAd], c]; [] _ Ports.InitTesterDrive[public[DStAd], force]; [] _ Ports.InitTesterDrive[public[DShOut], none]; }; ExerciseRose: PUBLIC PROC [ct: Core.CellType, cutSets: LIST OF ROPE _ NIL] RETURNS [tester: RosemaryUser.Tester] = { InitializePublic[ct.public]; tester _ RosemaryUser.TestProcedureViewer[ cellType: ct, testButtons: LIST["ZeroAndOne", "Sanity Check", "RamTest", "ALUTest", "FUTest", "WiresTest", "DBusTest"], name: "EUTest", displayWires: RosemaryUser.DisplayPortLeafWires[ct], cutSet: CoreFlat.CreateCutSet[labels: cutSets], steady: FALSE]; }; stackAdr: NAT = ORD[DragOpsCross.ProcessorRegister[euStack]]; junkAdr: NAT = ORD[DragOpsCross.ProcessorRegister[euJunk]]; ifuAdr: NAT = ORD[DragOpsCross.ProcessorRegister[euToKBus]]; marAdr: NAT = ORD[DragOpsCross.ProcessorRegister[euMAR]]; fieldAdr: NAT = ORD[DragOpsCross.ProcessorRegister[euField]]; constAdr: NAT = ORD[DragOpsCross.ProcessorRegister[euConstant]]; bogusAdr: NAT = ORD[DragOpsCross.ProcessorRegister[euBogus]]; Phase: TYPE = {A, B}; DoPh: PROC [p: Ports.Port, Eval: REProc, ph: Phase] = { nbPhases _ nbPhases+1; <<-- Invariants>> IF PhA=0 AND PhB=0 THEN ERROR; -- port indexes not initialized <<-- On PhA the chip always drives the PBus, so we check that the tester is not driving>> IF ph=A AND p[DPData].d=force THEN ERROR; <<-- appropriate clock up>> p[PhA].b _ ph=A; p[PhB].b _ ph=B; Eval[FALSE]; <<-- both clocks down>> p[PhA].b _ FALSE; p[PhB].b _ FALSE; Eval[FALSE ! Ports.CheckError =>RESUME]; }; Ignore: PROC [p: Ports.Port, port: NAT] ~ {p[port].d _ none}; Force: PROC [p: Ports.Port, port: NAT, val: CARD] ~ {p[port].d _ force; p[port].lc _ val}; Expect: PROC [p: Ports.Port, port: NAT, val: CARD] ~ {p[port].d _ expect; p[port].lc _ val}; ReadPBus: PROC [p: Ports.Port] ~ { p[EURdFromPBus3AB].b _ TRUE; p[EUWriteToPBus3AB].b _ FALSE; }; WritePBus: PROC [p: Ports.Port] ~ { p[EURdFromPBus3AB].b _ FALSE; p[EUWriteToPBus3AB].b _ TRUE; }; IgnorePBus: PROC [p: Ports.Port] ~ { p[EURdFromPBus3AB].b _ FALSE; p[EUWriteToPBus3AB].b _ FALSE; }; PackK: PROC [a, b: NAT _ constAdr, c: NAT _ junkAdr, st3AisC: BOOL _ FALSE, aluL, aluR, st2A: NAT _ 0] RETURNS [k: CARD] ~ { k _ (((((LONG[a]*256+LONG[b])*256+LONG[c])*2+(IF st3AisC THEN 1 ELSE 0))*4+aluL)*8+aluR)*4+st2A; }; WriteInRam: PROC [p: Ports.Port, Eval: REProc, ad: NAT, val: CARD] ~ { Force[p, KBus, PackK[c: ad]]; -- load c address in kReg ReadPBus[p]; Force[p, DPData, val]; DoPh[p, Eval, B]; -- 0B: kReg _ ad; dataIn _ val Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: ram[ad] _ val }; ReadFromRam: PROC [p: Ports.Port, Eval: REProc, ad: NAT, val: CARD, m: CARD _ 01234567H] ~ { Force[p, KBus, PackK[b: ad, st2A: 0]]; -- load b address in kReg ReadPBus[p]; Force[p, DPData, m]; -- to detect no drive on PBus DoPh[p, Eval, B]; -- 0B: kReg _ ad Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: st2A _ ram[ad] CheckSt2A[p, Eval, val]; -- 4 more phases }; <<-- Utility, not a test in itself>> <<-- Gets value through the KBus and computes OR[ct0, val]>> PutValInR2B: PROC [p: Ports.Port, Eval: REProc, val, k: CARD] ~ { Force[p, KBus, PackK[a: constAdr, aluR: 3]]; -- load addresses in kReg IgnorePBus[p]; Force[p, DPData, 0]; -- to detect no drive on PBus DoPh[p, Eval, B]; -- 0B: kReg _ ad Force[p, KBus, val]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: left _ ram[ad], right _ kBus p[EUAluOp2AB].c _ 0; -- ORD[Or] Force[p, KBus, k]; Ignore[p, DPData]; DoPh[p, Eval, B]; -- 1B: r2B _ right }; <<-- Gets value through the KBus and computes OR[ct0, val], then moves it down by two latches>> <<-- k is the value on the kBus in the last PhB>> PutValInR3B: PROC [p: Ports.Port, Eval: REProc, val, k: CARD, reject: BOOL _ FALSE] ~ { PutValInR2B[p, Eval, val, PackK[]]; -- 1B: r2B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: r3A _ val IF reject THEN p[DPRejectB].b _ TRUE; Force[p, KBus, k]; Ignore[p, DPData]; DoPh[p, Eval, B]; -- 2B: r3B _ val p[DPRejectB].b _ FALSE; }; <<-- Checks whether st2A=val>> CheckSt2A: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { Force[p, KBus, PackK[]]; Ignore[p, DPData]; DoPh[p, Eval, B]; -- 0B: st2B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: st3A _ val Force[p, KBus, PackK[]]; WritePBus[p]; Expect[p, DPData, val]; DoPh[p, Eval, B]; -- 1B: PBus _ st3A = val ??? Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: just for sync. }; <<-- Computes OP(left, right) and checks that the result is equal to val>> OpAndCheck: PROC [p: Ports.Port, Eval: REProc, val: CARD, op: NAT] ~ { p[EUAluOp2AB].c _ op; -- ORD[alu opcode] Force[p, KBus, PackK[]]; Ignore[p, DPData]; DoPh[p, Eval, B]; -- 0B: r2B _ val Ignore[p, KBus]; Expect[p, DPData, val]; DoPh[p, Eval, A]; -- 1A: PBus _ r2B = val ???. }; <<>> <<-- From PBus to dataIn to cBus to KBus>> FromPtoK: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { Force[p, KBus, PackK[c: ifuAdr]]; -- cBus->IFU on next PhA ReadPBus[p]; Force[p, DPData, val]; DoPh[p, Eval, B]; -- Cycle 0: dataIn _ val Expect[p, KBus, val]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- Cycle 1: KBus _ cBus _ val IgnorePBus[p]; }; ALUOp: PROC [p: Ports.Port, Eval: REProc, op: Dragon.ALUOps, opL, opR, res: CARD, cc: Dragon.CondSelects _ False, cond: BOOL _ FALSE] ~ { lAd: NAT = 1; rAd: NAT = 3; TerminalIO.PutF["ALU, phase %g: %g (%g) %g -> %g", IO.card[nbPhases], IO.card[opL], IO.rope[opName[op]], IO.card[opR], IO.card[res]]; TerminalIO.PutF[" cc: %g\n", IO.int[ORD[cc]]]; WriteInRam[p, Eval, lAd, opL]; WriteInRam[p, Eval, rAd, opR]; p[EURdFromPBus3AB].b _ FALSE; Force[p, KBus, PackK[a: lAd, b: rAd]]; Ignore[p, DPData]; DoPh[p, Eval, B]; -- 0B: aAdr _ lAd, bAdr _ rAd p[EUAluOp2AB].c _ ORD[op]; Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: opL _ ram[lAd]; opR _ ram[rAd] p[EUCondSel2AB].c _ ORD[cc]; p[EUCondition2B].b _ cond; p[EUCondition2B].d _ expect; p[DShOut].b _ FALSE; p[DShOut].d _ expect; Force[p, KBus, PackK[]]; Ignore[p, DPData]; DoPh[p, Eval, B]; -- 1B: r2B _ opL op opR p[EUCondSel2AB].c _ 0; p[EUCondition2B].b _ FALSE; p[EUCondition2B].d _ none; p[DShOut].d _ none; Ignore[p, KBus]; Expect[p, DPData, res]; DoPh[p, Eval, A]; -- 2A: PBus _ r2B p[EUAluOp2AB].c _ 0; }; <<-- This test uses the field register to hold the field descriptor>> FUOp: PROC [p: Ports.Port, Eval: REProc, leftW, rightW, mask, shift: CARD, insert: BOOL _ FALSE] ~ { fd: NAT _ ((IF insert THEN 1 ELSE 0)*64+mask)*64+shift; res: CARD _ EUArith.FieldOp[leftW, rightW, fd]; TerminalIO.PutF["FU, phase %g, mask: %g, shift: %g, insert: %g\n", IO.card[nbPhases], IO.card[mask], IO.card[shift], IO.bool[insert]]; WriteInRam[p, Eval, fieldAdr, LONG[fd]]; -- field_fd WriteInRam[p, Eval, 1, leftW]; -- ram[0]_leftW WriteInRam[p, Eval, 2, rightW]; -- ram[1]_rightW Force[p, KBus, PackK[a: 1, b: 2, aluR: 4]]; -- right_field; left_leftW; st2A_rightW Ignore[p, DPData]; DoPh[p, Eval, B]; -- 0B: load operand addresses p[EUAluOp2AB].c _ ORD[Dragon.ALUOps[FOP]]; Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: read ram Force[p, KBus, PackK[]]; Ignore[p, DPData]; DoPh[p, Eval, B]; -- 1B: field unit is active Ignore[p, KBus]; Expect[p, DPData, res]; DoPh[p, Eval, A]; -- 2A: PBus _ r2B }; <<>> <<>> <<-- Test procs>> <<>> <<-- The absolute minimum expected from a chip>> ZeroAndOne: RosemaryUser.TestProc = { Initialize[p, cellType.public]; FromPtoK[p, Eval,000000000H]; FromPtoK[p, Eval,0FFFFFFFFH]; FromPtoK[p, Eval,05555AAAAH]; }; <<>> <<-- The minimum expected from a chip>> SanityCheck: RosemaryUser.TestProc = { FromPtoP2: PROC [val: CARD] ~ { Force[p, KBus, PackK[st3AisC: TRUE]]; -- st3A _ cBus on next PhA ReadPBus[p]; Force[p, DPData, val]; DoPh[p, Eval, B]; -- 0B: dataIn _ val Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: st3A _ cBus _ dataIn (val) Force[p, KBus, PackK[]]; WritePBus[p]; Expect[p, DPData, val]; DoPh[p, Eval, B]; -- 1B: PBus _ st3A = val ??? Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: just for sync. }; FromPtoP4: PROC [val: CARD] ~ { Force[p, KBus, PackK[st2A: 2]]; -- st2A _ cBus on next PhA ReadPBus[p]; Force[p, DPData, val]; DoPh[p, Eval, B]; -- 0B: dataIn _ val Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 1A: st2A _ cBus _ val Force[p, KBus, PackK[]]; IgnorePBus[p]; Force[p, DPData, 01234567H]; -- to eliminate old (good) value on PBus DoPh[p, Eval, B]; -- 1B: st2B _ st2A Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: st3A _ st2B Force[p, KBus, PackK[]]; WritePBus[p]; Expect[p, DPData, val]; DoPh[p, Eval, B]; -- 2B: PBus _ st3A = val ??? Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 3A: just for sync. }; Initialize[p, cellType.public]; FromPtoP4[000000000H]; FromPtoP4[0AAAAAAAAH]; FromPtoP4[055555555H]; FromPtoP4[0FFFFFFFFH]; FromPtoP4[02BAD2BADH]; FromPtoP2[000000000H]; FromPtoP2[0AAAAAAAAH]; FromPtoP2[055555555H]; FromPtoP2[0FFFFFFFFH]; FromPtoP2[02BAD2BADH]; FromPtoK[p, Eval,000000000H]; FromPtoK[p, Eval,0AAAAAAAAH]; FromPtoK[p, Eval,055555555H]; FromPtoK[p, Eval,0FFFFFFFFH]; FromPtoK[p, Eval,02BAD2BADH]; }; <<-- Test the entire RAM>> RamTest: RosemaryUser.TestProc = { Val: PROC [i: NAT] RETURNS [val: CARD] ~ { val _ 0137FA00H+i; }; CheckRamBlock: PROC [from, to: NAT] ~ { FOR i: NAT IN [from..to) DO WriteInRam[p, Eval, i, 0137FA00H+i]; ENDLOOP; FOR i: NAT IN [from..to) DO ReadFromRam[p, Eval, i, 0137FA00H+i]; WriteInRam[p, Eval, i, 0FEC8500H+0FFH-i]; ENDLOOP; FOR i: NAT IN [from..to) DO ReadFromRam[p, Eval, i, 0FEC8500H+0FFH-i]; ENDLOOP; }; Initialize[p, cellType.public]; CheckRamBlock[stackAdr, junkAdr]; CheckRamBlock[junkAdr+1, constAdr]; -- avoid euJunk, since it should not exist CheckRamBlock[constAdr+4, bogusAdr]; <<-- Read constants in ROM>> ReadFromRam[p, Eval, constAdr, 0]; ReadFromRam[p, Eval, constAdr+1, 1]; ReadFromRam[p, Eval, constAdr+2, 2]; ReadFromRam[p, Eval, constAdr+3, 3]; }; ALUTest: RosemaryUser.TestProc = { ResetCarry: PROC ~ {TestALU[LAdd, 0, 0, 0]}; SetCarry: PROC ~ {TestALU[UAdd, 0FFFFFFFFH, 000000001H, 0]}; TestALU: PROC [op: Dragon.ALUOps, opL, opR, res: CARD, cc: Dragon.CondSelects _ False, cond: BOOL _ FALSE] ~ { ALUOp[p, Eval, op, opL, opR, res, cc, cond]; }; TestAdd: PROC [op: Dragon.ALUOps] ~ { IF op#SAdd AND op#UAdd AND op#VAdd AND op#LAdd AND op#VAdd2 THEN ERROR; ResetCarry[]; TestALU[op, 000000000H,000000000H,000000000H]; TestALU[op, 000000001H,000000002H,000000003H]; TestALU[op, 00FFFFFFFH,000000001H,010000000H]; TestALU[op, 012345678H,087654321H,099999999H]; TestALU[op, 0FFFFFFFFH,000000000H,0FFFFFFFFH]; TestALU[op, 000000000H,0FFFFFFFFH,0FFFFFFFFH]; <<-- may generates a carry>> TestALU[op, 000000001H,0FFFFFFFFH,000000000H]; ResetCarry[]; }; TestSub: PROC [op: Dragon.ALUOps] ~ { IF op#SSub AND op#USub AND op#VSub AND op#LSub THEN ERROR; TestALU[op, 000000000H,000000000H,000000000H]; TestALU[op, 000000003H,000000002H,000000001H]; TestALU[op, 010000000H,000000001H,00FFFFFFFH]; TestALU[op, 099999999H,087654321H,012345678H]; TestALU[op, 0FFFFFFFFH,000000000H,0FFFFFFFFH]; TestALU[op, 0FFFFFFFFH,0FFFFFFFFH,000000000H]; <<-- may generates a carry>> TestALU[op, 000000000H,0FFFFFFFFH,000000001H]; ResetCarry[]; }; Initialize[p, cellType.public]; TerminalIO.PutF["New Test\n"]; <<-- OvFl _ (Cout XOR opL[0] XOR opR[0]) XOR res[0], so we need a carry out;>> ResetCarry[]; TestALU[UAdd, 07FFFFFFFH, 000000001H, 080000000H, OvFl, TRUE]; ResetCarry[]; TestALU[UAdd, 07FFFFFFFH, 000000000H, 07FFFFFFFH, OvFl, FALSE]; <> ResetCarry[]; TestALU[BndChk, 000000000H, 000000001H, 000000000H, BC, FALSE]; ResetCarry[]; TestALU[BndChk, 000000002H, 000000001H, 000000002H, BC, TRUE]; ResetCarry[]; TestALU[BndChk, 000000000H, 000000001H, 000000000H, NotBC, TRUE]; ResetCarry[]; TestALU[BndChk, 000000002H, 000000001H, 000000002H, NotBC, FALSE]; <<-- LZ _ Cout XOR opL[0] XOR opR[0], so we need a carry out; GE _ ~ LZ>> ResetCarry[]; TestALU[USub, 000000000H, 000000001H, 0FFFFFFFFH, LZ, TRUE]; ResetCarry[]; TestALU[UAdd, 000000000H, 000000000H, 000000000H, LZ, FALSE]; ResetCarry[]; TestALU[UAdd, 000000000H, 000000000H, 000000000H, GE, TRUE]; ResetCarry[]; TestALU[USub, 000000000H, 000000001H, 0FFFFFFFFH, GE, FALSE]; <<-- LE _ EZ OR LZ>> ResetCarry[]; TestALU[USub, 000000000H, 000000000H, 000000000H, LE, TRUE]; TestALU[USub, 000000001H, 000000000H, 000000001H, LE, FALSE]; TestALU[USub, 000000001H, 000000000H, 000000001H, NE, TRUE]; TestALU[USub, 000000001H, 000000001H, 000000000H, NE, FALSE]; TestALU[USub, 000000001H, 000000000H, 000000001H, GZ, TRUE]; TestALU[USub, 000000000H, 000000000H, 000000000H, GZ, FALSE]; <> TestALU[LAdd, 07FFFFFFFH, 000000001H, 080000000H, IL, TRUE]; -- opL=011 TestALU[LAdd, 000000000H, 0FFFFFFFFH, 0FFFFFFFFH, IL, FALSE]; -- all 0 or 1 TestALU[LAdd, 010000000H, 010000000H, 020000000H, IL, TRUE]; -- res=001 TestALU[LAdd, 000000001H, 000000001H, 000000002H, IL, FALSE]; -- all 0 TestALU[LAdd, 07FFFFFFFH, 000000001H, 080000000H, NotIL, FALSE]; -- opL=011 TestALU[LAdd, 000000000H, 0FFFFFFFFH, 0FFFFFFFFH, NotIL, TRUE]; -- all 0 or 1 TestALU[LAdd, 010000000H, 010000000H, 020000000H, NotIL, FALSE]; -- res=001 TestALU[LAdd, 000000001H, 000000001H, 000000002H, NotIL, TRUE]; -- all 0 <> ResetCarry[]; TestALU[USub, 000000000H, 000000000H, 000000000H, EZ, TRUE]; TestALU[USub, 02BAD2BADH, 02BAD2BADH, 000000000H, EZ, TRUE]; TestALU[USub, 0FFFFFFFFH, 0FFFFFFFFH, 000000000H, EZ, TRUE]; TestALU[USub, 000000001H, 000000000H, 000000001H, EZ, FALSE]; TestALU[USub, 02BAD2BADH, 000000001H, 02BAD2BACH, EZ, FALSE]; TestALU[USub, 000000001H, 000000002H, 0FFFFFFFFH, EZ, FALSE]; < r2B-> pDriver path (passed)>> TestALU[BndChk, 000000000H,000000000H,000000000H]; TestALU[BndChk, 055555555H,000000000H,055555555H]; TestALU[BndChk, 0AAAAAAAAH,000000000H,0AAAAAAAAH]; TestALU[BndChk, 0FFFFFFFFH,000000000H,0FFFFFFFFH]; <> TestALU[Or, 000FF00FFH,00F0F0F0FH,00FFF0FFFH]; TestALU[And, 000FF00FFH,00F0F0F0FH,0000F000FH]; TestALU[Xor, 000FF00FFH,00F0F0F0FH,00FF00FF0H]; <> TestAdd[SAdd]; TestAdd[UAdd]; TestAdd[VAdd]; TestAdd[LAdd]; TestAdd[VAdd2]; <> TestSub[SSub]; TestSub[USub]; TestSub[VSub]; TestSub[LSub]; <> TestALU[LAdd, 000000000H, 000000000H, 000000000H, False, FALSE]; TestALU[LAdd, 000000000H, 000000000H, 000000000H, ModeFault, TRUE]; }; FUTest: RosemaryUser.TestProc = { TestFU: PROC [leftW, rightW, mask, shift: CARD, insert: BOOL _ FALSE] ~ { FUOp[p, Eval, leftW, rightW, mask, shift, insert]; }; Initialize[p, cellType.public]; <<-- Testing the shifter (no masking) (passed)>> FOR shift: NAT IN [0..32] DO TestFU[leftW: 0F0402010H, rightW: 0AAAAAAAAH, mask: 32, shift: shift]; ENDLOOP; <<-- Testing the mask generator (no shifting) (passed)>> FOR shift: NAT IN [0..32] DO TestFU[leftW: 0F0402010H, rightW: 0AAAAAAAAH, mask: shift, shift: 0]; ENDLOOP; <<-- General Shift and Mask test (passed)>> FOR i: NAT IN [0..32] DO TestFU[leftW: 0F0402010H, rightW: 0AAAAAAAAH, mask: (4*i+19) MOD 33, shift: (3*i+5) MOD 33]; ENDLOOP; <<-- With insert (passed)>> TestFU[leftW: 0F0402010H, rightW: 02BAD2BADH, mask: 0, shift: 0, insert: TRUE]; TestFU[leftW: 0F0402010H, rightW: 02BAD2BADH, mask: 32, shift: 0, insert: TRUE]; TestFU[leftW: 0F0402010H, rightW: 02BAD2BADH, mask: 32, shift: 32, insert: TRUE]; TestFU[leftW: 0F0402010H, rightW: 0AAAAAAAAH, mask: 18, shift: 4, insert: TRUE]; TestFU[leftW: 0F0402010H, rightW: 02BAD2BADH, mask: 21, shift: 12, insert: TRUE]; }; EUTest: RosemaryUser.TestProc = { }; <<-- Try to put a zero and a 1 through every path in the EU>> <<-- I use an asymetric pattern to detect flips in buses>> <<-- I use the bus names defined in the schematics of the datapath>> c1: CARD = 00137FFFFH; c2: CARD = 0FEC80000H; <<-- Test the tristate driver r3B on the cBus; normal case>> R3BNormal: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR3B[p, Eval, val, PackK[st3AisC: TRUE]];-- 2B: r3B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 3A: st3A _ val Force[p, KBus, PackK[]]; WritePBus[p]; Expect[p, DPData, val]; DoPh[p, Eval, B]; -- 3B: PBus _ st3A = val ??? Ignore[p, KBus]; IgnorePBus[p]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 4A: just for sync. }; <<-- Test the tristate driver r3B on the cBus; reject case>> R3BReject: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR3B[p, Eval, val, PackK[], TRUE];-- 2B: r3B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 3A: ram[marAdr] _ cBus _ val (reject) ReadFromRam[p, Eval, marAdr, val]; -- check marAdr }; <<-- Bypass from r2B to left>> R2BtoLeft: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR2B[p, Eval, val, PackK[b: constAdr, aluL: 1]]; -- 1B: r2B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: left _ r2B _ val; right _ 0 OpAndCheck[p, Eval, val, 0]; }; <<-- Bypass from r2B to right>> R2BtoRight: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR2B[p, Eval, val, PackK[a: constAdr, aluR: 1]]; -- 1B: r2B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: right _ r2B _ val; left _ 0 OpAndCheck[p, Eval, val, 0]; }; <<-- Bypass from r2B to st2A>> R2BtoSt2A: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR2B[p, Eval, val, PackK[a: constAdr, st2A: 1]]; -- 1B: r2B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: st2A _ r2B _ val CheckSt2A[p, Eval, val]; }; <<-- Bypass from r3B to left>> CBustoLeft: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR3B[p, Eval, val, PackK[b: constAdr, aluL: 2]]; -- 1B: r3B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: left _ r2B _ val; right _ 0 OpAndCheck[p, Eval, val, 0]; }; CBustoRight: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR3B[p, Eval, val, PackK[a: constAdr, aluR: 2]]; -- 1B: r3B _ val Ignore[p, KBus]; Ignore[p, DPData]; DoPh[p, Eval, A]; -- 2A: right _ r2B _ val; left _ 0 OpAndCheck[p, Eval, val, 0]; }; WiresTest: RosemaryUser.TestProc = { TryAllPaths: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { FromPtoK[p, Eval, val]; -- 4 evals R3BNormal[p, Eval, val]; -- 24 evals R3BReject[p, Eval, val]; -- 24 evals R2BtoLeft[p, Eval, val]; -- 12 evals R2BtoRight[p, Eval, val]; -- 12 evals R2BtoSt2A[p, Eval, val]; -- 16 evals CBustoLeft[p, Eval, val]; -- 16 evals CBustoRight[p, Eval, val]; -- 16 evals }; TryAllPaths[p, Eval, c1]; TryAllPaths[p, Eval, c2]; }; DBusTest: RosemaryUser.TestProc = { Initialize[p, cellType.public]; ReadR2BWithDBus[p, Eval, 0A123456FH]; }; ReadR2BWithDBus: PROC [p: Ports.Port, Eval: REProc, val: CARD] ~ { PutValInR2B[p, Eval, val, PackK[a: constAdr, aluR: 2]]; -- 1B: r2B _ val Ignore[p, KBus]; Ignore[p, DPData]; p[DStAd].c _ 7; -- EUUtils.r2BRow p[DShRd].b _ TRUE; p[DShWt].b _ FALSE; Eval[]; -- read the register: shiftReg _ reg[regAd] p[DShRd].b _ FALSE; p[DShWt].b _ FALSE; FOR i: NAT IN [0..32) DO bitOut: BOOL _ BitOps.EBFD[val, i]; p[DShOut].d _ expect; p[DShOut].b _ bitOut; p[DShB].b _ TRUE; Eval[]; -- _ ; shOut _ new value p[DShOut].d _ none; p[DShB].b _ FALSE; Eval[]; -- latched; shOut tristate p[DShIn].b _ FALSE; p[DShA].b _ TRUE; Eval[]; -- _ ; shIn is sampled p[DShA].b _ FALSE; p[DShB].b _ FALSE; Eval[]; -- latched ENDLOOP; p[DShRd].b _ FALSE; p[DShWt].b _ FALSE; p[DHold].b _ FALSE; p[DStAd].c _ 0; Eval[]; DoPh[p, Eval, A]; -- A: for synch }; Register: PROC [usingTester: BOOL] ~ { IF usingTester THEN { -- for IMS tester ICTest.RegisterTestProc[euTest, "ZeroAndOne", ZeroAndOne]; ICTest.RegisterTestProc[euTest, "Sanity Check", SanityCheck]; ICTest.RegisterTestProc[euTest, "RamTest", RamTest]; ICTest.RegisterTestProc[euTest, "ALUTest", ALUTest]; ICTest.RegisterTestProc[euTest, "FUTest", FUTest]; } ELSE { -- for Rosemary simulation RosemaryUser.RegisterTestProc["ZeroAndOne", ZeroAndOne]; RosemaryUser.RegisterTestProc["Sanity Check", SanityCheck]; RosemaryUser.RegisterTestProc["RamTest", RamTest]; RosemaryUser.RegisterTestProc["ALUTest", ALUTest]; RosemaryUser.RegisterTestProc["FUTest", FUTest]; RosemaryUser.RegisterTestProc["WiresTest", WiresTest]; RosemaryUser.RegisterTestProc["DBusTest", DBusTest]; }; }; euTest: ROPE = "EU4 Test"; opName: ARRAY Dragon.ALUOps OF Rope.ROPE; opName[Or] _ "Or"; opName[And] _ "And"; opName[VAdd2] _ "VAdd2"; opName[BndChk] _ "BndChk"; opName[SAdd] _ "SAdd"; opName[SSub] _ "SSub"; opName[LAdd] _ "LAdd"; opName[LSub] _ "LSub"; opName[Xor] _ "Xor"; opName[res9] _ "res9"; opName[FOP] _ "FOP"; opName[res11] _ "res11"; opName[VAdd] _ "VAdd"; opName[VSub] _ "VSub"; opName[UAdd] _ "UAdd"; opName[USub] _ "USub"; END.