<> <> <> <> <> <> <> <> <<>> DIRECTORY Atom, Basics, Cache2, CacheOps, Cluster, Core, CoreClasses, CoreCreate, CoreFlat, CoreOps, Dragon, DragonRosemary, DragOpsCross, DragOpsCrossUtils, EU, FileNames, IFU2, IO, LizardCache, LizardHeart, Ports, Process, RandomCode, Rope, Rosemary, RosemaryUser, SparseMemory, TerminalIO, TypeScript, ViewerClasses, ViewerIO, ViewRec; ClusterImpl: CEDAR PROGRAM IMPORTS Atom, Cache2, CacheOps, CoreCreate, CoreFlat, CoreOps, DragonRosemary, DragOpsCrossUtils, EU, FileNames, IFU2, IO, LizardCache, LizardHeart, Ports, Process, RandomCode, Rope, Rosemary, RosemaryUser, SparseMemory, TerminalIO, TypeScript, ViewerIO, ViewRec EXPORTS Cluster = BEGIN KitchenSink: TYPE = Cluster.KitchenSink; OpaqueKitchenSink: TYPE = Cluster.OpaqueKitchenSink; LizardSimulation: TYPE = Cluster.LizardSimulation; Instances: TYPE = Cluster.Instances; ClusterState: TYPE = Cluster.ClusterState; IFUState: TYPE = IFU2.IFUState; EUState: TYPE = EU.EUState; CacheSt: TYPE = REF Cache2.CacheState; nCacheLines: NAT _ 200; skipIFURejects: BOOL _ FALSE; skipEURejects: BOOL _ FALSE; fullEU: BOOL _ FALSE; fullIFU: BOOL _ FALSE; quickIFU: BOOL _ FALSE; lastKs: PUBLIC KitchenSink _ NIL; <> MakeCluster: PUBLIC PROC RETURNS [ks: KitchenSink] = { ifuRoseInst, euRoseInst, iCacheRoseInst, eCacheRoseInst: CoreClasses.CellInstance _ NIL; publicInputNames: LIST OF CoreCreate.WR _ LIST[ "ResetAB", "RescheduleAB", "PhA", "PhB", "NotPhA", "NotPhB", "DShA", "DShB", "DShRd", "DShWt", "DShIn", "DHold", CoreCreate.Seq["DStAd", 4], "Vdd", "Gnd", "PadVdd", "PadGnd", "VRef" ]; public: CoreCreate.Wire = CoreCreate.WireList[CONS["DShOut", 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[Cluster.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: EU.CreateEU[ typeData: NEW[EU.EUTypeData _ [data: ks, storeNoted: FALSE, noteStore: NoteRegStore]], fullEU: fullEU, useCkPt: 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]; 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; [] _ Ports.InitPort[wire: CoreCreate.FindWire[ks.cluster.public, "DStAd"], levelType: c, initDrive: force]; [] _ Ports.InitPort[wire: CoreCreate.FindWire[ks.cluster.public, "DShOut"], levelType: b, initDrive: none]; 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..Cluster.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[EU.EUStateRec], iCache: NEW[Cache2.CacheState], eCache: NEW[Cache2.CacheState]]; ENDLOOP; FOR i: NAT IN [0..Cluster.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[EU.EUStateRec], iCache: NEW[Cache2.CacheState], eCache: NEW[Cache2.CacheState]]; ENDLOOP; ks.euReject _ NEW[CoreFlat.FlatWireRec _ CoreFlat.ParseWirePath[ks.cluster, "DPRejectB"]]; <> <> <> <> <> <> <> <> <> <> <> <> IF fullEU THEN { -- fix the cutset!!!!!!!!!! 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["Logic", "LogicMacro"]]]; ks.euDisplay _ RosemaryUser.DisplayViewer[ks.euSimulation, euCellType, "EU", RosemaryUser.DisplayPortLeafWires[euCellType]]; Rosemary.Initialize[ks.euSimulation, FALSE]; RosemaryUser.InitializeDeltas[ks.euDisplay]; TerminalIO.WriteF["EU Instantiated %g\n", IO.time[]]}; 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 reason # $BoolWireHasX>> <0>> <> <> <> <> <> <> <<[ks.ifuSimulation, NARROW[ks.stateFull[0].data[ifu]], ks.controlPanel.cycle, A];>> <> <<[ks.ifuSimulation, NARROW[ks.stateFull[0].data[ifu]], ks.controlPanel.cycle, B];>> <> < >> <0)>> <> <> 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 reason = $BoolWireHasX THEN { TerminalIO.WriteF["%g = X at cycle %g", IO.rope[CoreOps.GetShortWireName[NARROW[data, CoreFlat.FlatWire].wire]], IO.int[time]]; 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}; <> <> <> <> <> <> <> <> <> <0 OR>> <> <> 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 [Cluster.historySize-1]; lastFull: ClusterState _ ks.stateFull [Cluster.historySize-1]; FOR i: NAT DECREASING IN (1..Cluster.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}; <
> 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, "DStAd"]].c _ 0; ks.clusterIOPort[CoreOps.GetWireIndex[public, "DHold"]].b _ FALSE; ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShA"]].b _ FALSE; ks.clusterIOPort[CoreOps.GetWireIndex[public, "DShB"]].b _ FALSE; 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; 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)}; 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 => { 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 ] = { <> 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] = { <> 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] = { <> 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] = { <> 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[Cluster.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 Cluster.CSProcRec _ [DefaultCheckSynch]; StartPanel: PROC [ks: KitchenSink] = { IF ks.controlPanel = NIL THEN { ks.controlPanel _ NEW[Cluster.ControlPanelRec _ [ msg: "Initialized...", enaIFULog: TRUE, diagnostic: ks.diagnostics ]]; ViewRec.SetBehavior[newBehavior: [delayParms: [min: 2000.0]]]; [] _ ViewRec.ViewRef[ agg: ks.controlPanel, label: "Dragon Cluster3 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.