LizardRosemaryCheckSynchImpl.mesa
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by McCreight, April 7, 1986 4:45:29 pm PST
Herrmann, September 5, 1985 10:53:41 am PDT
Curry, September 11, 1986 1:26:58 am PDT
Don Curry March 31, 1987 9:15:15 pm PST
Last Edited by: Louis Monier April 7, 1987 1:17:46 pm PST
DIRECTORY
Cluster, Dragon, DragonRosemary, DragOpsCross, DragOpsCrossUtils, IFUTop, LizardHeart;
LizardRosemaryCheckSynchImpl: CEDAR PROGRAM
IMPORTS Cluster, DragonRosemary, DragOpsCrossUtils, LizardHeart =
BEGIN
CSynch: PROC [ data: REF ANY, basicInst: IFUTop.BasicInst ] RETURNS [deltaInstrCount: INT ← 1] -- IFUTop.CheckSynchProc -- =
BEGIN
CheckAInB: PROC [ a, b: REF ANY ] =
BEGIN
FOR la: LIST OF REF ANYNARROW[a, LIST OF REF ANY], la.rest WHILE la#NIL DO
WITH la.first SELECT FROM
rsa: Dragon.RegStore => {
IF rsa.instr<basicInst.instr THEN EXIT; -- ancient history
SELECT rsa.reg FROM
euJunk, euToKBus, IN [euBogus..ifuLast] => LOOP;
euMAR => LOOP; -- haven't quite got this synchronized yet
ENDCASE => -- look for it in the other list
FOR lb: LIST OF REF ANYNARROW[b, LIST OF REF ANY], lb.rest DO
IF lb = NIL THEN GOTO NotFound;
WITH lb.first SELECT FROM
rsb: Dragon.RegStore => {
IF rsb.instr<rsa.instr THEN GOTO NotFound;
IF rsb.instr=rsa.instr AND rsb.reg=rsa.reg THEN {
IF rsb.data#rsa.data THEN GOTO NotFound ELSE EXIT;
};
};
ctb: Dragon.CacheTrans =>
IF ctb.instr<basicInst.instr THEN GOTO NotFound;
ENDCASE => NULL;
REPEAT
NotFound=> DragonRosemary.Assert[FALSE,
"Cluster & Rosemary disagree on register store"];
ENDLOOP;
};
cta: Dragon.CacheTrans =>
IF cta.instr<basicInst.instr THEN EXIT;
ENDCASE => NULL;
ENDLOOP;
END; -- of CheckAInB
ks: Cluster.KitchenSink = NARROW[data];
sim: Cluster.LizardSimulation = ks.lizardSimulation;
IF (NOT ks.controlPanel.reset) THEN {
Rosemary instruction number basicInst.instr has finished, for better or worse.
IF basicInst.trapped THEN deltaInstrCount ← 0;
SELECT basicInst.trapPC FROM
reschedulePC => { -- Get Lizard to Reschedule on the next instruction
ERROR;
status: DragOpsCross.IFUStatusRec ← LOOPHOLE[sim.processor.regs[ifuStatus]];
status.reschedule ← TRUE;
sim.processor.regs[ifuStatus] ← LOOPHOLE[status];
deltaInstrCount ← 0; -- Lizard doesn't generate a trapped instruction for Reschedule
};
ENDCASE => {
IF basicInst.instr >= 0 THEN {
IF sim # NIL THEN {
Get Lizard to do the same instruction, and then compare them.
lizardNewPC: Dragon.Word ←
DragOpsCrossUtils.WordToCard[sim.processor.regs[ifuPC]];
DragonRosemary.Assert[ sim.processor.stats.instructions = basicInst.instr ,
"Cluster & Lizard instruction counts disagree"];
DragonRosemary.Assert[ lizardNewPC = basicInst.pc ,
"Cluster & Lizard PC's disagree"];
LizardHeart.InstructionExecute[sim.processor];
IF basicInst.trapped AND basicInst.trapPC = ifuPageFaultPC THEN
{ -- "execute" the Lizard instruction that causes the page fault
oldStatus: Dragon.RegStore;
LizardHeart.InstructionExecute[sim.processor]; -- the faulting instruction
deltaInstrCount ← 1;
oldStatus ← NARROW[sim.lastInstrOps.first];
};
DragonRosemary.Assert[oldStatus.instr = sim.processor.stats.instructions,
"Couldn't find Lizard's save of processor status for IFU page fault"]};
CheckAInB[a: ks.rosemaryStores, b: sim.lastInstrOps];
CheckAInB[a: sim.lastInstrOps, b: ks.rosemaryStores];
IF basicInst.op=dKFC
THEN deltaInstrCount𡤀 --
ELSE DragonRosemary.Assert[(sim.control=doAbort) = (basicInst.trapped),
"Cluster & Lizard disagree about trap"];
}; -- end of Lizard check
IF basicInst.op = x377b AND basicInst.alpha = 0FFH AND basicInst.beta = 0FFH
THEN Cluster.SetSuccessHalt[TRUE]
ELSE IF (basicInst.op = x000b) OR (basicInst.op = x377b)
THEN SIGNAL Cluster.Breakpoint} };
ks.controlPanel.instrCount ← basicInst.instr+deltaInstrCount;
};
END;
reschedulePC: Dragon.HexWord = DragOpsCrossUtils.TrapIndexToBytePC[RescheduleTrap];
ifuPageFaultPC: Dragon.HexWord = DragOpsCrossUtils.TrapIndexToBytePC[IFUPageFaultTrap];
Cluster.csProcRec.proc ← CSynch;
END.