DIRECTORY
Atom, Basics, Cache2, CacheOps, Cluster2, Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, Dragon, DragonRosemary, DragOpsCross, DragOpsCrossUtils, EU2, FileNames, IFU2, IFUTest, IO, LizardCache, LizardHeart, Ports, Process, RandomCode, Rope, Rosemary, RosemaryUser, SparseMemory, TerminalIO, TypeScript, ViewerClasses, ViewerIO, ViewRec;
Cluster2Impl:
CEDAR
PROGRAM
IMPORTS Atom, Cache2, CacheOps, CoreCreate, CoreFlat, CoreOps, DragonRosemary, DragOpsCrossUtils, EU2, FileNames, IFU2, IFUTest, IO, LizardCache, LizardHeart, Ports, Process, RandomCode, Rope, Rosemary, RosemaryUser, SparseMemory, TerminalIO, TypeScript, ViewerIO, ViewRec
EXPORTS Cluster2 =
BEGIN
KitchenSink: TYPE = Cluster2.KitchenSink;
OpaqueKitchenSink: TYPE = Cluster2.OpaqueKitchenSink;
LizardSimulation: TYPE = Cluster2.LizardSimulation;
Instances: TYPE = Cluster2.Instances;
ClusterState: TYPE = Cluster2.ClusterState;
IFUState: TYPE = IFU2.IFUState;
EUState: TYPE = EU2.EU2State;
CacheSt: TYPE = REF Cache2.CacheState;
nCacheLines: PUBLIC NAT ← 200;
skipIFURejects: PUBLIC BOOL ← FALSE;
skipEURejects: PUBLIC BOOL ← FALSE;
fullEU: PUBLIC BOOL ← FALSE;
fullIFU: PUBLIC BOOL ← FALSE;
fullIFUCuts: PUBLIC LIST OF Core.ROPE ← NIL;
quickIFU: PUBLIC BOOL ← FALSE;
lastKs:
PUBLIC 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] = {
ifuRoseInst, euRoseInst, iCacheRoseInst, eCacheRoseInst: CoreClasses.CellInstance ← NIL;
DStateAddress: CoreCreate.WR ← CoreCreate.Seq["DStateAddress", 4];
publicOutputName: CoreCreate.WR ← "DShOut"; -- IFU debug
publicInputNames:
LIST
OF CoreCreate.
WR ←
LIST[
"ResetAB", "RescheduleAB",
"PhA", "PhB", "NotPhA", "NotPhB",
"DShA", "DShB", "DShRd", "DShWt", "DShIn",
CoreCreate.Seq["DStAd", 4], "DHold", -- EU debug
"Vdd", "Gnd", "PadVdd", "PadGnd", "VRef" ];
public: CoreCreate.Wire = CoreCreate.WireList[
CONS[DStateAddress,
CONS
[publicOutputName, publicInputNames]]];
tempInstances: CoreClasses.CellInstances ← NIL;
internalOnly: CoreCreate.Wire = CoreCreate.WireList[
LIST[
"UserMode2BA",
"IPCmdFetchA",
"IPFaultingB",
CoreCreate.Seq["IPFaultingXB", 3],
CoreCreate.Seq["IPData", 32],
CoreCreate.Seq["DPCmdA", 8],
CoreCreate.Seq["DPFaultB", 4],
CoreCreate.Seq["DPData", 32],
CoreCreate.Seq["EUAluOp2AB", 4],
CoreCreate.Seq["EUCondSel2AB", 4],
CoreCreate.Seq["KBus", 32],
"EURdFromPBus3AB",
"EUWriteToPBus3AB",
"EUCondition2B",
"DPRejectB",
"IPRejectB" ] ];
ks ← lastKs ←
NEW[Cluster2.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: CoreFlat.
CellTypeCutLabels[
on: Cache2.Cache[vm: ks.iCache, skipRejects: skipIFURejects],
l1: "TopLevel"],
pas:
LIST[
["PUserMode", "Gnd"],
["PData", "IPData"],
["PCmdA[7]", "Gnd"],
["PCmdA[6]", "Gnd"],
["PCmdA[5]", "Gnd"],
["PCmdA[4]", "IPCmdFetchA"],
["PCmdA[3]", "IPCmdFetchA"],
["PCmdA[2]", "IPCmdFetchA"],
["PCmdA[1]", "IPCmdFetchA"],
["PCmdA[0]", "IPCmdFetchA"],
["PRejectB", "IPRejectB"],
["PFaultB[0]", "IPFaultingB"],
["PFaultB[1]", "IPFaultingXB[0]"],
["PFaultB[2]", "IPFaultingXB[1]"],
["PFaultB[3]", "IPFaultingXB[2]"] ] ];
ks.coreInsts[eCache] ← CoreCreate.InstanceList[
type: CoreFlat.
CellTypeCutLabels[
on: Cache2.Cache[vm: ks.eCache, skipRejects: skipEURejects],
l1: "TopLevel"],
pas:
LIST[
["PUserMode", "UserMode2BA"],
["PData", "DPData"],
["PCmdA", "DPCmdA"],
["PRejectB", "DPRejectB"],
["PFaultB", "DPFaultB"] ] ];
ks.coreInsts[ifu] ← CoreCreate.InstanceList[
type: CoreFlat.
CellTypeCutLabels[
on: IFU2.CreateIFU[
NEW[IFU2.IFUTypeData ←
[data: ks, getLog: GetLog, checkSynch: CheckSynch, getCycle: GetCycle ]],
fullIFU, quickIFU],
l1: "TopLevel" ],
pas: LIST[] ];
ks.coreInsts[eu] ← CoreCreate.InstanceList[
type: CoreFlat.
CellTypeCutLabels[
on: EU2.CreateEU2[
NEW[EU2.EUTypeData ←
[data: ks, storeNoted: FALSE, noteStore: NoteRegStore ]],
fullEU ],
l1: "TopLevel" ],
pas: LIST[ ] ];
FOR inst: Instances
DECREASING
IN Instances
DO
tempInstances ← CONS[ks.coreInsts[inst], tempInstances] ENDLOOP;
ks.cluster ← CoreCreate.Cell[
public: public,
onlyInternal: internalOnly,
instances: tempInstances,
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];
[] ← Rosemary.SetFixedWire[public[CoreOps.GetWireIndex[public, "VRef" ]], H];
[] ← Ports.InitPort[wire: CoreCreate.FindWire[ks.cluster.public, DStateAddress], levelType: c, initDrive: force];
[] ← Ports.InitPort[wire: CoreCreate.FindWire[ks.cluster.public, publicOutputName], levelType: 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], levelType: b, initDrive: force];
ENDLOOP;
ks.clusterIOPort ← Ports.CreatePort[ks.cluster];
ks.rosemarySimulation ← Rosemary.Instantiate[
cellType: ks.cluster,
testPort: ks.clusterIOPort,
cutSet: CoreFlat.CreateCutSet[labels: LIST["TopLevel"] ] ];
FOR inst: Instances
IN Instances
DO
ks.flatCT[inst] ← NEW[CoreFlat.FlatCellTypeRec ← CoreFlat.ParseCellTypePath[ks.cluster, IO.PutFR["/%g", IO.int[Instances[inst].ORD]]]];
ks.stateTop[0].refCy ← NEW[INT ← 0];
ks.stateTop[0].refPh ← NEW[Dragon.Phase ← a];
ks.stateTop[0].data[inst] ← Rosemary.GetState[ks.rosemarySimulation, ks.flatCT[inst]];
ENDLOOP;
FOR i:
NAT
IN [1..Cluster2.historySize)
DO
ks.stateTop[i].refCy ← NEW[INT ← 0];
ks.stateTop[i].refPh ← NEW[Dragon.Phase ← a];
ks.stateTop[i].data ← [
ifu: NEW[IFU2.IFUStateRec],
eu: NEW[EU2.EU2StateRec],
iCache: NEW[Cache2.CacheState],
eCache: NEW[Cache2.CacheState]];
ENDLOOP;
FOR i:
NAT
IN [0..Cluster2.historySize)
DO
ks.stateFull[i].refCy ← NEW[INT ← 0];
ks.stateFull[i].refPh ← NEW[Dragon.Phase ← a];
ks.stateFull[i].data ← [
ifu: NEW[IFU2.IFUStateRec],
eu: NEW[EU2.EU2StateRec],
iCache: NEW[Cache2.CacheState],
eCache: NEW[Cache2.CacheState]];
ENDLOOP;
ks.euReject ← NEW[CoreFlat.FlatWireRec ← CoreFlat.ParseWirePath[ks.cluster, "DPRejectB"]];
IF fullIFU
THEN {
ifuCellType: Core.CellType ← ks.coreInsts[ifu].type;
TerminalIO.WriteF["Make IFU Simulation %g\n", IO.time[]];
ks.ifuSimulationTruthPort ← Ports.CreatePort[ifuCellType, TRUE];
ks.ifuSimulationTestPort ← Ports.CreatePort[ifuCellType, TRUE];
ks.ifuSimulation ← Rosemary.Instantiate[
ifuCellType,
ks.ifuSimulationTestPort,
CoreFlat.CreateCutSet[labels: fullIFUCuts]];
ks.ifuDisplay ← RosemaryUser.DisplayViewer[ks.ifuSimulation, ifuCellType, "IFU2", RosemaryUser.DisplayPortLeafWires[ifuCellType]];
Rosemary.Initialize[ks.ifuSimulation, FALSE];
RosemaryUser.InitializeDeltas[ks.ifuDisplay];
TerminalIO.WriteF["IFU Instantiated %g\n", IO.time[]]};
IF fullEU
THEN {
euCellType: Core.CellType ← ks.coreInsts[eu].type;
TerminalIO.WriteF["Make EU Simulation %g\n", IO.time[]];
ks.euSimulationTruthPort ← Ports.CreatePort[euCellType, TRUE];
ks.euSimulationTestPort ← Ports.CreatePort[euCellType, TRUE];
ks.euSimulation ← Rosemary.Instantiate[
euCellType,
ks.euSimulationTestPort,
CoreFlat.CreateCutSet[labels: LIST["AlpsCell", "EU2Ram"]]];
ks.euDisplay ← RosemaryUser.DisplayViewer[ks.euSimulation, euCellType, "EU2", RosemaryUser.DisplayPortLeafWires[euCellType]];
Rosemary.Initialize[ks.euSimulation, FALSE]};
StartPanel[ks]};
DoCluster:
PUBLIC
PROC [ks: KitchenSink, diagnostic: Core.
ROPE ←
NIL] = {
originalPriority: Process.Priority = Process.GetPriority[];
diagnosticName: Core.ROPE ← "unknown";
IF ks=NIL THEN ks ← MakeCluster[];
{
ENABLE
UNWIND => {
ks.log.PutF["\nSimulation of %g aborted\n\n", IO.rope[diagnosticName]];
ks.log.Flush[];
Process.SetPriority[ originalPriority ] };
time: INT ← -1;
DoEval:
PROC = {
time ← time+1;
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];
CopyClusterArrayContents[ks.stateTop[0], ks.stateFull[0]];
IF fullIFU
THEN {
Rosemary.SettleToTest[simulation: ks.rosemarySimulation, flatCell: ks.flatCT[ifu], test: ks.ifuSimulationTruthPort];
Ports.CopyPortValue[from: ks.ifuSimulationTruthPort, to: ks.ifuSimulationTestPort];
RosemaryUser.LogSettle[ks.ifuDisplay, time
! Rosemary.Stop =>
IF reason # $BoolWireHasX
THEN
REJECT
ELSE
IF ks.controlPanel.reset
OR ks.protCyclesAfterReject>0
THEN
RESUME
ELSE {
TerminalIO.WriteF["%g = X\n",
IO.rope[
CoreOps.GetShortWireName[NARROW[data, CoreFlat.FlatWire].wire]]];
RosemaryUser.UpdateDisplay[ks.ifuDisplay];
RESUME}];
IF ks.controlPanel.sampleFullIFU
AND GetPublicBool[ks, $PhA]
THEN UpdateIFUState
[ks.ifuSimulation, NARROW[ks.stateFull[0].data[ifu]], ks.controlPanel.cycle, A];
IF ks.controlPanel.sampleFullIFU
AND GetPublicBool[ks, $PhB]
THEN UpdateIFUState
[ks.ifuSimulation, NARROW[ks.stateFull[0].data[ifu]], ks.controlPanel.cycle, B];
RosemaryUser.UpdateDisplay[ks.ifuDisplay];
Ports.CheckPortValue[root: ks.coreInsts[ifu].type.public, truth: ks.ifuSimulationTruthPort, question: ks.ifuSimulationTestPort ! Ports.CheckError =>
IF
NOT (ks.controlPanel.proceedFromCheckPort
OR ks.protCyclesAfterReject>0)
THEN REJECT
ELSE {TerminalIO.WriteF["%g\n", IO.rope[msg]]; RESUME}] };
IF fullEU
THEN {
Rosemary.SettleToTest[simulation: ks.rosemarySimulation, flatCell: ks.flatCT[eu], test: ks.euSimulationTruthPort];
Ports.CopyPortValue[from: ks.euSimulationTruthPort, to: ks.euSimulationTestPort];
RosemaryUser.LogSettle[ks.euDisplay, time
! Rosemary.Stop =>
IF ks.protCyclesAfterReject>0
AND reason = $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 ! Ports.CheckError =>
IF
NOT ks.controlPanel.proceedFromCheckPort
THEN REJECT
ELSE {TerminalIO.WriteF["%g\n", IO.rope[msg]]; RESUME}]};
IF ks.controlPanel.reset THEN ks.controlPanel.instrCount ← -1;
Process.Yield[];
ks.controlPanel.continueTestFromAbort ← FALSE};
UpdateIFUState: IFUTest.UpdateProc = {
comp: IFUState ← NARROW[ks.stateTop[0].data[ifu]];
atom: ATOM ← IFUTest.ifuUpdateProc;
updateProc: REF IFUTest.UpdateProc ← NARROW[Atom.GetProp[atom, atom]];
updateProc^[sim, state, pass, qph];
comp.cycle ← state.cycle;
comp.ph ← state.ph;
IF state^#comp^
THEN
IF
ks.controlPanel.reset OR
ks.protCyclesAfterReject>0 OR
ks.controlPanel.proceedFromCompareTest
THEN TerminalIO.WriteF["#\n"] ELSE Signal[]};
Signal: SIGNAL = CODE;
CopyClusterArrayContents:
PROC[fm, to: ClusterState] = {
to.refCy^ ← fm.refCy^;
to.refPh^ ← fm.refPh^;
NARROW[ to.data[ifu], IFUState]^ ← NARROW[ fm.data[ifu], IFUState]^;
NARROW[ to.data[eu], EUState]^ ← NARROW[ fm.data[eu], EUState]^;
NARROW[ to.data[iCache], CacheSt]^ ← NARROW[ fm.data[iCache], CacheSt]^;
NARROW[ to.data[eCache], CacheSt]^ ← NARROW[ fm.data[eCache], CacheSt]^};
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, $PhA, ph=a];
SetPublicBool[ks, $PhB, ph=b];
SetPublicBool[ks, $NotPhA, ph#a];
SetPublicBool[ks, $NotPhB, ph#b];
ks.stateTop[0].refPh^ ← ks.stateFull[0].refPh^ ← ks.controlPanel.phase;
ks.stateTop[0].refCy^ ← ks.stateFull[0].refCy^ ← ks.controlPanel.cycle;
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 {
OPEN cp: ks.controlPanel;
IF cp.stopInPh[ph]
AND
(cp.cycle >= cp.slowFromCycle OR
(cp.cycle >= 0
AND cp.instrCount >= cp.slowFromInstr))
THEN
Remark[
IO.PutFR["Doing cycle %g Ph%g...",
IO.int[cp.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 history buffers [1..top)
lastTop: ClusterState ← ks.stateTop [Cluster2.historySize-1];
lastFull: ClusterState ← ks.stateFull [Cluster2.historySize-1];
FOR i:
NAT
DECREASING
IN (1..Cluster2.historySize)
DO
ks.stateTop [i] ← ks.stateTop [i-1];
ks.stateFull [i] ← ks.stateFull [i-1] ENDLOOP;
ks.stateTop[1] ← lastTop;
ks.stateFull[1] ← lastFull;
CopyClusterArrayContents[ks.stateTop[0], ks.stateTop[1]];
CopyClusterArrayContents[ks.stateFull[0], ks.stateFull[1]];
first ← FALSE };
SetPublicBool[ks, $PhB, FALSE];
SetPublicBool[ks, $PhA, FALSE];
SetPublicBool[ks, $NotPhA, TRUE];
SetPublicBool[ks, $NotPhB, TRUE];
DoEval[];
ENDLOOP;
ks.protCyclesAfterReject ←
SELECT
TRUE
FROM
ks.controlPanel.reset => 3,
ph=a OR
Rosemary.WireValue[simulation: ks.rosemarySimulation, flatWire: ks.euReject][0]=H
=> ks.protCyclesAfterReject,
ks.protCyclesAfterReject>0 => ks.protCyclesAfterReject-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 ] = {
dStream: IO.STREAM = IO.RIS[ks.controlPanel.diagnostic];
first ← dStream.GetTokenRope[IO.IDProc ! IO.EndOfStream => CONTINUE].token;
rest ← ks.controlPanel.diagnostic.Substr[dStream.GetIndex]};
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, "DHold"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DStAd"]].c ← 0;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShA"]].b ← TRUE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShB"]].b ← TRUE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShRd"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShWt"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShIn"]].b ← FALSE;
};
FOR j:
NAT
IN [0..3)
DO
DoPh[a !
DragonRosemary.AssertionFailed => RESUME;
Rosemary.Stop => IF reason = $FailedAssertion OR reason = $BoolWireHasX THEN RESUME ELSE REJECT;
IFU2.IFUInconsistent => CONTINUE ];
DoPh[b !
DragonRosemary.AssertionFailed => RESUME;
Rosemary.Stop => IF reason = $FailedAssertion OR reason = $BoolWireHasX THEN RESUME ELSE REJECT;
IFU2.IFUInconsistent => CONTINUE ];
ENDLOOP;
{
public: Core.Wire ← ks.cluster.public;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShA"]].b ← FALSE;
ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShB"]].b ← FALSE;
};
Cycles[2];
SELECT TRUE FROM
diagnosticFileName #
NIL => {
fullName: Core.
ROPE ← FileNames.FileWithSearchRules
[diagnosticFileName, NIL, FALSE, TRUE, NIL].fullPath;
CacheOps.VirtualMemoryFromFile[ks.vm, fullName ];
ks.lizardSimulation ← (IF ks.controlPanel.lizardToo THEN StartNewLizard[ks.vm] ELSE NIL)};
ks.controlPanel.randomSeed#0 => {
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)};
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 => {
first, rest: Rope.ROPE;
[first, rest] ← Chop[];
IF first.Equal[diagnosticFileName]
THEN
ks.controlPanel.diagnostic ← Rope.Cat[rest, " ",first]};
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 ]};
SetPublic:
PUBLIC
PROC [ks: KitchenSink, signal:
ATOM, value:
REF
ANY ←
NIL ] = {
WITH value
SELECT
FROM
refBool:
REF
BOOL =>
ks.clusterIOPort[CoreOps.GetWireIndex[ks.rosemarySimulation.cellType.public, Atom.GetPName[signal]]].b ← refBool^;
ENDCASE => ERROR};
SetPublicBool:
PUBLIC
PROC [ks: KitchenSink, signal:
ATOM, value:
BOOL ] =
{SetPublic[ks, signal, NEW[BOOL ← value]]};
SetPublicAndSettle:
PUBLIC
PROC [ks: KitchenSink, signal:
ATOM, value:
REF
ANY ←
NIL ] = {
SetPublic[ks, signal, value];
Rosemary.Settle[ ks.rosemarySimulation
! ABORTED => IF ks.controlPanel.continueTestFromAbort THEN CONTINUE ELSE REJECT ];
ks.controlPanel.continueTestFromAbort ← FALSE};
GetPublicBool:
PUBLIC
PROC [ks: KitchenSink, signal:
ATOM]
RETURNS [value:
BOOL] =
{value ← ks.clusterIOPort[CoreOps.GetWireIndex[ks.rosemarySimulation.cellType.public, Atom.GetPName[signal]]].b};
GetLog:
PROC [ data: OpaqueKitchenSink ]
RETURNS [ Core.
STREAM ] =
{ks: KitchenSink = NARROW[data]; RETURN [ ks.log ]};
GetCycle:
PROC [ data: OpaqueKitchenSink ]
RETURNS [ cycle:
INT ] =
{ks: KitchenSink = NARROW[data]; RETURN [ ks.controlPanel.cycle ]};
NoteRegStore:
PROC [ data:
REF
ANY, reg: [0..256), value: Dragon.Word ] = {
EU2.NoteRegStoreProc
ks: KitchenSink = NARROW[data];
ks.rosemaryStores ← CONS[NEW[Dragon.RegStoreRec ← [instr: ks.controlPanel.instrCount, reg: VAL[reg], data: value]], ks.rosemaryStores]};
randomStartPC: Dragon.Word ← 102000H;
runningMsg: Core.ROPE ← "Running...";
randomBackground: Core.
ROPE ← "RandomBackground.quad";
InsertRandomProgramInVM:
PROC[ ks: KitchenSink ] = {
WriteOneCodeByte:
PROC [byte: [0..255]] = {
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};
fullName: Core.
ROPE ← FileNames.FileWithSearchRules
[randomBackground, NIL, FALSE, TRUE, NIL].fullPath;
nextByteAddr: Dragon.Word ← randomStartPC;
CacheOps.VirtualMemoryFromFile[ks.vm, fullName];
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, userMode:
BOOL, noEffect:
BOOL ←
FALSE]
RETURNS [data: LizardCache.Word, status: LizardCache.TrapIndex, rejectCycles:
INT] = {
Lizard.CacheFetchProc
sim: LizardSimulation = NARROW[base.data];
[data: data, status: status, rejectCycles: rejectCycles] ← sim.euCache.fetch
[base: sim.euCache, addr: addr, cycle: cycle, userMode: userMode, 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,
MemAccessFault => memAccess,
IOAccessFault => ioAccess,
EUPageFault => page,
EUWriteFault => write,
ENDCASE => ERROR ]],
sim.lastInstrOps]};
LizardEUCacheStoreTrap:
PROC
[base: LizardCache.CacheBase, addr: LizardCache.Word, data: LizardCache.Word, cycle: INT, userMode: BOOL]
RETURNS [old: LizardCache.Word, status: LizardCache.TrapIndex, rejectCycles:
INT] = {
Lizard.CacheStoreProc
sim: LizardSimulation = NARROW[base.data];
[old: old, status: status, rejectCycles: rejectCycles] ←
sim.euCache.store[base: sim.euCache, addr:addr, data:data, cycle:cycle, userMode:userMode];
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,
MemAccessFault => memAccess,
IOAccessFault => ioAccess,
EUPageFault => page,
EUWriteFault => write,
ENDCASE => ERROR ]],
sim.lastInstrOps]};
NoteChangedReg:
PROC[data:
REF, processor: LizardHeart.Processor, reg: DragOpsCross.ProcessorRegister, old,new: DragOpsCross.Word] = {
LizardHeart.RegChangeProc
sim: LizardSimulation = NARROW[data];
sim.lastInstrOps ←
CONS[
NEW[Dragon.RegStoreRec ← [
instr: sim.processor.stats.instructions,
reg: reg,
data: DragOpsCrossUtils.WordToCard[new] ]],
sim.lastInstrOps]};
NoteInstDone:
PROC [data:
REF, processor: LizardHeart.Processor, newPC, rtnPC: DragOpsCross.Word, control: LizardHeart.Control, cycles:
INT] =
-- LizardHeart.InstDoneProc--
{sim: LizardSimulation = NARROW[data]; sim.control ← control};
StartNewLizard:
PUBLIC
PROC [ m:
REF
-- CacheOps.VM -- ]
RETURNS [ sim: LizardSimulation ] = {
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[Cluster2.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,
sharedBase: sim.euCache.sharedBase,
private: sim.euCache.private,
data: sim ]],
logger:
NEW[LizardHeart.ChangeLoggerRep ← [
data: sim,
regChange: NoteChangedReg,
instDone: NoteInstDone ]] ]};
SuccessHalt: PUBLIC ERROR = CODE;
Breakpoint:
PUBLIC
SIGNAL =
CODE;
CheckSynch:
PUBLIC
PROC [ data: OpaqueKitchenSink, basicInst: IFU2.BasicInst ]
RETURNS [deltaInstrCount:
INT ← 1]
-- IFU2.CheckSynchProc -- = {
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};
DefaultCheckSynch:
PUBLIC IFU2.CheckSynchProc =
{RETURN[1]};
csProcRec:
PUBLIC Cluster2.CSProcRec ← [DefaultCheckSynch];
StartPanel:
PROC [ks: KitchenSink] = {
IF ks.controlPanel =
NIL
THEN {
ks.controlPanel ←
NEW[Cluster2.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.