DIRECTORY
Atom, Basics, Cache2, CacheOps, Cluster2, Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, Dragon, DragonRosemary, DragOpsCross, DragOpsCrossUtils, EU2, IFU2, IO, LizardCache, LizardHeart, Ports, Process, RandomCode, Rope, Rosemary, RosemaryUser, SparseMemory, TypeScript, ViewerClasses, ViewerIO, ViewRec;
Cluster2Impl:
CEDAR
PROGRAM
IMPORTS Atom, Cache2, CacheOps, CoreCreate, CoreOps, DragonRosemary, DragOpsCrossUtils, EU2, IFU2, IO, LizardCache, LizardHeart, Ports, Process, RandomCode, Rope, Rosemary, RosemaryUser, SparseMemory, TypeScript, ViewerIO, ViewRec
EXPORTS Cluster2 =
BEGIN OPEN Cluster2;
nCacheLines: NAT ← 200;
skipIFURejects: BOOL ← FALSE;
skipEURejects: BOOL ← FALSE;
fullEU: BOOL ← FALSE;
lastKs: KitchenSink ← NIL; -- I put this in so that you can get your hands on the kitchen sink from a new command tool. If you take it out, I may not rip your lungs out, but ...
MakeCluster:
PUBLIC
PROC
RETURNS [ks: KitchenSink] =
BEGIN
ifuRoseInst, euRoseInst, iCacheRoseInst, eCacheRoseInst: CoreClasses.CellInstance ← NIL;
DStateAddress: CoreCreate.WR ← CoreCreate.Seq["DStateAddress", 4];
publicInputNames:
LIST
OF CoreCreate.
WR ←
LIST[
"PhA", "PhB", "ResetAB", "RescheduleAB",
"Vdd", "Gnd", "PadVdd", "PadGnd",
"DExecuteAB", "DNSelectAB", "DHoldAB",
"DrShA", "DrShB", "DrShRd", "DrShWt", "DrShIn" -- IFU's debugging shifter
and implicitly the MBus --
];
publicOutputName: CoreCreate.WR ← "DrShOut"; -- IFU's debugging shifter
public: CoreCreate.Wire = CoreCreate.WireList[CONS[DStateAddress, CONS[publicOutputName, publicInputNames]]];
internal: CoreCreate.Wire = CoreCreate.WireList[
LIST[
CoreCreate.Seq["KBus", 32],
CoreCreate.Seq["EUAluOp2AB", 4],
CoreCreate.Seq["EUCondSel2AB", 4],
"EUCondition2B", "EURes3BisPBus3AB", "EUWriteToPBus3AB",
CoreCreate.Seq["IPData", 32],
CoreCreate.Seq["IPCmdA", 8],
"IPRejectB",
CoreCreate.Seq["IPFaultB", 5],
CoreCreate.Seq["DPData", 32],
CoreCreate.Seq["DPCmdA", 8],
"DPRejectB",
CoreCreate.Seq["DPFaultB",5]
]];
flatInstance: CoreFlat.FlatInstance ←
NEW[CoreFlat.FlatInstanceRec];
ks ← lastKs ←
NEW[KitchenSinkRec ← [
log: ViewerIO.CreateViewerStreams["Rosemary Cluster Simulation"].out,
vm: CacheOps.NewVirtualMemory[]
]];
TypeScript.ChangeLooks[ViewerIO.GetViewerFromStream[ks.log], 'f];
ks.iCache ← CacheOps.NewCache[mem: ks.vm, nLines: nCacheLines];
ks.eCache ← CacheOps.NewCache[mem: ks.vm, nLines: nCacheLines];
ks.coreInsts[iCache] ← CoreCreate.InstanceList[
type: Cache2.Cache[vm: ks.iCache, skipRejects: skipIFURejects],
pas:
LIST[
[public: "PData", actual: "IPData"],
["PCmdA", "IPCmdA"],
["PRejectB", "IPRejectB"],
["PFaultB", "IPFaultB"]
]
];
ks.coreInsts[eCache] ← CoreCreate.InstanceList[
type: Cache2.Cache[vm: ks.eCache, skipRejects: skipEURejects],
pas:
LIST[
[public: "PData", actual: "DPData"],
["PCmdA", "DPCmdA"],
["PRejectB", "DPRejectB"],
["PFaultB", "DPFaultB"]
]
];
ks.coreInsts[ifu] ← CoreCreate.InstanceList[
type: IFU2.
IFU[
NEW[IFU2.IFUTypeData ← [
data: ks, getLog: GetLog, checkSynch: CheckSynch, getCycle: GetCycle
]]],
pas: LIST[]
];
ks.coreInsts[eu] ← CoreCreate.InstanceList[
type: Rosemary.AddCutSets[
cellType: EU2.CreateEU2[
NEW[EU2.EUTypeData ← [
data: ks, storeNoted: FALSE, noteStore: NoteRegStore
]],
fullEU],
cs1: "TopLevel"
],
pas: LIST[]
];
ks.cluster ← CoreCreate.Cell[
public: public,
onlyInternal: internal,
instances: LIST[ks.coreInsts[ifu], ks.coreInsts[eu], ks.coreInsts[iCache], ks.coreInsts[eCache]],
name: "Cluster"
];
[] ← Rosemary.SetFixedWire[public[CoreOps.GetWireIndex[public, "Vdd"]], H];
[] ← Rosemary.SetFixedWire[public[CoreOps.GetWireIndex[public, "Gnd"]], L];
[] ← Rosemary.SetFixedWire[public[CoreOps.GetWireIndex[public, "PadVdd"]], H];
[] ← Rosemary.SetFixedWire[public[CoreOps.GetWireIndex[public, "PadGnd"]], L];
[] ← Ports.InitPort[wire: CoreCreate.FindWire[ks.cluster.public, DStateAddress], initType: c, initDrive: force];
[] ← Ports.InitPort[wire: CoreCreate.FindWire[ks.cluster.public, publicOutputName], initType: b, initDrive: none];
FOR rl:
LIST
OF CoreCreate.
WR ← publicInputNames, rl.rest
WHILE rl #
NIL
DO
[] ← Ports.InitPort[wire: CoreCreate.FindWire[ks.cluster.public, rl.first], initType: b, initDrive: force];
ENDLOOP;
ks.clusterIOPort ← Ports.CreatePort[ks.cluster.public];
ks.rosemarySimulation ← Rosemary.InstantiateInstances[
cellType: ks.cluster,
testPort: ks.clusterIOPort,
cutSets: LIST["TopLevel"]
];
FOR inst: Instances
IN Instances
DO
flatInstance.instance ← ks.coreInsts[inst];
ks.state[0].data[inst] ← Rosemary.GetInstanceState[ks.rosemarySimulation, flatInstance];
ENDLOOP;
FOR i:
NAT
IN [1..historySize)
DO
ks.state[i].data ← [
ifu: IFU2.NewIFUState[NARROW[ks.state[0].data[ifu]]],
eu: NEW[EU2.EU2StateRec],
iCache: NEW[Cache2.CacheState],
eCache: NEW[Cache2.CacheState]];
ENDLOOP;
ks.euReject ← NEW[CoreFlat.FlatWireRec];
ks.euReject.wire ← CoreCreate.FindWire[internal, "DPRejectB"];
IF fullEU
THEN {
euCellType: Core.CellType ← ks.coreInsts[eu].type;
ks.euSimulationTruthPort ← Ports.CreatePort[euCellType.public, TRUE];
ks.euSimulationTestPort ← Ports.CreatePort[euCellType.public, TRUE];
ks.euSimulation ← Rosemary.InstantiateInstances[euCellType, ks.euSimulationTestPort, LIST["AlpsCell", "EU2Ram"]];
ks.euFlatInstance ← NEW[CoreFlat.FlatInstanceRec];
ks.euFlatInstance.instance ← ks.coreInsts[eu];
ks.euDisplay ← RosemaryUser.DisplayViewer[ks.euSimulation, euCellType, "EU2", RosemaryUser.DisplayCellTypePortLeafWires[euCellType]];
Rosemary.Initialize[ks.euSimulation, FALSE];
};
StartPanel[ks];
END;
runningMsg: Core.ROPE ← "Running...";
SetPublic:
PUBLIC
PROC [ks: KitchenSink, signal:
ATOM, value:
REF
ANY ←
NIL ] =
BEGIN
WITH value
SELECT
FROM
refBool:
REF
BOOL =>
ks.clusterIOPort[CoreOps.GetWireIndex[ks.rosemarySimulation.coreCellType.public, Atom.GetPName[signal]]].b ← refBool^;
ENDCASE => ERROR;
END;
SetPublicBool:
PUBLIC
PROC [ks: KitchenSink, signal:
ATOM, value:
BOOL ] =
BEGIN
SetPublic[ks, signal, NEW[BOOL ← value]];
END;
SetPublicAndSettle:
PUBLIC PROC [ks: KitchenSink, signal:
ATOM, value:
REF ANY ← NIL ] =
BEGIN
SetPublic[ks, signal, value];
Rosemary.Settle[ ks.rosemarySimulation
!
ABORTED =>
IF ks.controlPanel.continueTestFromAbort
THEN CONTINUE ELSE REJECT;
];
ks.controlPanel.continueTestFromAbort ← FALSE;
END;
GetPublicBool:
PUBLIC PROC [ks: KitchenSink, signal:
ATOM]
RETURNS [value:
BOOL] =
{value ← ks.clusterIOPort[CoreOps.GetWireIndex[ks.rosemarySimulation.coreCellType.public, Atom.GetPName[signal]]].b};
DoCluster:
PUBLIC
PROC [ks: KitchenSink, diagnostic: Core.
ROPE ←
NIL] =
BEGIN
originalPriority: Process.Priority = Process.GetPriority[];
diagnosticName: Core.ROPE ← "unknown";
{
ENABLE
UNWIND => {
ks.log.PutF["\nSimulation of %g aborted\n\n", IO.rope[diagnosticName]];
ks.log.Flush[];
Process.SetPriority[ originalPriority ] };
DoEval:
PROC = {
ks.controlPanel.continueTestFromAbort ← FALSE;
IF GetPublicBool[ks, $PhA]
THEN {
SetPublicBool[ks, $RescheduleAB, ks.controlPanel.resched];
SetPublicBool[ks, $ResetAB, ks.controlPanel.reset];
};
Rosemary.Settle[ ks.rosemarySimulation
!
ABORTED =>
IF ks.controlPanel.continueTestFromAbort
THEN CONTINUE ELSE REJECT;
];
IF fullEU
THEN {
Rosemary.SettleToTest[simulation: ks.rosemarySimulation, instance: ks.euFlatInstance, test: ks.euSimulationTruthPort];
Ports.CopyPortValue[from: ks.euSimulationTruthPort, to: ks.euSimulationTestPort];
Rosemary.Settle[ks.euSimulation ! Rosemary.Stop => IF ks.euCyclesFromReject>0 AND data = $BoolWireHasX THEN RESUME ELSE {RosemaryUser.UpdateDisplay[ks.euDisplay]; REJECT}];
RosemaryUser.UpdateDisplay[ks.euDisplay];
Ports.CheckPortValue[root: ks.coreInsts[eu].type.public, truth: ks.euSimulationTruthPort, question: ks.euSimulationTestPort];
};
IF ks.controlPanel.reset THEN ks.controlPanel.instrCount ← -1;
Process.Yield[];
ks.controlPanel.continueTestFromAbort ← FALSE
};
Cycles:
PROC [ n:
INT ] =
{FOR i: INT IN [0..n) DO DoPh[a]; DoPh[b] ENDLOOP};
Remark:
PROC [explan: Core.
ROPE] = {
ks.controlPanel.msg ← explan;
ks.controlPanel.running ← FALSE;
DoEval[];
UNTIL ks.controlPanel.running DO Process.Pause[Process.MsecToTicks[1000]] ENDLOOP;
ks.controlPanel.msg ← runningMsg;
DoEval[];
};
DoPh:
PROC [ ph: Dragon.Phase ] = {
first: BOOL ← TRUE;
ks.controlPanel.phase ← ph;
WHILE first
OR ks.controlPanel.repeatPhase
DO
SetPublicBool[ks, $PhB, ph=b];
SetPublicBool[ks, $PhA, ph=a];
IF ks.controlPanel.running
THEN {
ks.controlPanel.msg ← runningMsg;
DoEval[];
}
ELSE Remark[(IF ks.controlPanel.msg = runningMsg THEN "Simulation manually suspended..." ELSE ks.controlPanel.msg)];
IF first
THEN {
IF (ks.controlPanel.cycle >= ks.controlPanel.slowFromCycle
OR
(ks.controlPanel.cycle>=0
AND ks.controlPanel.instrCount >= ks.controlPanel.slowFromInstr))
AND
ks.controlPanel.stopInPh[ph] THEN
Remark[
IO.PutFR["Doing cycle %g Ph%g...",
IO.int[ks.controlPanel.cycle], IO.char[IF ph=a THEN 'A ELSE 'B]]];
}
ELSE Remark[
IO.PutFR["...repeating cycle %g Ph%g..",
IO.int[ks.controlPanel.cycle], IO.char[IF ph=a THEN 'A ELSE 'B]]];
IF first
THEN {
-- cycle the history buffer
s: ClusterState ← ks.state[historySize-1];
FOR i:
NAT
DECREASING
IN (1..historySize)
DO
ks.state[i] ← ks.state[i-1];
ENDLOOP;
s.cycle ← ks.controlPanel.cycle;
s.phase ← ks.controlPanel.phase;
NARROW[s.data[ifu], REF IFU2.IFUState]^ ← NARROW[ks.state[0].data[ifu], REF IFU2.IFUState]^;
NARROW[s.data[eu], REF EU2.EU2StateRec]^ ← NARROW[ks.state[0].data[eu], REF EU2.EU2StateRec]^;
NARROW[s.data[iCache], REF Cache2.CacheState]^ ← NARROW[ks.state[0].data[iCache], REF Cache2.CacheState]^;
NARROW[s.data[eCache], REF Cache2.CacheState]^ ← NARROW[ks.state[0].data[eCache], REF Cache2.CacheState]^;
ks.state[1] ← s;
first ← FALSE;
};
SetPublicBool[ks, $PhB, FALSE];
SetPublicBool[ks, $PhA, FALSE];
DoEval[];
ENDLOOP;
ks.euCyclesFromReject ←
SELECT
TRUE
FROM
ks.controlPanel.reset => 3,
ph=a OR Rosemary.WireValue[simulation: ks.rosemarySimulation, wire: ks.euReject][0]=H => ks.euCyclesFromReject,
ks.euCyclesFromReject>0 => ks.euCyclesFromReject-1,
ENDCASE => 0;
};
Main body of Inner
Process.SetPriority[ Process.priorityBackground ];
ks.diagnostics ← IF diagnostic=NIL THEN "test end" ELSE diagnostic;
ks.controlPanel.diagnostic ← ks.diagnostics;
ks.controlPanel.running ← TRUE;
DO
-- over all diagnostics
Chop:
PROC
RETURNS [ first, rest: Rope.
ROPE ←
NIL ] =
BEGIN
dStream: IO.STREAM = IO.RIS[ks.controlPanel.diagnostic];
first ← dStream.GetTokenRope[IO.IDProc ! IO.EndOfStream => CONTINUE].token;
rest ← ks.controlPanel.diagnostic.Substr[dStream.GetIndex];
END;
diagnosticFileName: Core.ROPE ← diagnosticName ← Chop[].first;
IF Rope.Length[diagnosticFileName] = 0
OR
(Rope.Equal[s1: diagnosticFileName, s2: "END", case:
FALSE]
AND
ks.controlPanel.randomSeed=0)
THEN EXIT;
ks.controlPanel.reset ← TRUE;
WHILE ks.controlPanel.reset
DO
-- as often as RESET is asserted in the same diagnostic
ks.controlPanel.stopInPh ← ALL[TRUE];
ks.controlPanel.repeatPhase ← ks.controlPanel.resched ← FALSE;
ks.controlPanel.cycle ← -1;
ks.controlPanel.instrCount ← -1;
{
public: Core.Wire ← ks.cluster.public;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DExecuteAB"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DNSelectAB"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DHoldAB"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DStateAddress"]].c ← 0;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DrShA"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DrShB"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DrShRd"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DrShWt"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DrShIn"]].b ← FALSE;
};
FOR j:
NAT
IN [0..3)
DO
DoPh[a !
DragonRosemary.AssertionFailed => RESUME;
Rosemary.Stop => IF data = $FailedAssertion OR data = $BoolWireHasX THEN RESUME ELSE REJECT;
IFU2.IFUInconsistent => CONTINUE
];
DoPh[b !
DragonRosemary.AssertionFailed => RESUME;
Rosemary.Stop => IF data = $FailedAssertion OR data = $BoolWireHasX THEN RESUME ELSE REJECT;
IFU2.IFUInconsistent => CONTINUE
];
ENDLOOP;
Cycles[2];
SELECT TRUE FROM
diagnosticFileName #
NIL =>
BEGIN
CacheOps.VirtualMemoryFromFile[ks.vm, diagnosticFileName ];
ks.lizardSimulation ← (IF ks.controlPanel.lizardToo THEN StartNewLizard[ks.vm] ELSE NIL);
END;
ks.controlPanel.randomSeed#0 =>
BEGIN
diagnosticName ← IO.PutFR["random code (seed = %d)", IO.int[ks.controlPanel.randomSeed]];
InsertRandomProgramInVM[ks];
ks.lizardSimulation ← (IF ks.controlPanel.lizardToo THEN StartNewLizard[ks.vm] ELSE NIL);
END;
ks.controlPanel.reset ← FALSE;
DoPh[a];
IF ks.controlPanel.reset THEN LOOP; -- restart this diagnostic
DoPh[b];
IF ks.controlPanel.reset THEN LOOP; -- restart this diagnostic
IF ks.controlPanel.slowFromCycle<=0 THEN Remark["Processor has been reset..."];
ks.controlPanel.cycle ← 0;
ks.rosemaryStores ← NIL;
ks.log.PutF["\n\n\n%g Dragon Rosemary simulation of %g beginning...\n\n",
IO.time[],
IO.rope[diagnosticName]];
WHILE ks.controlPanel.randomSeed=0
OR ks.controlPanel.cycle<=ks.controlPanel.randomCycleLimit
DO
ENABLE {
SuccessHalt => {
ks.log.PutF["\n%g Success XOP in %g at instruction %d, cycle %d.\n\n",
IO.time[],
IO.rope[diagnosticName],
IO.int[ks.controlPanel.instrCount],
IO.int[ks.controlPanel.cycle]];
EXIT;
};
Breakpoint => {
ks.log.PutF["\n%g Breakpoint XOP in %g at instruction %d, cycle %d.\n\n",
IO.time[],
IO.rope[diagnosticName],
IO.int[ks.controlPanel.instrCount],
IO.int[ks.controlPanel.cycle]];
SELECT
TRUE
FROM
ks.controlPanel.emulateBreakpoint => RESUME;
diagnosticFileName # NIL => REJECT;
ENDCASE => EXIT;
};
};
DoPh[a];
IF ks.controlPanel.reset THEN EXIT; -- restart this diagnostic
DoPh[b];
IF ks.controlPanel.reset
THEN
EXIT;
-- restart this diagnostic
ks.controlPanel.cycle ← ks.controlPanel.cycle+1;
ENDLOOP; -- on ks.controlPanel.cycle
ENDLOOP; -- on a single diagnostic
SELECT
TRUE
FROM
diagnosticFileName #
NIL =>
BEGIN
first, rest: Rope.ROPE;
[first, rest] ← Chop[];
IF first.Equal[diagnosticFileName]
THEN
ks.controlPanel.diagnostic ← Rope.Cat[rest, " ",first];
END;
ks.controlPanel.randomSeed # 0 =>
ks.controlPanel.randomSeed ← ks.controlPanel.randomSeed+1;
ENDCASE => NULL;
ENDLOOP; -- on ks.diagnostic or ks.controlPanel.randomSeed
}; -- for catching UNWIND
Process.SetPriority[ originalPriority ];
END;
GetLog:
PROC [ data: OpaqueKitchenSink ]
RETURNS [ Core.
STREAM ] =
BEGIN
ks: KitchenSink = NARROW[data];
RETURN [ ks.log ];
END;
GetCycle:
PROC [ data: OpaqueKitchenSink ]
RETURNS [ cycle:
INT ] =
BEGIN
ks: KitchenSink = NARROW[data];
RETURN [ ks.controlPanel.cycle ];
END;
NoteRegStore:
PROC [ data:
REF
ANY, reg: [0..256), value: Dragon.Word ]
-- EU2.NoteRegStoreProc -- =
BEGIN
ks: KitchenSink = NARROW[data];
ks.rosemaryStores ← CONS[NEW[Dragon.RegStoreRec ← [instr: ks.controlPanel.instrCount, reg: VAL[reg], data: value]], ks.rosemaryStores];
END;
randomStartPC: Dragon.Word ← 102000H;
randomBackground: Core.ROPE ← "RandomBackground.quad";
InsertRandomProgramInVM: PROC[ ks: KitchenSink ] = {
WriteOneCodeByte:
PROC [byte: [0..255]] =
BEGIN
background: Basics.LongNumber;
CacheOps.SetFlags[c: ks.eCache, address: nextByteAddr/4, mapped: TRUE, writeProtect: FALSE, dirty: FALSE];
background.lc ← CacheOps.Access[c: ks.eCache, address: nextByteAddr/4].data;
SELECT nextByteAddr
MOD 4
FROM
0 => background.hh ← byte;
1 => background.hl ← byte;
2 => background.lh ← byte;
3 => background.ll ← byte;
ENDCASE => ERROR;
CacheOps.Write[c: ks.eCache, address: nextByteAddr/4, data: background.lc];
nextByteAddr ← nextByteAddr+1;
END;
nextByteAddr: Dragon.Word ← randomStartPC;
CacheOps.VirtualMemoryFromFile[ks.vm, randomBackground];
RandomCode.GenerateRandomProgramBytes[
initialByteAddress: randomStartPC,
randomSeed: ks.controlPanel.randomSeed,
seeOneByte: WriteOneCodeByte,
dribble: ks.log
];
ks.eCache ← CacheOps.NewCache[ks.eCache]; -- resets first free cycle, cache lines
};
LizardEUCacheFetchTrap:
PROC [base: LizardCache.CacheBase, addr: LizardCache.Word, cycle:
INT, noEffect:
BOOL ←
FALSE]
RETURNS [data: LizardCache.Word, status: LizardCache.TrapIndex, rejectCycles:
INT]
-- Lizard.CacheFetchProc -- =
BEGIN
sim: LizardSimulation = NARROW[base.data];
[data: data, status: status, rejectCycles: rejectCycles] ←
sim.euCache.fetch[base: sim.euCache, addr: addr, cycle: cycle, noEffect: noEffect];
sim.lastInstrOps ←
CONS[
NEW[Dragon.CacheTransRec ← [
instr: sim.processor.stats.instructions,
cmd: Fetch, -- might be FetchHold, we can't tell here
addr: DragOpsCrossUtils.WordToCard[addr],
data: DragOpsCrossUtils.WordToCard[data],
fault:
SELECT status
FROM
ALUCondFalse => none,
EUPageFault => page,
EUWriteFault => write,
ENDCASE => ERROR
]],
sim.lastInstrOps];
END;
LizardEUCacheStoreTrap: PROC [base: LizardCache.CacheBase, addr: LizardCache.Word, data: LizardCache.Word, cycle: INT]
RETURNS [old: LizardCache.Word, status: LizardCache.TrapIndex, rejectCycles:
INT]
-- Lizard.CacheStoreProc -- =
BEGIN
sim: LizardSimulation = NARROW[base.data];
[old: old, status: status, rejectCycles: rejectCycles] ←
sim.euCache.store[base: sim.euCache, addr: addr, data: data, cycle: cycle];
sim.lastInstrOps ←
CONS[
NEW[Dragon.CacheTransRec ← [
instr: sim.processor.stats.instructions,
cmd: Store,
addr: DragOpsCrossUtils.WordToCard[addr],
data: DragOpsCrossUtils.WordToCard[data],
fault:
SELECT status
FROM
ALUCondFalse => none,
EUPageFault => page,
EUWriteFault => write,
ENDCASE => ERROR
]],
sim.lastInstrOps];
END;
NoteChangedReg:
PROC [data:
REF, processor: LizardHeart.Processor, reg: DragOpsCross.ProcessorRegister, old,new: DragOpsCross.Word]
-- LizardHeart.RegChangeProc -- =
BEGIN
sim: LizardSimulation = NARROW[data];
sim.lastInstrOps ←
CONS[
NEW[Dragon.RegStoreRec ← [
instr: sim.processor.stats.instructions,
reg: reg,
data: DragOpsCrossUtils.WordToCard[new]
]],
sim.lastInstrOps];
END;
NoteInstDone:
PROC [data:
REF, processor: LizardHeart.Processor, newPC, rtnPC: DragOpsCross.Word, control: LizardHeart.Control, cycles:
INT]
-- LizardHeart.InstDoneProc -- =
BEGIN
sim: LizardSimulation = NARROW[data];
sim.control ← control;
END;
StartNewLizard:
PUBLIC
PROC [ m:
REF
-- CacheOps.VM -- ]
RETURNS [ sim: LizardSimulation ] =
BEGIN
StoreWord:
PROC [ addr, data: Dragon.Word, readOnly, dirty:
BOOL ←
FALSE, privateData:
REF ←
NIL ] =
{SparseMemory.Store[base: lizardVM, index: DragOpsCrossUtils.CardToWord[addr], new: DragOpsCrossUtils.CardToWord[data]]};
lizardVM: SparseMemory.Base;
lizardSharedVM: LizardCache.SharedBase;
sim ← NEW[LizardSimulationRec];
lizardVM ← SparseMemory.Create[];
lizardSharedVM ← LizardCache.NewBase[lizardVM];
CacheOps.EnumerateVirtualMemory[m, StoreWord]; -- initialize Lizard's memory
sim.euCache ← LizardCache.NewCache[lizardSharedVM];
sim.processor ← LizardHeart.NewProcessor[
ifuCache: LizardCache.NewCache[lizardSharedVM],
euCache:
NEW[LizardCache.CacheBaseRep ← [
fetch: LizardEUCacheFetchTrap,
store: LizardEUCacheStoreTrap,
data: sim
]],
logger:
NEW[LizardHeart.ChangeLoggerRep ← [
data: sim,
regChange: NoteChangedReg,
instDone: NoteInstDone
]]
];
END;
SuccessHalt: PUBLIC ERROR = CODE;
Breakpoint: PUBLIC SIGNAL = CODE;
CheckSynch:
PUBLIC
PROC [ data: OpaqueKitchenSink, basicInst: IFU2.BasicInst ]
RETURNS [deltaInstrCount:
INT ← 1]
-- IFU2.CheckSynchProc -- =
BEGIN
retry: BOOL ← TRUE;
WHILE retry
DO
retry ← FALSE;
deltaInstrCount ← csProcRec.proc[data: data, basicInst: basicInst ]; -- debugger might set retry to TRUE
NULL; -- for breakpoints and what-have-you
ENDLOOP;
END;
DefaultCheckSynch:
PUBLIC IFU2.CheckSynchProc =
{RETURN[1]};
csProcRec: PUBLIC CSProcRec ← [DefaultCheckSynch];
StartPanel:
PROC [ks: KitchenSink] = {
IF ks.controlPanel =
NIL
THEN {
ks.controlPanel ←
NEW[ControlPanelRec ← [
msg: "Initialized...",
enaIFULog: TRUE,
diagnostic: ks.diagnostics
]];
ViewRec.SetBehavior[newBehavior: [delayParms: [min: 2000.0]]];
[] ← ViewRec.ViewRef[
agg: ks.controlPanel,
label: "Dragon Cluster2 Rosemary5 Control Panel", specs:
LIST[
["cycle", Value[val:NIL, visible:TRUE, dontAssign:TRUE]],
["phase", Value[val:NIL, visible:TRUE, dontAssign:TRUE]],
["instrCount", Value[val:NIL, visible:TRUE, dontAssign:TRUE]]
]];
};
END.}