<> <> <> <> <> <<>> 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 <> ]; 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; }; <
> 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; ENDCASE => ERROR; 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.}