Test of EU2
Vdd, Gnd, PadVdd, PadGnd, PhA, PhB, VRef,
DPRejectB, DPData, -- 32 bits
KBus, --
32 bits
-- Phase-multiplexed on KBus
aAdr [0..7]
bAdr [8..15]
cAdr [16..23]
EUSt3AisCBus2BA [24]
EUAluLeftSrc1BA [25..26]
EUAluRightSrc1BA [27..29]
EUStore2ASrc1BA [30..31]
EURes3BisPBus3AB, EUWriteToPBus3AB,
EUAluOp2AB, -- 4 bits Dragon.ALUOps
EUCondSel2AB, -- 4 bits Dragon.CondSelects
EUCondition2B,
DShA, DShB, DShRd, DShWt, DShIn, DShOut, DHold, DStAd: NAT;
testName: ROPE = "EU2Test";
allOnes: LONG CARDINAL ← LOOPHOLE[LONG[-1]];
Initialize:
PROC [public: Wire] = {
Vdd ← PortIndex[public, "Vdd"];
Gnd ← PortIndex[public, "Gnd"];
PadVdd ← PortIndex[public, "PadVdd"];
PadGnd ← PortIndex[public, "PadGnd"];
PhA ← PortIndex[public, "PhA"];
PhB ← PortIndex[public, "PhB"];
VRef ← PortIndex[public, "VRef"];
DPRejectB ← PortIndex[public, "DPRejectB"];
DPData ← PortIndex[public, "DPData"];
KBus ← PortIndex[public, "KBus"];
EURes3BisPBus3AB ← PortIndex[public, "EURes3BisPBus3AB"];
EUWriteToPBus3AB ← PortIndex[public, "EUWriteToPBus3AB"];
EUAluOp2AB ← PortIndex[public, "EUAluOp2AB"];
EUCondSel2AB ← PortIndex[public, "EUCondSel2AB"];
EUCondition2B ← PortIndex[public, "EUCondition2B"];
DShA ← PortIndex[public, "DShA"];
DShB ← PortIndex[public, "DShB"];
DShRd ← PortIndex[public, "DShRd"];
DShWt ← PortIndex[public, "DShWt"];
DShIn ← PortIndex[public, "DShIn"];
DShOut ← PortIndex[public, "DShOut"];
DHold ← PortIndex[public, "DHold"];
DStAd ← PortIndex[public, "DStAd"];
};
ExerciseRose:
PUBLIC
PROC [eu2: CellType]
RETURNS [sim: Rosemary.Simulation] = {
public: Wire ← eu2.public;
Initialize[public];
[] ← Rosemary.SetFixedWire[public[Vdd], H];
[] ← Rosemary.SetFixedWire[public[Gnd], L];
[] ← Rosemary.SetFixedWire[public[PadVdd], H];
[] ← Rosemary.SetFixedWire[public[PadGnd], L];
[] ← Rosemary.SetFixedWire[public[VRef], H];
[] ← 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[EURes3BisPBus3AB], 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[DShOut], none];
[] ← Ports.InitTesterDrive[public[DHold], force];
[] ← Ports.InitPort[public[DStAd], c];
[] ← Ports.InitTesterDrive[public[DStAd], force];
sim ← RosemaryUser.TestProcedureViewer[
cellType: eu2,
testButtons: LIST[testName],
name: testName,
displayWires: RosemaryUser.DisplayCellTypePortLeafWires[eu2],
flatten: TRUE,
cutSets: LIST["AlpsCell", "EU2Ram"]];
};
EU2Test: RosemaryUser.TestProc = {
constAdr: NAT ← EU2Utils.constAdr;
junkAdr: NAT ← EU2Utils.junkAdr;
PackK:
PROC [a, b:
NAT ← constAdr,
c: NAT ← junkAdr,
st3AisC: BOOL ← FALSE,
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;
};
Phase: TYPE = {A, B};
DoPh:
PROC [ph: Phase] = {
p[PhA].b ← ph=A;
p[PhB].b ← ph=B;
Eval[];
p[DPData].d ← none;
p[PhA].b ← FALSE;
p[PhB].b ← FALSE;
Eval[ ! Ports.CheckError => RESUME];
};
LoadRam:
PROC [ad:
NAT, val:
LONG CARDINAL] ~ {
p[KBus].lc ← PackK[aluR: 3];
DoPh[B]; -- load address
p[EUAluOp2AB].c ← ORD[Dragon.ALUOps[Or]];
p[KBus].lc ← val;
DoPh[A]; -- right ← val
p[KBus].lc ← PackK[];
DoPh[B]; -- OR
p[KBus].lc ← 0;
DoPh[A]; -- PBus ← val; r3A ← val;
p[KBus].lc ← PackK[c: ad];
DoPh[B]; -- r3B ←r3A
p[KBus].lc ← 0;
DoPh[A]; -- ram[c] ← val;
};
DoubleLoadRam:
PROC [ad1, ad2:
NAT, val1, val2:
LONG CARDINAL] ~ {
p[KBus].lc ← PackK[aluR: 3];
DoPh[B]; -- load junk addresses
p[EUAluOp2AB].c ← ORD[Dragon.ALUOps[Or]];
p[KBus].lc ← val1;
DoPh[A]; -- right ← val1
p[KBus].lc ← PackK[aluR: 3];
DoPh[B]; -- OR
p[KBus].lc ← val2;
DoPh[A]; -- PBus ← val1; r3A ← val1;
p[KBus].lc ← PackK[c: ad1];
DoPh[B]; -- r3B ←r3A
p[KBus].lc ← 0;
DoPh[A]; -- ram[ad1] ← val2;
p[KBus].lc ← PackK[c: ad2];
DoPh[B]; -- r3B ←r3A
p[KBus].lc ← 0;
DoPh[A]; -- ram[ad2] ← val2;
};
DoALUOp:
PROC [a, b, res:
LONG
CARDINAL, op: Dragon.ALUOps, condSel: Dragon.CondSelects ← False, cond:
BOOL ←
FALSE] ~ {
DoubleLoadRam[0, 1, a, b];
p[KBus].lc ← PackK[a: 0, b: 1];
DoPh[B]; -- load operands addresses
p[EUAluOp2AB].c ← ORD[op];
p[KBus].lc ← 0;
DoPh[A]; -- left ← a; right ← b
p[EUCondition2B].b ← FALSE;
p[EUCondSel2AB].c ← ORD[condSel];
p[EUCondition2B].b ← cond;
p[KBus].lc ← PackK[];
DoPh[B]; -- op
p[KBus].lc ← 0;
p[DPData].lc ← res;
p[EUCondSel2AB].c ← 0;
p[EUCondition2B].b ← FALSE;
p[DPData].d ← expect;
DoPh[A]; -- PBus ← res; check PBus
};
DoFUOp:
PROC [leftW, rightW, res, mask, shift:
LONG
CARDINAL, insert:
BOOL] ~ {
fd: NAT ← ((IF insert THEN 1 ELSE 0)*64+mask)*64+shift;
LoadRam[fieldAdr, LONG[fd]]; -- field
DoubleLoadRam[0, 1, leftW, rightW]; -- ram[0]←leftW; ram[1]←rightW
p[KBus].lc ← PackK[a: 0, b: 1, aluR: 4]; -- right𡤏ield; left←leftW; st2A←rightW
DoPh[B]; -- load operand addresses
p[EUAluOp2AB].c ← ORD[Dragon.ALUOps[FOP]];
p[KBus].lc ← 0;
DoPh[A];
p[KBus].lc ← PackK[];
DoPh[B]; -- field unit is active
p[KBus].lc ← 0;
p[DPData].lc ← res;
p[DPData].d ← expect;
DoPh[A]; -- PBus ← res; check PBus
};
-- Initial values
Initialize[cellType.public];
p[DPRejectB].b ← FALSE;
p[DShA].b ← TRUE; -- hack to clean up the ShReg.
p[DShB].b ← TRUE;
p[DShRd].b ← FALSE;
p[DShWt].b ← FALSE;
p[DShIn].b ← FALSE;
p[DHold].b ← FALSE;
p[DStAd].c ← 0;
p[EUCondSel2AB].c ← 0; -- false
p[EUAluOp2AB].c ← ORD[Dragon.ALUOps[Or]];
p[EURes3BisPBus3AB].b ← FALSE; -- don't (fetch) read data from PBus
p[EUWriteToPBus3AB].b ← TRUE; -- (store) and don't write onto PBus during PhB
p[EUAluOp2AB].c ← 0; -- OR
-- Purge the pipeline
TerminalIO.WriteRope["Purging the pipe\n"];
p[DPData].d ← none;
FOR c:
NAT
IN [0..3)
DO
p[KBus].lc ← PackK[];
DoPh[B ! Ports.CheckError => RESUME; Rosemary.Stop => RESUME];
p[KBus].lc ← 0;
DoPh[A ! Ports.CheckError => RESUME; Rosemary.Stop => RESUME];
ENDLOOP;
-- Test starts here (commented out code already works)
-- Carry Test
TerminalIO.WriteRope["Testing LAdd\n"]; -- the only op which sets but doesn't use carry
DoALUOp[12, 73, 85, LAdd]; -- sets the carry to 0
TerminalIO.WriteRope["Testing SAdd\n"];
DoALUOp[12, 73, 85, SAdd]; -- uses the carry (now 0)
-- Condition Test
TerminalIO.WriteRope["Testing VSub, negative result\n"];
DoALUOp[2, 3, allOnes, VSub, LZ, TRUE];
DoALUOp[2, 2, 0, VSub, EZ, TRUE];
-- Field Unit Test
TerminalIO.WriteRope["Insert\n"];
DoFUOp[leftW: 1, rightW: 632B, res: 602B, mask: 2, shift: 6, insert: TRUE];
TerminalIO.WriteRope["Testing simple Shift\n"];
DoFUOp[leftW: 2, rightW: 1, res: 16, mask: 20, shift: 3, insert: FALSE];
TerminalIO.WriteRope["Testing simple Masking\n"];
DoFUOp[leftW: 15, rightW: 1, res: 7, mask: 3, shift: 0, insert: FALSE];
TerminalIO.WriteRope["Shift and Mask\n"];
DoFUOp[leftW: 6, rightW: allOnes, res: 23, mask: 5, shift: 3, insert: FALSE];
-- ALU Test
TerminalIO.WriteRope["Testing VAdd\n"];
DoALUOp[12, 73, 85, VAdd];
TerminalIO.WriteRope["Testing VSub\n"];
DoALUOp[47, 31, 16, VSub];
TerminalIO.WriteRope["Testing VSub, negative result\n"];
DoALUOp[2, 3, allOnes, VSub];
TerminalIO.WriteRope["Testing Or\n"];
DoALUOp[10, 3, 11, Or];
TerminalIO.WriteRope["Testing And\n"];
DoALUOp[10, 3, 2, And];
TerminalIO.WriteRope["Testing Xor\n"];
DoALUOp[10, 3, 9, Xor];
};
RosemaryUser.RegisterTestProc[testName, EU2Test];