EUTestExerciseEveryBlock: RoseTypes.CellTestProc =
BEGIN
instructions: EUIORef ← NARROW[io];
drive: EUDriveRef ← NARROW[driveAsAny];
initPattern: LONG CARDINAL ← 0H;
PackAddress:
PROC[a, b, c: DragOpsCross.ProcessorRegister]
RETURNS[k: BitDWord] = {
--
for EU RAM mux
k ← ICID[Dragon.PRtoByte[a], k, 32, 0, 8];
k ← ICID[Dragon.PRtoByte[b], k, 32, 8, 8];
k ← ICID[Dragon.PRtoByte[c], k, 32, 16, 8];
};
PhAUp: PROC = {PhA ← TRUE; nPhA ← FALSE; [] ← RoseRun.Eval[handle]};
PhADown: PROC = {PhA ← FALSE; nPhA ← TRUE; [] ← RoseRun.Eval[handle]};
PhBUp: PROC = {PhB ← TRUE; nPhB ← FALSE; [] ← RoseRun.Eval[handle]};
PhBDown: PROC = {PhB ← FALSE; nPhB ← TRUE; [] ← RoseRun.Eval[handle]};
Ground Rules:
Every PhA: ALU reads 2 words from RAM
Every PhB: IFU puts an address on the KBus
for KBus:
Phase A: Data moves on KBus
Phase B: RAM addresses get muxed
for PBus:
Phase A: Addr -> Cache/data -> FPU
Phase B: Data <-> Cache/FPU
NullCycles:
PROC [n:
NAT] = {
THROUGH [0..n)
DO
PhAUp[]; PhADown[];
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhBUp[]; PhBDown[];
ENDLOOP;
};
Reset:
PROC = {
-- Homing sequence
drive.s[MHold] ← drive.s[MnReset] ← Ignore; -- set tri-state driver "strength" = 0
drive.s[DDataOut] ← Ignore;
drive.s[EPData] ← Ignore;
drive.s[EUCondition2BA] ← Ignore;
drive.s[KBus] ← Ignore;
NullCycles[5];
-- Timing & power up
PhA ← FALSE; nPhA ← TRUE; PhB ← FALSE; nPhB ← TRUE;
drive.s[PhA] ← drive.s[nPhA] ← drive.s[PhB] ← drive.s[nPhB] ← Drive;
Vdd ← TRUE; Gnd ← FALSE; PadVdd ← TRUE; PadGnd ← FALSE;
drive.s[Vdd] ← drive.s[Gnd] ← drive.s[PadVdd] ← drive.s[PadGnd] ← Drive;
-- MBus/ main memory
MHold ← FALSE; -- driver "level" = 0
MnReset ← TRUE; -- driver "level" = 1
drive.s[MHold] ← drive.s[MnReset] ← Drive; -- driver "strength" = 1
-- DBus
DShift ← DExecute ← DDataIn ← DNSelect ← FALSE;
drive.s[DShift] ← drive.s[DExecute] ← drive.s[DDataIn] ← drive.s[DNSelect] ← Drive;
drive.s[DDataOut] ← Ignore;
-- PBus <-> Cache/FPU
EPData ← BitDWordZero;
drive.s[EPData] ← Ignore;
EPFaultB ← Dragon.None;
drive.s[EPFaultB] ← Drive;
EPParityB ← EPRejectB ← FALSE;
drive.s[EPParityB] ← drive.s[EPRejectB] ← Drive;
EPNPErrorB ← TRUE;
drive.s[EPNPErrorB] ← Drive;
-- KBus <-> IFU
KBus ← PackAddress[euConstant, euConstant, euJunk];
drive.s[KBus] ← Drive;
EUAluLeftSrc1BA ← aBus; drive.s[EUAluLeftSrc1BA] ← Drive;
EUAluRightSrc1BA ← bBus; drive.s[EUAluRightSrc1BA] ← Drive;
EUStore2ASrc1BA ← bBus; drive.s[EUStore2ASrc1BA] ← Drive;
EUAluOp2AB ← Or; drive.s[EUAluOp2AB] ← Drive;
EUCondSel2AB ← False; drive.s[EUCondSel2AB] ← Drive;
EURes3AisCBus2BA ← FALSE; drive.s[EURes3AisCBus2BA] ← Drive;
EUSt3AisCBus2BA ← FALSE; drive.s[EUSt3AisCBus2BA] ← Drive;
EURes3BisPBus3AB ← FALSE; drive.s[EURes3BisPBus3AB] ← Drive;
EUCheckParity3AB ← FALSE; drive.s[EUCheckParity3AB] ← Drive;
EUWriteToPBus3AB ← FALSE; drive.s[EUWriteToPBus3AB] ← Drive;
drive.s[EUCondition2BA] ← Ignore;
};
GeneratePattern: PROC [data: LONG CARDINAL, shift: INTEGER] RETURNS [bits: LONG CARDINAL] = {
-- Use BitOps interface for twiddling bits
--newLowWord: WORD ← BITSHIFT[lowWord, shift];
--bits ← BITOR[highWord, newLowWord];
bits ← 00000001H
};
WriteRAM:
PROC [address:
CARDINAL, data:
LONG
CARDINAL] = {
d: BitDWord ← ILID[data, BitDWordZero, 32, 0, 32];
PhAUp[]; PhADown[]; -- phase A pulse; level 1
-- IFU stimulates KBus control signal to setup rightOp2AB (1 phase in advance)
EUAluRightSrc1BA ← kBus; -- latches on PhB; stable on PhA
PhBUp[]; PhBDown[]; -- phase B pulse; level 1
-- IFU puts data word on KBus
KBus ← d; -- will latch in next phase
PhAUp[]; PhADown[]; -- level 2
EUAluRightSrc1BA ← bBus; -- to rightOp2AB OR-ed with euConst = 0 in ALU
-- IFU puts address on KBus (simulation uses junk address)
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhBUp[]; PhBDown[];
PhAUp[]; PhADown[]; -- level 3
-- IFU puts valid cAddr on KBus (for write into RAM)
KBus ← PackAddress[euConstant, euConstant, LOOPHOLE[address]];
PhBUp[]; PhBDown[];
PhAUp[]; --write into RAM takes place here; level 1 again
PhADown[];
-- IFU addressing KBus period ( (using junk addr)
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhBUp[]; PhBDown[];
};
ReadRAM:
PROC [address:
CARDINAL, expectedData:
LONG
CARDINAL] = {
PhAUp[]; PhADown[]; -- level 1
-- IFU puts valid aAddr on KBus (for read from RAM)
KBus ← PackAddress[LOOPHOLE[address], euConstant, euJunk];
PhBUp[]; PhBDown[];
-- IFU stimulates KBus
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhAUp[]; PhADown[]; -- level 2
PhBUp[]; PhBDown[];
-- Move data onto PBus(of Cache)
EPData ← ILID[expectedData, BitDWordZero, 32, 0, 32]; -- BitOps.InsertLongInDouble
drive.s[EPData] ← Test; -- acquired by simulator for comparison
PhAUp[]; -- level 3
drive.s[EPData] ← Ignore; -- tri-state driver between edges; prior to next Eval
PhADown[];
PhBUp[]; PhBDown[];
};
IFURegisterOp:
PROC [address, ifuReg:
CARDINAL, expectedData:
LONG
CARDINAL] = {
PhAUp[]; PhADown[]; -- 1
KBus ← PackAddress[LOOPHOLE[address], euConstant, euJunk]; -- get data out of RAM
PhBUp[]; PhBDown[];
PhAUp[]; PhADown[]; -- 2
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhBUp[]; PhBDown[];
PhAUp[]; PhADown[]; -- 3
KBus ← PackAddress[euConstant, euConstant, LOOPHOLE[ifuReg]];
PhBUp[]; PhBDown[];
KBus ← ILID[expectedData, BitDWordZero, 32, 0, 32]; -- put data on KBus - > IFU
drive.s[KBus] ← Test;
PhAUp[]; -- 4
drive.s[KBus] ← Ignore; -- tri-state the driver
PhADown[];
KBus ← PackAddress[euConstant, euConstant, euJunk]; -- overwrite data on the bus
drive.s[KBus] ← Drive;
PhBUp[]; PhBDown[];
};
CacheReject:
PROC = {
EPRejectB ← TRUE;
drive.s[EPRejectB] ← Drive;
};
CachePageFault:
PROC = {
EPFaultB ← Dragon.Page; -- FPlsInfE
drive.s[EPFaultB] ← Drive;
};
ExerciseStack:
PROC [fromReg, toReg:
CARDINAL, data, eData:
LONG
CARDINAL] = {
IF NOT(fromReg IN [0..128)) OR NOT(toReg IN [0..128)) THEN ERROR;
FOR addr:
CARDINAL
IN [fromReg..toReg)
DO
WriteRAM[address: addr, data: data];
ReadRAM[address: addr, expectedData: eData];
ENDLOOP;
};
ExerciseIStack:
PROC [fromReg, toReg:
CARDINAL, data, eData:
LONG
CARDINAL] = {
addr: CARDINAL ← 0;
IF NOT(fromReg IN [240..255]) OR NOT(toReg IN [240..255]) THEN ERROR;
FOR cAddr:
CARDINAL
IN [fromReg..toReg]
DO
WriteRAM[address: addr, data: data];
IFURegisterOp[address: addr, ifuReg: cAddr, expectedData: eData];
ENDLOOP;
};
ExerciseCacheExceptions:
PROC [fault: Dragon.PBusFaults] = {
ramAddr: CARDINAL ← 0;
requestAddr: LONG CARDINAL ← 10101010H;
IF fault = Dragon.None THEN RETURN;
WriteRAM[address: ramAddr, data: requestAddr];
-- read operation puts data on PBus
THROUGH [0..5)
DO
IF EPRejectB THEN EXIT;
PhAUp[]; PhADown[]; -- 1
KBus ← PackAddress[LOOPHOLE[ramAddr], euConstant, euJunk];
PhBUp[]; PhBDown[];
PhAUp[]; PhADown[]; -- 2
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhBUp[]; PhBDown[];
EPData ← ILID[requestAddr, BitDWordZero, 32, 0, 32];
drive.s[EPData] ← Test;
PhAUp[]; -- 3
drive.s[EPData] ← Ignore;
PhADown[];
CacheReject[]; -- "wait"; received during PhB
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhBUp[]; PhBDown[];
ENDLOOP;
IF fault = Dragon.Page THEN CachePageFault[];
PhAUp[]; PhADown[];
KBus ← PackAddress[euConstant, euConstant, euJunk];
PhBUp[]; PhBDown[];
NullCycles[5];
};
Reset[];
FOR shift: INTEGER IN [0..2) DO
bitPattern ← GeneratePattern[data: initPattern, shift: shift];
ExerciseStack[fromReg: 0, toReg: 127, data: bitPattern, eData: bitPattern];
ENDLOOP;
Reset[];
FOR shift: INTEGER IN [0..2) DO
bitPattern ← GeneratePattern[data: initPattern, shift: shift];
ExerciseIStack[fromReg: 240, toReg: 255, data: bitPattern, eData: bitPattern];
Reset[];
ExerciseCacheExceptions[Dragon.Page];
END;