EUSim.mesa
Copyright © 1985 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet July 31, 1985 3:03:17 pm PDT
Last edited by Bertrand Serlet June 8, 1986 5:21:11 pm PDT
Barth, April 16, 1986 3:05:40 pm PST
Louis Monier June 19, 1986 11:54:42 pm PDT
Last Edited by: Louis Monier November 18, 1986 9:17:43 pm PST
DIRECTORY
Core, CoreFlat, Dragon, EUArith, EUUtils, IO, Rope, Rosemary, RosemaryUser, Ports, TerminalIO;
EUSim: CEDAR PROGRAM
IMPORTS CoreFlat, EUArith, EUUtils, IO, Rosemary, RosemaryUser, Ports, TerminalIO =
BEGIN
Test of EU
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: NATLAST[NAT];
Initialize: PROC [p: Ports.Port, public: Core.Wire] = {
InitializePublic[public];
p[DPRejectB].b ← FALSE;
p[DShA].b ← p[DShB].b ← TRUE; -- hack to clean up the ShReg.
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 ROPENIL] RETURNS [tester: RosemaryUser.Tester] = {
InitializePublic[ct.public];
tester ← RosemaryUser.TestProcedureViewer[
cellType: ct,
testButtons: LIST["EUTest", "Sanity Check", "RamTest", "ALUTest", "FUTest"],
name: "EUTest",
displayWires: RosemaryUser.DisplayPortLeafWires[ct],
cutSet: CoreFlat.CreateCutSet[labels: cutSets],
steady: FALSE];
};
constAdr: NAT ← EUUtils.constAdr;
junkAdr: NAT ← EUUtils.junkAdr;
IFUAdr: NAT ← EUUtils.IFUAdr;
fieldAdr: NAT ← EUUtils.fieldAdr;
Phase: TYPE = {A, B};
DoPh: PROC [p: Ports.Port, Eval: PROC, 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[];
-- both clocks down
p[PhA].b ← FALSE; p[PhB].b ← FALSE; Eval[ ! Ports.CheckError => RESUME];
};
Ignore: PROC [p: Ports.Port, port: NAT] ~ {p[port].d ← none};
Force: PROC [p: Ports.Port, port: NAT, val: LONG CARDINAL] ~ {p[port].d ← force; p[port].lc ← val};
Expect: PROC [p: Ports.Port, port: NAT, val: LONG CARDINAL] ~ {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: BOOLFALSE,
aluL, aluR, st2A: NAT ← 0] RETURNS [k: LONG CARDINAL] ~ {
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: PROC, ad: NAT, val: LONG CARDINAL] ~ {
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: PROC, ad: NAT, val: LONG CARDINAL, m: LONG CARDINAL ← 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]
Force[p, KBus, PackK[]];
Ignore[p, DPData];
DoPh[p, Eval, B];         -- 1B: st2B ← st2A
Ignore[p, KBus];
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.
};
-- From PBus to dataIn to cBus to KBus
FromPtoK: PROC [p: Ports.Port, Eval: PROC, val: LONG CARDINAL] ~ {
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: PROC, op: Dragon.ALUOps, opL, opR, res: LONG CARDINAL, cc: Dragon.CondSelects ← False, cond: BOOLFALSE] ~ {
lAd: NAT = 1;
rAd: NAT = 3;
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
TerminalIO.WriteF["ALU, phase %g: %g (%g) %g -> %g", IO.card[nbPhases], IO.card[opL], IO.rope[opName[op]], IO.card[opR], IO.card[res]];
TerminalIO.WriteF[" cc: %g\n", IO.int[ORD[cc]]];
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;
};
FUOp: PROC [p: Ports.Port, Eval: PROC, leftW, rightW, mask, shift: LONG CARDINAL, insert: BOOLFALSE] ~ {
fd: NAT ← ((IF insert THEN 1 ELSE 0)*64+mask)*64+shift;
res: LONG CARDINAL ← EUArith.FieldOp[leftW, rightW, fd];
TerminalIO.WriteF["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�
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𡤏ield; 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 minimum expected from a chip
SanityCheck: RosemaryUser.TestProc = {
FromPtoP2: PROC [val: LONG CARDINAL] ~ {
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: LONG CARDINAL] ~ {
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];
};
-- A quick test of the RAM
RamTest: RosemaryUser.TestProc = {
CheckRamBlock: PROC [from, to: NAT] ~ {
FOR i: NAT IN [from..to) DO
WriteInRam[p, Eval, i, 55555555H];
ENDLOOP;
FOR i: NAT IN [from..to) DO
ReadFromRam[p, Eval, i, 55555555H, i];
WriteInRam[p, Eval, i, 0AAAAAAAAH];
ENDLOOP;
FOR i: NAT IN [from..to) DO
ReadFromRam[p, Eval, i, 0AAAAAAAAH, i];
ENDLOOP;
};
Initialize[p, cellType.public];
CheckRamBlock[0, 4];
-- 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];
};
-- Test the entire RAM
RamTest: RosemaryUser.TestProc = {
CheckRamBlock: PROC [from, to: NAT] ~ {
FOR i: NAT IN [from..to) DO
WriteInRam[p, Eval, i, 55555555H];
ENDLOOP;
FOR i: NAT IN [from..to) DO
ReadFromRam[p, Eval, i, 55555555H, i];
WriteInRam[p, Eval, i, 0AAAAAAAAH];
ENDLOOP;
FOR i: NAT IN [from..to) DO
ReadFromRam[p, Eval, i, 0AAAAAAAAH, i];
ENDLOOP;
};
Initialize[p, cellType.public];
CheckRamBlock[0, 132];
-- 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];
CheckRamBlock[136, 160];
};
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: LONG CARDINAL, cc: Dragon.CondSelects ← False, cond: BOOLFALSE] ~ {
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.WriteF["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];
BC ← ~Cout (passed)
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];
IL ← all 3 high-order bits equal (passed)
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
EZ ← zero, found after a sub at the top of the CLA tree (passed)
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];
Check integrity of aluLeft-> r2B-> pDriver path (passed)
TestALU[BndChk,  000000000H,000000000H,000000000H];
TestALU[BndChk,  055555555H,000000000H,055555555H];
TestALU[BndChk,  0AAAAAAAAH,000000000H,0AAAAAAAAH];
TestALU[BndChk,  0FFFFFFFFH,000000000H,0FFFFFFFFH];
Logic operations (passed)
TestALU[Or, 000FF00FFH,00F0F0F0FH,00FFF0FFFH];
TestALU[And,  000FF00FFH,00F0F0F0FH,0000F000FH];
TestALU[Xor,  000FF00FFH,00F0F0F0FH,00FF00FF0H];
All additions (passed)
TestAdd[SAdd];
TestAdd[UAdd];
TestAdd[VAdd];
TestAdd[LAdd];
TestAdd[VAdd2];
All subtractions (passed)
TestSub[SSub];
TestSub[USub];
TestSub[VSub];
TestSub[LSub];
Constant Conditions (passed)
TestALU[LAdd, 000000000H, 000000000H, 000000000H, False, FALSE];
TestALU[LAdd, 000000000H, 000000000H, 000000000H, ModeFault, TRUE];
};
FUTest: RosemaryUser.TestProc = {
TestFU: PROC [leftW, rightW, mask, shift: LONG CARDINAL, insert: BOOLFALSE] ~ {
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 = {
}; 
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";
RosemaryUser.RegisterTestProc["EUTest",  EUTest];
RosemaryUser.RegisterTestProc["Sanity Check",  SanityCheck];
RosemaryUser.RegisterTestProc["RamTest",  RamTest];
RosemaryUser.RegisterTestProc["ALUTest",  ALUTest];
RosemaryUser.RegisterTestProc["FUTest",  FUTest];
END.
ShiftDBus: PROC [bitOut: BOOL] ~ {
p[DHold].b ← TRUE;
p[DShA].b ← TRUE; -- DShIn is sampled
p[DShB].b ← FALSE;
Eval[];
p[DShA].b ← FALSE; -- DShIn is latched
p[DShB].b ← FALSE;
Eval[];
p[DShA].b ← FALSE; -- DShOut is driven with a new value
p[DShB].b ← TRUE;
p[DShOut].d ← expect;
p[DShOut].b ← bitOut;
Eval[];
p[DShA].b ← FALSE; -- Back to normal
p[DShB].b ← FALSE;
p[DShOut].d ← none;
p[DShRd].b ← FALSE;
p[DShWt].b ← FALSE;
p[DHold].b ← FALSE;
p[DStAd].c ← 0;
Eval[];
};