LizardToolWatcher:
PROC [data: ToolData] = {
NewMenuEntry:
PROC [name:
ROPE, proc: Menus.MenuProc, line:
INTEGER ← 0] = {
Menus.AppendMenuEntry[
menu, Menus.CreateEntry[name: name, proc: proc, clientData: data], line];
};
StandardButton:
PROC
[name: ROPE, proc: Menus.MenuProc, x,y: INTEGER, w: INTEGER ← 0]
RETURNS [button: Buttons.Button] = {
button ← Buttons.Create[
info: [parent: topViewer, name: name, border: TRUE, wx: x, wy: y, ww: w],
proc: proc,
clientData: data,
paint: FALSE];
nextX ← button.wx+button.ww-1;
nextY ← button.wy+button.wh-1;
};
nextX: INTEGER ← 1;
nextY: INTEGER ← 1;
menu: Menus.Menu = Menus.CreateMenu[2];
topViewer: Viewer = Containers.Create[
info: [name: "LizardTool", iconic: TRUE, column: left, scrollable: FALSE],
paint: FALSE];
traceButton: Buttons.Button ← data.traceButton ← StandardButton[
" Trace ", TraceButtonProc, 1, 1];
baseButton: Buttons.Button ← data.baseButton ← StandardButton[
" Octal ", BaseButtonProc, nextX, 1];
setDumpStartButton: Buttons.Button = StandardButton[
" Set Dump Start ", SetDumpStartButtonProc, nextX, 1];
setDumpWordsButton: Buttons.Button = StandardButton[
" Set Dump Words ", SetDumpWordsButtonProc, nextX, 1];
setPauseCondButton: Button = StandardButton[
" SetPauseCond ", SetPauseCondProc, 1, nextY];
samplePauseCondButton: Button = StandardButton[
" Sample ", SamplePauseCondProc, 1, nextY, setPauseCondButton.ww];
pauseCondText: Viewer = ViewerOps.CreateViewer[
flavor: $Text,
info: [
wx: nextX,
wy: setPauseCondButton.wy,
ww: setPauseCondButton.ww,
wh: nextY+1 - setPauseCondButton.wy,
parent: topViewer],
paint: FALSE];
vTab: VTable = VTables.Create[columns: 10, rows: 3, parent: topViewer, x: 1, y: nextY];
statusLabel: Label ← data.statusLabel ← Labels.Create[
info: [name: "Initializing", parent: vTab, border: FALSE],
paint: FALSE];
instCountLabel: NumberLabel = StandardNumberLabel[vTab, 10];
instRateLabel: NumberLabel = StandardNumberLabel[vTab, 7];
cycleCountLabel: NumberLabel = StandardNumberLabel[vTab, 10];
cycleRateLabel: NumberLabel = StandardNumberLabel[vTab, 7];
iBytesCountLabel: NumberLabel = StandardNumberLabel[vTab, 10];
iBytesRateLabel: NumberLabel = StandardNumberLabel[vTab, 7];
readCountLabel: NumberLabel = StandardNumberLabel[vTab, 10];
readRateLabel: NumberLabel = StandardNumberLabel[vTab, 7];
writeCountLabel: NumberLabel = StandardNumberLabel[vTab, 10];
writeRateLabel: NumberLabel = StandardNumberLabel[vTab, 7];
DoRefresh:
PROC [data: ToolData] = {
newStats: ToolStats = SampleStats[data];
deltaStats: ToolStats = GetDeltaFromBase[data];
IF deltaStats.samplePulses # 0
THEN {
Now we are off and running!
secs: REAL = BasicTime.PulsesToSeconds[deltaStats.samplePulses];
invSecs: REAL = 1/secs;
IF deltaStats.pStats.instructions # 0
THEN {
NumberLabels.NumberLabelUpdate[instCountLabel, newStats.pStats.instructions];
NumberLabels.NumberLabelUpdate[instRateLabel,
Real.RoundLI[(deltaStats.pStats.instructions) * invSecs]];
};
IF deltaStats.pStats.cycles # 0
THEN {
NumberLabels.NumberLabelUpdate[cycleCountLabel, newStats.pStats.cycles];
NumberLabels.NumberLabelUpdate[cycleRateLabel,
Real.RoundLI[(deltaStats.pStats.cycles) * invSecs]];
};
IF deltaStats.pStats.instBytes # 0
THEN {
NumberLabels.NumberLabelUpdate[iBytesCountLabel, newStats.pStats.instBytes];
NumberLabels.NumberLabelUpdate[iBytesRateLabel,
Real.RoundLI[(deltaStats.pStats.instBytes) * invSecs]];
};
IF deltaStats.pStats.euFetches # 0
THEN {
NumberLabels.NumberLabelUpdate[readCountLabel, newStats.pStats.euFetches];
NumberLabels.NumberLabelUpdate[readRateLabel,
Real.RoundLI[(deltaStats.pStats.euFetches) * invSecs]];
};
IF deltaStats.pStats.euStores # 0
THEN {
NumberLabels.NumberLabelUpdate[writeCountLabel, newStats.pStats.euStores];
NumberLabels.NumberLabelUpdate[writeRateLabel,
Real.RoundLI[(deltaStats.pStats.euStores) * invSecs]];
};
};
};
topViewer.menu ← menu;
NewMenuEntry["Stop!", StopMenuProc];
NewMenuEntry["Pause", PauseMenuProc];
NewMenuEntry["Run", RunMenuProc];
NewMenuEntry["Step", StepMenuProc];
NewMenuEntry["Reset", ResetMenuProc];
NewMenuEntry["Resched", ReschedMenuProc];
NewMenuEntry["StopPrint!", StopPrintMenuProc];
NewMenuEntry["DumpMem", DumpMemMenuProc, 1];
NewMenuEntry["DumpRegs", DumpRegsMenuProc, 1];
NewMenuEntry["DumpStats", DumpStatsMenuProc, 1];
NewMenuEntry["DumpRing", DumpRingMenuProc, 1];
NewMenuEntry["BiasStats", BiasStatsMenuProc, 1];
VTables.SetTableEntry[
table: vTab, row: 0, column: 0, flavor: $Viewer, clientData: statusLabel];
VTables.SetTableEntry[table: vTab, row: 1, column: 0, name: "count"];
VTables.SetTableEntry[table: vTab, row: 2, column: 0, name: "rate"];
VTables.SetTableEntry[table: vTab, row: 0, column: 1, name: "inst"];
VTables.SetTableEntry[
table: vTab, row: 1, column: 1, flavor: $Viewer, clientData: instCountLabel];
VTables.SetTableEntry[
table: vTab, row: 2, column: 1, flavor: $Viewer, clientData: instRateLabel];
VTables.SetTableEntry[table: vTab, row: 0, column: 2, name: "cycle"];
VTables.SetTableEntry[
table: vTab, row: 1, column: 2, flavor: $Viewer, clientData: cycleCountLabel];
VTables.SetTableEntry[
table: vTab, row: 2, column: 2, flavor: $Viewer, clientData: cycleRateLabel];
VTables.SetTableEntry[table: vTab, row: 0, column: 3, name: "instBytes"];
VTables.SetTableEntry[
table: vTab, row: 1, column: 3, flavor: $Viewer, clientData: iBytesCountLabel];
VTables.SetTableEntry[
table: vTab, row: 2, column: 3, flavor: $Viewer, clientData: iBytesRateLabel];
VTables.SetTableEntry[table: vTab, row: 0, column: 4, name: "read"];
VTables.SetTableEntry[
table: vTab, row: 1, column: 4, flavor: $Viewer, clientData: readCountLabel];
VTables.SetTableEntry[
table: vTab, row: 2, column: 4, flavor: $Viewer, clientData: readRateLabel];
VTables.SetTableEntry[table: vTab, row: 0, column: 5, name: "write"];
VTables.SetTableEntry[
table: vTab, row: 1, column: 5, flavor: $Viewer, clientData: writeCountLabel];
VTables.SetTableEntry[
table: vTab, row: 2, column: 5, flavor: $Viewer, clientData: writeRateLabel];
VTables.Install[table: vTab, paint: FALSE];
data.logTS ← TypeScript.Create[
info: [parent: topViewer, wx: vTab.wx, wy: vTab.wy+vTab.wh, border: FALSE],
paint: FALSE];
TypeScript.ChangeLooks[data.logTS, 'f]; -- fixed width font for alignment
TypeScript.ChangeLooks[data.logTS, 's]; -- small for compactness
data.vTab ← vTab;
data.pauseCondText ← pauseCondText;
data.log ← ViewerIO.CreateViewerStreams[
name: "LizardTool.log",
viewer: data.logTS,
backingFile: "LizardTool.log",
editedStream: FALSE].out;
Containers.ChildXBound[container: topViewer, child: data.logTS];
Containers.ChildYBound[container: topViewer, child: data.logTS];
Containers.ChildXBound[container: topViewer, child: pauseCondText];
InvertOutputBase[data]; -- forces the initial base to be Octal
ViewerOps.OpenIcon[topViewer];
Start[data];
WHILE data.live
DO
DoRefresh[data];
WaitForRefresh[data];
IF NOT data.live OR topViewer.destroyed THEN EXIT;
ENDLOOP;
ExecBase:
PROC [nProcessors:
NAT, area: HandCodingSupport.Area] = {
data: ToolData = NEW[ToolDataRep];
processors: ProcessorSequence = NEW[ProcessorSequenceRep[nProcessors]];
logger: ChangeLogger =
NEW[ChangeLoggerRep ← [
data, LogRegChange, LogMemChange, LogIOChange, LogInstStart, LogInstDone]];
cycles: INT ← 0;
processor: Processor ← NIL;
lagControl: InternalControl ← run;
statusLabel: Label ← NIL;
mem: SparseMemory.Base = NARROW[area.data];
shared: LizardCache.SharedBase = LizardCache.NewBase[mem];
instTable: InstCountTable ← NEW[InstCountTableRep ← ALL[0]];
logger.data ← data;
data.instTable ← instTable;
data.lastInstTable ← NEW[LastInstTableRep];
data.lastInstTable.last ← 0;
data.lastInstTable.pcArray ← ALL[ZerosWord];
FOR i:
NAT
IN [0..nProcessors)
DO
ifuCache: LizardCache.CacheBase = LizardCache.NewCache[shared, instCacheLines];
euCache: LizardCache.CacheBase = LizardCache.NewCache[shared, dataCacheLines];
processors[i] ← LizardHeart.NewProcessor[ifuCache, euCache, logger];
ENDLOOP;
TRUSTED {Process.Detach[FORK LizardToolWatcher[data]]};
Wait for the watcher to start up
UNTIL data.live DO WaitForRefresh[data]; ENDLOOP;
statusLabel ← data.statusLabel;
IO.PutF[data.log, "\nStarting interpreter at %g\n\n", [time[BasicTime.Now[]]] ];
Labels.Set[statusLabel, "Pausing"];
processor ← processors[0];
For now, we only support one processor
Process.SetPriority[Process.priorityBackground];
When we are really cranking along in the instruction stream we don't want to hog the machine. Cedar does not really handle competing processes at the same priority level as well as we would like.
Now start interpreting instructions until told to stop (currently we only support one processor).
WHILE data.live
AND
NOT data.vTab.destroyed
DO
internalControl: InternalControl ← data.internalControl;
SELECT
TRUE
FROM
data.requestReset => {
processor.resetRequested ← TRUE;
IO.PutRope[data.log, "Note: reset requested by user.\n\n"];
data.requestReset ← FALSE;
UpdateStats[data, SampleStats[data]];
LOOP;
};
data.requestReschedule => {
LOOPHOLE[processor.regs[ifuStatus], DragOpsCross.IFUStatusRec].reschedule ← TRUE;
IO.PutRope[data.log, "Note: reschedule requested by user.\n\n"];
data.requestReschedule ← FALSE;
LOOP;
};
data.requestDump # none => {
ServiceDumpRequest[data, processor, mem, data.requestDump];
data.requestDump ← none;
LOOP;
};
data.requestBiasStats => {
ServiceBiasStatsRequest[data, processor];
data.requestBiasStats ← FALSE;
LOOP;
};
ENDCASE;
IF internalControl # lagControl
THEN {
Show the new status
SELECT internalControl
FROM
run => Labels.Set[statusLabel, "Running"];
step => Labels.Set[statusLabel, "Stepping"];
pause => Labels.Set[statusLabel, "Pausing"];
stop => Labels.Set[statusLabel, "Stopping"];
ENDCASE => ERROR;
lagControl ← internalControl;
SetBaseState[data];
CauseRefresh[data];
};
SELECT internalControl
FROM
pause => {
UpdateStats[data, SampleStats[data]];
[] ← WaitForControlChange[data];
LOOP};
stop => EXIT;
ENDCASE => ERROR;
LizardHeart.InstructionExecute[processor !
LizardHeart.OutsideEnvelope => {
data.log.PutF["Warning: In instruction %g processor outside defined envelope -\n %g\n\n",
IO.int[processor.stats.instructions], IO.rope[explanation]];
internalControl ← step;
RESUME
}
IF internalControl = step
THEN {
SetInternalControl[data, pause];
CauseRefresh[data];
};
ENDLOOP;
IO.PutF[data.log, "\nStopping interpreter at %g\n\n", [time[BasicTime.Now[]]]
! IO.Error => CONTINUE];
Stop[data];
IF NOT statusLabel.destroyed THEN Labels.Set[statusLabel, "Stopped"];
};