File: spMain.mesa
Copyright (C) 1985 by Xerox Corporation. All rights reserved.
Last Edited by:
Sweetsun Chen, October 21, 1985 3:55:58 pm PDT
DIRECTORY
BasicTime USING [Now],
CommandTool USING [Run],
FS USING [Error],
IO USING [PutF, rope],
MessageWindow USING [Append],
PrincOps USING [NoTimeout],
Process USING [Abort, Detach, GetPriority, Priority, priorityBackground, SecondsToTicks, SetPriority, SetTimeout],
RecursivelyNIL USING [CheckProc, NILRef],
Real USING [FixC],
RefText USING [New],
Rope USING [Equal, Find, FromRefText, IsEmpty, ROPE, Substr],
spGlobals USING [Aborted, bomb, CircuitRec, CleanUp, defineCircuit, dumpAll, error, ErrWarnSummary, fileNameStackSeq, fileStackSeq, function, functionTable, FuncTableBlk, Handle, keys, makePlotList, makePrintList, maxInclude, maxLog, maxPlots, maxPrints, model, modFuncPtr, modelTable, ModelTableBlk, nameBlk, namePtr, next, openInputFile, output, PlotSeq, printHole, PrintSeq, PutMsgLine, runIt, searchKey, SetCursor, setICs, topoAnalysis, Variables, WorstNodeLog],
ViewerClasses USING [Viewer],
ViewerTools USING [SetContents];
spMain: CEDAR MONITOR
IMPORTS BasicTime, CommandTool, FS, IO, MessageWindow, Process, Real, --RecursivelyNIL, --RefText, Rope, spGlobals, ViewerTools
EXPORTS spGlobals=
{ OPEN spGlobals;
EnterModels: PUBLIC ENTRY PROC[entry: ModelTableBlk]= {
ENABLE UNWIND => NULL;
FOR m: LIST OF REF ModelTableBlk ← modelTable, m.rest UNTIL m=NIL DO
IF Rope.Equal[m.first.name, entry.name] THEN {
m.first^ ← entry;
RETURN;
};
ENDLOOP;
modelTable ← CONS[NEW[ModelTableBlk← entry], modelTable];
}; -- EnterModels
EnterFunctions: PUBLIC ENTRY PROC[entry: FuncTableBlk]= {
ENABLE UNWIND => NULL;
FOR f: LIST OF REF FuncTableBlk ← functionTable, f.rest UNTIL f=NIL DO
IF Rope.Equal[f.first.name, entry.name] THEN {
f.first^ ← entry;
RETURN;
};
ENDLOOP;
functionTable ← CONS[NEW[FuncTableBlk← entry], functionTable];
}; -- EnterFunctions
entry procs
findModel: PUBLIC ENTRY PROC[name: Rope.ROPE] RETURNS[REF ModelTableBlk]= {
ENABLE UNWIND => NULL;
FOR m: LIST OF REF ModelTableBlk ← modelTable, m.rest UNTIL m=NIL DO
IF Rope.Equal[m.first.name, name] THEN RETURN[m.first];
ENDLOOP;
RETURN[NIL];
}; -- findModel
findFunction: PUBLIC ENTRY PROC[name: Rope.ROPE]
RETURNS[REF FuncTableBlk]= {
ENABLE UNWIND => NULL;
FOR f: LIST OF REF FuncTableBlk← functionTable, f.rest UNTIL f=NIL DO
IF Rope.Equal[f.first.name, name] THEN RETURN[f.first];
ENDLOOP;
RETURN[NIL];
}; -- findFunction
ResetCheckPoint: PUBLIC ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
handle.vars.checkPoint← FALSE };
Canned: PUBLIC ENTRY PROC[handle: Handle] RETURNS[BOOL]= {
ENABLE UNWIND => NULL;
RETURN[handle.vars.canned]};
ForcedDump: PUBLIC ENTRY PROC[handle: Handle] RETURNS[BOOL]= {
ENABLE UNWIND => NULL;
RETURN[handle.vars.forcedDump]};
CheckPoint: PUBLIC ENTRY PROC[handle: Handle] RETURNS[BOOL]= {
ENABLE UNWIND => NULL;
RETURN[handle.vars.checkPoint]};
ShowDetails: PUBLIC ENTRY PROC[handle: Handle] RETURNS[BOOL]= {
ENABLE UNWIND => NULL;
RETURN[handle.showTimeStep]};
EchoInput: PUBLIC ENTRY PROC[handle: Handle] RETURNS[BOOL]= {
ENABLE UNWIND => NULL;
RETURN[handle.echoInput]};
StopIt: PUBLIC ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
IF handle # NIL THEN {
IF handle.vars # NIL THEN {
handle.vars.forcedDump← FALSE;
handle.vars.canned← TRUE;
};
AbortCheckPoint[handle];
};
}; -- StopIt
DumpIt: PUBLIC ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
IF handle # NIL THEN {
IF handle.vars # NIL THEN {
handle.vars.forcedDump← TRUE;
handle.vars.canned← TRUE;
};
AbortCheckPoint[handle];
};
}; -- DumpIt
ToggleShowDetails: PUBLIC ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
handle.showTimeStep← ~handle.showTimeStep;
}; -- ToggleShowDetails
ToggleEchoInput: PUBLIC ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
handle.echoInput← ~handle.echoInput;
}; -- ToggleEchoInput
NormalRun: PUBLIC ENTRY PROC[handle: Handle, background, fork: BOOLTRUE]= {
ENABLE UNWIND => NULL;
IF handle = NIL THEN RETURN;
IF handle.stage=idle AND handle.simulation=NIL THEN {
curPriority: Process.Priority = Process.GetPriority[];
handle.stage← input;
SetCursor[handle];
IF background THEN Process.SetPriority[Process.priorityBackground];
handle.outer.inhibitDestroy ← TRUE;
IF fork THEN handle.simulation← FORK Simulate[handle]
ELSE {
handle.simulation← NIL;
Simulate[handle];
};
IF background THEN Process.SetPriority[curPriority];
IF fork THEN TRUSTED {Process.Detach[handle.simulation]};
}
ELSE MessageWindow.Append[
message: "Previous simulation has not finished yet.", clearFirst: TRUE];
}; -- NormalRun
BatchRun: PUBLIC PROC[handle: Handle, inputFile: Rope.ROPENIL]= {
IF handle = NIL THEN RETURN;
IF inputFile # NIL THEN ViewerTools.SetContents[handle.input, inputFile];
NormalRun[handle, FALSE];
IF handle.simulation # NIL THEN TRUSTED {JOIN handle.simulation};
}; -- BatchRun
NextStage: PUBLIC ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
SELECT handle.stage FROM
input, bomb, topo => {
handle.stage← SUCC[handle.stage];
SetCursor[handle];
};
run => {
handle.vars.runState ← (handle.vars.runState + 1) MOD 4;
SetCursor[handle];
};
ENDCASE => MessageWindow.Append[ -- should not get here
message: "* Weird situation detected in 'NextStage', please inform SChen.pa",
clearFirst: TRUE];
}; -- NextStage
PeriodicSetCheckPoint: ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
WHILE handle # NIL DO
ENABLE ABORTED => EXIT;
WAIT handle.checkPointCV;
IF handle # NIL THEN
IF handle.vars # NIL THEN handle.vars.checkPoint← TRUE
ELSE EXIT;
ENDLOOP;
IF handle # NIL THEN
TRUSTED {Process.SetTimeout[@handle.checkPointCV, PrincOps.NoTimeout]};
}; -- PeriodicSetCheckPoint
CleanIt: ENTRY PROC[handle: Handle]= {
ENABLE UNWIND => NULL;
CleanUp[handle];
}; -- CleanIt
AbortCheckPoint: INTERNAL PROC[handle: Handle]= {
IF handle = NIL THEN RETURN;
IF handle.stage=run AND handle.checkProcess # NIL THEN {
TRUSTED {Process.Abort[LOOPHOLE[handle.checkProcess, UNSPECIFIED]]};
handle.checkProcess← NIL;
};
}; -- AbortCheckPoint
AddLibrary: PROC[handle: Handle]= {
next[handle];
IF handle.vars.item=leftB THEN next[handle] ELSE error[handle, 801, TRUE];
IF handle.vars.item=name THEN {
originalName, nameRoot, errMsg: Rope.ROPE;
dotPosition: INT;
originalName← Rope.FromRefText[handle.vars.newString];
dotPosition← Rope.Find[originalName, "."];
nameRoot← IF dotPosition=-1 THEN originalName
ELSE Rope.Substr[originalName, 0, dotPosition-1];
IF NOT (Rope.Equal[nameRoot, "MosModels", FALSE] OR
Rope.Equal[nameRoot, "StdFunctions", FALSE] OR
Rope.Equal[nameRoot, "Level2Model", FALSE]) THEN {
[errMsg, ]← CommandTool.Run[originalName];
IF NOT errMsg.IsEmpty[] THEN PutMsgLine[handle, errMsg];
};
next[handle];
}
ELSE error[handle, 804, TRUE];
IF handle.vars.item=rightB THEN next[handle] ELSE error[handle, 802, FALSE];
IF handle.vars.item=semi THEN next[handle] ELSE error[handle, 800, FALSE];
}; -- AddLibrary
Simulate: PROC[handle: Handle]= {
ENABLE {
Aborted => GOTO stop;
ABORTED => {handle.vars.canned ← TRUE; GOTO dumpStop};
FS.Error => {
handle.msgStream.PutF["%g\nProgram stopped.\n", IO.rope[error.explanation]];
GOTO stop;
};
};
InitVars[handle];
openInputFile[handle];
next[handle];
libraries
WHILE handle.vars.item=name DO
IF Canned[handle] THEN GOTO stop;
IF searchKey[handle]=libraryKey THEN AddLibrary[handle] ELSE EXIT;
ENDLOOP;
circuit definition
IF handle.vars.item=name AND searchKey[handle]=circuitKey THEN {
theRoot: namePtr← NEW[nameBlk←
[name: "Main Circuit", details: NEW[CircuitRec← []]] ];
defineCircuit[handle: handle, ckt: theRoot, root: TRUE]; -- may signal Aborted
}
ELSE error[handle, 820, TRUE];
IF handle.vars.item=slash AND handle.vars.errCount <= 0 THEN {
next[handle];
output[handle, handle.vars.cktRoot, 0];
};
explode
IF handle.vars.item#semi THEN error[handle, 800,, FALSE]
ELSE IF handle.vars.errCount <= 0 THEN {
NextStage[handle];
bomb[handle]; -- may signal Aborted
next[handle];
IF handle.vars.item=plus THEN {next[handle]; printHole[handle]};
};
analyze
IF handle.vars.errCount <= 0 THEN {
NextStage[handle];
topoAnalysis[handle];
IF Canned[handle] THEN GOTO stop;
};
run
IF handle.vars.errCount <= 0 THEN {
NextStage[handle];
WHILE handle.vars.item=name DO
OPEN handle.vars;
key: keys← searchKey[handle];
next[handle];
SELECT key FROM
runKey=> {
TRUSTED {
Process.SetTimeout[@handle.checkPointCV,
Process.SecondsToTicks[Real.FixC[60.0*checkPointInterval]]];
Process.Detach[handle.checkProcess← FORK PeriodicSetCheckPoint[handle]];
};
lastTime← runIt[handle];
IF NOT Canned[handle] THEN PutMsgLine[handle, "Done."];
};
printKey=> makePrintList[handle];
plotKey => makePlotList[handle];
icKey => setICs[handle];
dumpKey => IF ~ForcedDump[handle] THEN dumpAll[handle, lastTime];
checkPointKey=> {
IF item=leftB THEN next[handle] ELSE error[handle, 801];
IF item=number THEN {
checkPointInterval← value;
next[handle]
}
ELSE error[handle, 809, FALSE];
IF item=rightB THEN next[handle] ELSE error[handle, 802];
}
ENDCASE=> GOTO err1;
IF item=eof THEN EXIT;
IF item=semi THEN next[handle] ELSE error[handle, 800,, FALSE];
REPEAT
err1=> error[handle, 821, TRUE];
ENDLOOP;
}; -- run
IF ForcedDump[handle] THEN dumpAll[handle, handle.vars.lastTime];
ErrWarnSummary[handle];
killPlot[]
GOTO stop;
EXITS
dumpStop=> {
dumpAll[handle, handle.vars.lastTime];
handle.msgStream.PutF["Last state is dumped in the dump file."];
CleanIt[handle];
};
stop=> CleanIt[handle];
}; -- Simulate
InitVars: PROC[handle: Handle]= {
handle.vars← NEW[Variables← [ ]];
{OPEN handle.vars;
simTime ← BasicTime.Now[];
line← RefText.New[256];
newString← RefText.New[256];
line.length← 0;
newString.length← 0;
fileStack← NEW[fileStackSeq[maxInclude]];
FOR i: NAT IN [0..maxInclude) DO fileStack[i] ← NIL ENDLOOP;
fileNameStack← NEW[fileNameStackSeq[maxInclude]];
FOR i: NAT IN [0..maxInclude) DO fileNameStack[i] ← NIL ENDLOOP;
prints← NEW[PrintSeq[maxPrints]];
FOR i: NAT IN [0..maxPrints) DO prints[i] ← [] ENDLOOP;
plots← NEW[PlotSeq[maxPlots]];
FOR i: NAT IN [0..maxPlots) DO plots[i] ← [] ENDLOOP;
worstNodeLog← NEW[WorstNodeLog[maxLog]];
FOR i: NAT IN [0..maxLog) DO worstNodeLog[i] ← []; ENDLOOP;
};
}; -- InitVars
}.
CHANGE LOG
Wilhelm, April 27, 1982 4:07 PM
Barth, 7-May-82 14:41:52 PDT
Chen, April 19, 1983 6:45 PM, changed the version name for openSysWindow.
Barth, July 11, 1983 12:46 PM
Chen, June 12, 1984 11:37:19 am PDT, cedarized.
Chen, May 15, 1985 5:23:49 pm PDT, Thyme viewer is inhibited from being destroyed by user when simulation is running.
Chen, July 22, 1985 8:09:51 pm PDT, => Cedar6.0.