RoseRunImpl.mesa
Last Edited by: Spreitzer, October 7, 1984 4:27:18 pm PDT PDT
Last Edited by: Barth, April 25, 1984 9:54:24 am PST
Last Edited by: Gasbarro, July 17, 1984 4:24:09 pm PDT
DIRECTORY IO, List, OrderedSymbolTableRef, Rope, RoseEvents, RoseIOHacks, RoseRun, RoseTypes;
RoseRunImpl:
CEDAR
PROGRAM
IMPORTS RoseEvents, RoseIOHacks, RoseTypes
EXPORTS RoseRun, RoseTypes =
BEGIN OPEN RoseTypes;
stop: PUBLIC BOOLEAN ← FALSE;
notInStrList: PUBLIC Structure ← NEW [StructureRep];
notInCellList: PUBLIC Cell ← NEW [CellRep];
notInNodeList: PUBLIC Node ← NEW [NodeRep];
StrEvals:
PUBLIC EvalProcs ← [
InitQ: StrInitQ,
PropQ: StrPropQ,
InitUD: StrInitUD,
PropUD: StrPropUD,
FinalUD: StrFinalUD,
EvalSimple: StrSimple,
FindVicinity: StrFindVicinity
];
StrMirrorEvals:
PUBLIC EvalProcs ← [
InitQ: StrInitQ,
PropQ: StrMirrorPropQ,
InitUD: StrInitUD,
PropUD: StrMirrorPropUD,
FinalUD: StrFinalUD,
EvalSimple: StrMirrorSimple,
FindVicinity: StrMirrorFindVicinity
];
SocketToWP:
PUBLIC
PROC [s: Socket, useBryant:
BOOL ←
FALSE]
RETURNS [wp: WordPtr] =
TRUSTED BEGIN
wp ← (IF useBryant THEN s.cell.realCellStuff.switchIOAsWP ELSE s.cell.realCellStuff.newIOAsWP) + s.cell.type.ports[s.index].firstWord;
END;
CellToStr:
PUBLIC
PROC [cell: Cell]
RETURNS [str: Structure] =
BEGIN
WHILE (IF cell.realCellStuff = NIL THEN TRUE ELSE IF cell.realCellStuff.state = NIL THEN TRUE ELSE NOT ISTYPE[cell.realCellStuff.state, Structure]) DO cell ← cell.parent ENDLOOP;
RETURN [NARROW[cell.realCellStuff.state]];
END;
Run:
PUBLIC
PROC [sim: Simulation] =
BEGIN
WHILE StepSim[sim] # noStep
DO
IF stop THEN SIGNAL Stop[msg: "Stopped", data: sim];
ENDLOOP;
END;
Next:
PUBLIC
PROC [sim: Simulation]
RETURNS [stepType: RoseRun.StepType] =
BEGIN
topStr: Structure;
topStr ← NARROW[sim.root.realCellStuff.state];
IF sim.switched AND topStr.schedFirst # NIL THEN RETURN [otherStep];
IF sim.firstPerturbedStr # NIL THEN RETURN [switchStep];
IF topStr.schedFirst # NIL THEN RETURN [otherStep];
stepType ← noStep;
END;
StepSim:
PUBLIC
PROC [sim: Simulation]
RETURNS [stepType: RoseRun.StepType] =
BEGIN
SELECT stepType ← Next[sim]
FROM
noStep => {
wasSettled: BOOL ← sim.wasSettled;
sim.wasSettled ← TRUE;
IF NOT wasSettled THEN RoseEvents.Notify[event: $Settled, watched: sim, handleAborted: TRUE];
};
switchStep => {
sim.wasSettled ← FALSE;
SwitchStepSim[sim];
};
otherStep => {
sim.wasSettled ← FALSE;
sim.root.realCellStuff.evals.EvalSimple[sim.root];
sim.switched ← FALSE;
};
ENDCASE => ERROR;
END;
SwitchStepSim:
PROC [sim: Simulation] =
BEGIN
str: Structure;
sim.firstWasPerturbedStr ← sim.firstPerturbedStr;
sim.firstPerturbedStr ← NIL;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed
WHILE str #
NIL
DO
IF str = notInStrList THEN ERROR;
IF str.nextPerturbed = notInStrList THEN ERROR;
str.nextWasPerturbed ← str.nextPerturbed;
str.nextPerturbed ← notInStrList;
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed
WHILE str #
NIL
DO
IF str.container.realCellStuff.evals # StrEvals THEN ERROR;
StrFindVicinity[str.container, noPort, FALSE];
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed
WHILE str #
NIL
DO
IF
NOT str.container.realCellStuff.initQed
THEN {
str.container.realCellStuff.initQed ← TRUE;
StrInitQ[str.container]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed
WHILE str #
NIL
DO
IF
NOT str.container.realCellStuff.propQed
THEN {
str.container.realCellStuff.propQed ← TRUE;
StrPropQWork[str, IF str.mirror = NIL THEN str.container ELSE str.mirror, str.insideNodes, TRUE]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed
WHILE str #
NIL
DO
IF
NOT str.container.realCellStuff.initUDed
THEN {
str.container.realCellStuff.initUDed ← TRUE;
StrInitUD[str.container]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed
WHILE str #
NIL
DO
IF
NOT str.container.realCellStuff.propUDed
THEN {
str.container.realCellStuff.propUDed ← TRUE;
StrPropUDWork[str, IF str.mirror = NIL THEN str.container ELSE str.mirror, str.insideNodes, TRUE]}
ENDLOOP;
FOR str ← sim.firstWasPerturbedStr, str.nextWasPerturbed
WHILE str #
NIL
DO
StrFinalUD[str.container];
str.container.realCellStuff.initQed ← str.container.realCellStuff.propQed ← str.container.realCellStuff.initUDed ← str.container.realCellStuff.propUDed ← FALSE;
ENDLOOP;
sim.switched ← TRUE;
END;
PerturbNode:
PUBLIC
PROC [node: Node, within: Cell, evenIfInput:
BOOL ←
FALSE] =
{ReallyPerturb[node, CellToStr[within], within.sim, within, evenIfInput]};
PerturbPort:
PUBLIC
PROC [cell: Cell, index:
CARDINAL, evenIfInput:
BOOL ←
FALSE] =
{ReallyPerturb[cell.interfaceNodes[index], ContainingStr[cell], cell.sim, cell, evenIfInput]};
ReallyPerturb:
PROC [node: Node, str: Structure, sim: Simulation, cell: Cell, evenIfInput:
BOOL ←
FALSE] =
BEGIN
IF node.type.simple THEN ERROR;
IF node.isInput AND NOT evenIfInput THEN RETURN;
IF node.nextPerturbed = notInNodeList
THEN {
IF str.firstPerturbed = notInNodeList THEN ERROR;
node.nextPerturbed ← str.firstPerturbed;
str.firstPerturbed ← node;
IF str.nextPerturbed = notInStrList
THEN {
IF sim.firstPerturbedStr = notInStrList THEN ERROR;
str.nextPerturbed ← sim.firstPerturbedStr;
sim.firstPerturbedStr ← str;
};
RoseEvents.Notify[event: $Perturbed, watched: node, handleAborted: TRUE, arg: cell];
};
END;
FindExteriorVicinity:
PUBLIC
PROC [cell: Cell, index:
CARDINAL, evenIfInput:
BOOL ←
FALSE] =
BEGIN
ReallyFindVicinity[ContainingStr[cell], cell.interfaceNodes[index], evenIfInput, [cell, index]];
END;
ReallyFindVicinity:
PROC [str: Structure, n: Node, evenIfInput:
BOOL, from: Socket] =
BEGIN
IF n.found THEN RETURN;
IF n.isInput AND NOT evenIfInput THEN RETURN;
n.found ← TRUE;
IF str.firstAffected = notInNodeList THEN ERROR;
n.nextAffected ← str.firstAffected;
str.firstAffected ← n;
RoseEvents.Notify[$Found, n, TRUE, from.cell];
FOR sl: SocketList ← n.readers, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.evals.FindVicinity # NIL THEN sl.first.cell.realCellStuff.evals.FindVicinity[sl.first.cell, sl.first.index, evenIfInput];
sl.first.cell.realCellStuff.affectedFlags[read][Specialty[sl.first]] ← TRUE;
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.evals.FindVicinity # NIL THEN sl.first.cell.realCellStuff.evals.FindVicinity[sl.first.cell, sl.first.index, evenIfInput];
sl.first.cell.realCellStuff.affectedFlags[read][Specialty[sl.first]] ← TRUE;
sl.first.cell.realCellStuff.affectedFlags[write][Specialty[sl.first]] ← TRUE;
ENDLOOP;
FOR sl: SocketList ← n.writers, sl.rest
WHILE sl #
NIL
DO
sl.first.cell.realCellStuff.affectedFlags[write][Specialty[sl.first]] ← TRUE;
ENDLOOP;
END;
Specialty:
PROC [st: Socket]
RETURNS [sy: Speciality] =
{sy ← IF st.cell.type.ports[st.index].special AND NotAgg[st.cell] THEN special ELSE general};
NotAgg:
PROC [cell: Cell]
RETURNS [notAgg:
BOOL] =
INLINE
{notAgg ← cell.expansion = Leaf AND CellToStr[cell.parent].mirror # cell};
StrFindVicinity:
PROC [cell: Cell, portIndex:
CARDINAL, evenIfInput:
BOOL] =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
this: Node;
IF portIndex # noPort THEN ReallyFindVicinity[str, str.insideNodes[portIndex], evenIfInput, [str.mirror, portIndex]];
WHILE str.firstPerturbed #
NIL
DO
IF str.firstPerturbed = notInNodeList THEN ERROR;
this ← str.firstPerturbed;
str.firstPerturbed ← this.nextPerturbed;
this.nextPerturbed ← notInNodeList;
ReallyFindVicinity[str, this, this.isInput, [NIL, LAST[CARDINAL]]];
ENDLOOP;
END;
StrMirrorFindVicinity:
PROC [cell: Cell, portIndex:
CARDINAL, evenIfInput:
BOOL] =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
unmirrored: Cell← cell.parent;
this: Node;
IF portIndex # noPort THEN ReallyFindVicinity[str, unmirrored.interfaceNodes[portIndex], evenIfInput, [unmirrored, portIndex]];
WHILE str.firstPerturbed #
NIL
DO
IF str.firstPerturbed = notInNodeList THEN ERROR;
this ← str.firstPerturbed;
str.firstPerturbed ← this.nextPerturbed;
this.nextPerturbed ← notInNodeList;
ReallyFindVicinity[str, this, this.isInput, [NIL, LAST[CARDINAL]]];
ENDLOOP;
END;
Need1:
PROC [str: Structure, n: Node, also: CellProc] =
BEGIN
FOR sl: SocketList ← n.writers, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList
THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
IF also # NIL THEN also[sl.first.cell];
END;
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList
THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
IF also # NIL THEN also[sl.first.cell];
END;
ENDLOOP;
FOR sl: SocketList ← n.readers, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList
THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
IF also # NIL THEN also[sl.first.cell];
END;
ENDLOOP;
END;
Need2:
PROC [str: Structure, n: Node, except: Cell] =
BEGIN
FOR sl: SocketList ← n.readers, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList
AND sl.first.cell # except
AND (sl.first.cell.realCellStuff.affectedFlags[write][special]
OR sl.first.cell.realCellStuff.affectedFlags[write][general])
THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
END;
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNeeded = notInCellList
AND sl.first.cell # except
THEN
BEGIN
IF str.firstNeeded = notInCellList THEN ERROR;
sl.first.cell.realCellStuff.nextNeeded ← str.firstNeeded;
str.firstNeeded ← sl.first.cell;
END;
ENDLOOP;
END;
InitQ: CellProc
--PROC [cell: Cell]-- = {
IF
NOT cell.realCellStuff.initQed
THEN {
cell.realCellStuff.initQed ← TRUE;
IF cell.realCellStuff.evals.InitQ # NIL THEN cell.realCellStuff.evals.InitQ[cell]}};
StrInitQ: CellProc
--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
FOR n: Node ← str.firstAffected, n.nextAffected
WHILE n #
NIL
DO
IF n = notInNodeList THEN ERROR;
IF n.type.procs.InitQ # NIL THEN n.type.procs.InitQ[n];
RoseEvents.Notify[event: $NewNodeQ, watched: n, handleAborted: TRUE, arg: NIL];
Need1[str, n, InitQ];
ENDLOOP;
END;
StrPropQ: CellProc
--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
StrPropQWork[str, IF str.mirror = NIL THEN cell ELSE str.mirror, str.insideNodes, FALSE];
END;
StrMirrorPropQ: CellProc
--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
StrPropQWork[str, cell.parent, cell.parent.interfaceNodes, FALSE];
END;
StrPropQWork:
PROC [str: Structure, innerBorder: Cell, borderNodes: NodeS, top:
BOOLEAN] =
BEGIN
IF
NOT top
THEN
FOR index:
CARDINAL
IN [0 .. innerBorder.type.ports.length)
DO
inside: Node ← borderNodes[index];
IF inside.type.procs.NewQ = NIL THEN LOOP;
IF inside.type.procs.NewQ[inside, SocketToWP[[innerBorder, index],
TRUE]]
THEN {
RoseEvents.Notify[event: $NewNodeQ, watched: inside, handleAborted: TRUE, arg: innerBorder];
Need2[str, inside, innerBorder];
};
ENDLOOP;
WHILE str.firstNeeded #
NIL
DO
needed: Cell ← str.firstNeeded;
IF needed = notInCellList THEN ERROR;
str.firstNeeded ← needed.realCellStuff.nextNeeded;
needed.realCellStuff.nextNeeded ← notInCellList;
needed.realCellStuff.initQed ← FALSE;
IF (needed.realCellStuff.evals.PropQ = NIL) AND (NOT (needed.type.hasASpecialPort AND NotAgg[needed])) THEN LOOP;
FOR index:
CARDINAL
IN [0 .. needed.type.ports.length)
DO
IF needed.type.ports[index].type.procs.QFromNode # NIL THEN needed.type.ports[index].type.procs.QFromNode[needed.interfaceNodes[index], SocketToWP[[needed, index], TRUE]];
ENDLOOP;
PropInner[needed, needed.realCellStuff.evals.PropQ];
FOR index:
CARDINAL
IN [0 .. needed.type.ports.length)
DO
inside: Node ← needed.interfaceNodes[index];
IF inside.type.procs.NewQ = NIL OR NOT needed.type.ports[index].output THEN LOOP;
IF inside.nextAffected = notInNodeList THEN ERROR;
IF inside.type.procs.NewQ[inside, SocketToWP[[needed, index],
TRUE]]
THEN {
RoseEvents.Notify[event: $NewNodeQ, watched: inside, handleAborted: TRUE, arg: needed];
Need2[str, inside, needed];
};
ENDLOOP;
ENDLOOP;
IF
NOT top
THEN
FOR index:
CARDINAL
IN [0 .. innerBorder.type.ports.length)
DO
inside: Node ← borderNodes[index];
IF inside.type.procs.QFromNode = NIL THEN LOOP;
inside.type.procs.QFromNode[inside, SocketToWP[[innerBorder, index], TRUE]];
ENDLOOP;
END;
PropInner:
PROC [cell: Cell, prop: CellProc] =
BEGIN
IF cell.type.hasASpecialPort
AND NotAgg[cell]
THEN RoseIOHacks.CopyIO[
from: cell.realCellStuff.newIOAsWP,
to: cell.realCellStuff.switchIOAsWP,
by: cell.type.ports,
what: [inputs: none, outputs: forward, bidirs: forward],
specials: TRUE, generals: FALSE, simples: FALSE, drive: NIL];
IF prop # NIL THEN prop[cell];
END;
InitUD: CellProc
--PROC [cell: Cell]-- = {
IF
NOT cell.realCellStuff.initUDed
THEN {
cell.realCellStuff.initUDed ← TRUE;
IF cell.realCellStuff.evals.InitUD # NIL THEN cell.realCellStuff.evals.InitUD[cell]}};
StrInitUD: CellProc
--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
FOR n: Node ← str.firstAffected, n.nextAffected
WHILE n #
NIL
DO
IF n = notInNodeList THEN ERROR;
IF n.type.procs.InitUD # NIL THEN n.type.procs.InitUD[n];
RoseEvents.Notify[event: $NewNodeUD, watched: n, handleAborted: TRUE, arg: NIL];
Need1[str, n, InitUD];
ENDLOOP;
END;
StrPropUD: CellProc
--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
StrPropUDWork[str, IF str.mirror = NIL THEN cell ELSE str.mirror, str.insideNodes, FALSE];
END;
StrMirrorPropUD: CellProc
--PROC [cell: Cell]-- =
BEGIN
StrPropUDWork[NARROW[cell.realCellStuff.state], cell.parent, cell.parent.interfaceNodes, FALSE];
END;
StrPropUDWork:
PROC [str: Structure, innerBorder: Cell, borderNodes: NodeS, top:
BOOLEAN] =
BEGIN
IF
NOT top
THEN
FOR index:
CARDINAL
IN [0 .. innerBorder.type.ports.length)
DO
inside: Node ← borderNodes[index];
IF inside.type.procs.NewUD = NIL THEN LOOP;
IF inside.type.procs.NewUD[inside, SocketToWP[[innerBorder, index],
TRUE]]
THEN {
RoseEvents.Notify[event: $NewNodeUD, watched: inside, handleAborted: TRUE, arg: innerBorder];
Need2[str, inside, innerBorder];
};
ENDLOOP;
WHILE str.firstNeeded #
NIL
DO
needed: Cell ← str.firstNeeded;
IF needed = notInCellList THEN ERROR;
str.firstNeeded ← needed.realCellStuff.nextNeeded;
needed.realCellStuff.nextNeeded ← notInCellList;
needed.realCellStuff.initUDed ← FALSE;
IF (needed.realCellStuff.evals.PropUD = NIL) AND (NOT (needed.type.hasASpecialPort AND NotAgg[needed])) THEN LOOP;
FOR index:
CARDINAL
IN [0 .. needed.type.ports.length)
DO
IF needed.type.ports[index].type.procs.UDFromNode # NIL THEN needed.type.ports[index].type.procs.UDFromNode[needed.interfaceNodes[index], SocketToWP[[needed, index], TRUE]];
ENDLOOP;
PropInner[needed, needed.realCellStuff.evals.PropUD];
FOR index:
CARDINAL
IN [0 .. needed.type.ports.length)
DO
inside: Node ← needed.interfaceNodes[index];
IF inside.type.procs.NewUD = NIL OR NOT needed.type.ports[index].output THEN LOOP;
IF inside.nextAffected = notInNodeList THEN ERROR;
IF inside.type.procs.NewUD[inside, SocketToWP[[needed, index],
TRUE]]
THEN {
RoseEvents.Notify[event: $NewNodeUD, watched: inside, handleAborted: TRUE, arg: needed];
Need2[str, inside, needed];
};
ENDLOOP;
ENDLOOP;
IF
NOT top
THEN
FOR index:
CARDINAL
IN [0 .. innerBorder.type.ports.length)
DO
inside: Node ← borderNodes[index];
IF inside.type.procs.UDFromNode = NIL THEN LOOP;
inside.type.procs.UDFromNode[inside, SocketToWP[[innerBorder, index], TRUE]];
ENDLOOP;
END;
StrFinalUD: CellProc
--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
firstNoted, next: Cell ← NIL;
FOR n: Node ← str.firstAffected, n.nextAffected
WHILE n #
NIL
DO
IF n = notInNodeList THEN ERROR;
n.found ← FALSE;
IF n.type.procs.NewVal # NIL THEN n.type.procs.NewVal[n];
theActivityReport.node ← n;
theActivityReport.socket ← [NIL, noPort];
RoseEvents.Notify[event: $ChangeEarly, watched: n, handleAborted: TRUE];
RoseEvents.Notify[event: $ChangeLate, watched: n, handleAborted: TRUE];
RoseEvents.Notify[event: $SwitchChanged, arg: theActivityReport, handleAborted: TRUE];
FOR sl: SocketList ← n.readers, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNoted = notInCellList
THEN
{sl.first.cell.realCellStuff.nextNoted ← firstNoted; firstNoted ← sl.first.cell};
ENDLOOP;
FOR sl: SocketList ← n.bidirs, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNoted = notInCellList
THEN
{sl.first.cell.realCellStuff.nextNoted ← firstNoted; firstNoted ← sl.first.cell};
ENDLOOP;
FOR sl: SocketList ← n.writers, sl.rest
WHILE sl #
NIL
DO
IF sl.first.cell.realCellStuff.nextNoted = notInCellList
THEN
{sl.first.cell.realCellStuff.nextNoted ← firstNoted; firstNoted ← sl.first.cell};
ENDLOOP;
ENDLOOP;
str.firstAffected ← NIL;
FOR firstNoted ← firstNoted, next
WHILE firstNoted #
NIL
DO
IF firstNoted = notInCellList THEN ERROR;
next ← firstNoted.realCellStuff.nextNoted;
firstNoted.realCellStuff.nextNoted ← notInCellList;
FOR index:
CARDINAL
IN [0 .. firstNoted.type.ports.length)
DO
ntp: NodeProcs ← firstNoted.type.ports[index].type.procs;
IF ntp.ValFromNode #
NIL
THEN ntp.ValFromNode[
firstNoted.interfaceNodes[index],
SocketToWP[[firstNoted, index], TRUE]];
IF SocketIsSpecial[[firstNoted, index]]
AND ntp.UDFromNode #
NIL
THEN ntp.UDFromNode[
firstNoted.interfaceNodes[index],
SocketToWP[[firstNoted, index], TRUE]];
ENDLOOP;
IF firstNoted.realCellStuff.evals.FinalUD # NIL THEN firstNoted.realCellStuff.evals.FinalUD[firstNoted];
IF firstNoted.realCellStuff.affectedFlags[read][special]
THEN ScheduleCell[firstNoted];
IF (firstNoted.realCellStuff.affectedFlags[read][general]
OR firstNoted.realCellStuff.affectedFlags[read][special])
AND firstNoted.realCellStuff.evals.ValsChanged #
NIL
THEN ValsChanged[firstNoted, str];
firstNoted.realCellStuff.affectedFlags ← ALL[ALL[FALSE]];
ENDLOOP;
END;
ValsChanged:
PROC [cell: Cell, str: Structure] =
BEGIN
NewToOld[cell];
cell.realCellStuff.evals.ValsChanged[cell
!UNWIND => [] ← ReallyCleanUpAfterModify[cell: cell, str: str, outputsOnly: TRUE, blindly: FALSE, mayRescheduleSelf: TRUE, simples: TRUE, generals: FALSE, specials: TRUE]];
[] ← ReallyCleanUpAfterModify[cell: cell, str: str, outputsOnly: TRUE, blindly: FALSE, mayRescheduleSelf: TRUE, simples: TRUE, generals: FALSE, specials: TRUE];
END;
StrSimple: CellProc
--PROC [cell: Cell]-- =
BEGIN
str: Structure ← NARROW[cell.realCellStuff.state];
IF str.running
THEN
ERROR
ELSE str.running ←
TRUE;
BEGIN ENABLE UNWIND => {str.running ← FALSE};
FOR portIndex:
CARDINAL
IN [0 .. cell.type.ports.length)
DO
port: Port ← cell.type.ports[portIndex];
IF
NOT port.type.simple
THEN
LOOP;
TRUSTED BEGIN
Distribute[
cell.realCellStuff.newIOAsWP + port.firstWord,
str.insideNodes[portIndex],
NIL,
str];
END;
ENDLOOP;
RunStr[str];
END;
str.running ← FALSE;
END;
StrMirrorSimple: CellProc
--PROC [cell: Cell]-- =
{ERROR Error["Attempt to evaluate mirror's other", cell]};
ValueChanged:
PUBLIC
PROC [node: Node] =
BEGIN
IF node.type.simple THEN ERROR;
PerturbNode[node, node.cellIn, TRUE];
RoseEvents.Notify[event: $ChangeEarly, watched: node, handleAborted: TRUE];
RoseEvents.Notify[event: $ChangeLate, watched: node, handleAborted: TRUE];
END;
Distribute:
PROC [base: WordPtr, fromNode: Node, fromCell: Cell, str: Structure] =
BEGIN
DoDest:
PROC [dest: Socket] =
BEGIN
target: Cell ← dest.cell;
targPort: Port ← target.type.ports[dest.index];
sourceWP: WordPtr ← base;
destWP: WordPtr;
IF target =
NIL
THEN
ERROR;
TRUSTED BEGIN
destWP ← target.realCellStuff.newIOAsWP + targPort.firstWord;
END;
FOR j:
CARDINAL
IN [0 .. targPort.wordCount)
DO
TRUSTED
BEGIN
destWP^ ← sourceWP^;
sourceWP ← sourceWP + 1;
destWP ← destWP + 1;
END;
ENDLOOP;
IF target = fromCell THEN NULL
ELSE
IF target = str.mirror
THEN {
IF
NOT str.running
THEN {
parentCell: Cell ← str.container;
parentStr: Structure ← ContainingStr[parentCell];
Distribute[base: SocketToWP[[parentCell, dest.index]], fromNode: parentCell.interfaceNodes[dest.index], fromCell: parentCell, str: parentStr];
ScheduleAllup[parentCell, parentStr];
};
}
ELSE ScheduleAllup[target, str];
END;
abort: BOOLEAN ← FALSE;
IF fromNode.type.procs.SetNode # NIL THEN fromNode.type.procs.SetNode[fromNode, base];
FOR dests: SocketList ← fromNode.readers, dests.rest
WHILE dests #
NIL
DO
DoDest[dests.first] ENDLOOP;
FOR dests: SocketList ← fromNode.bidirs, dests.rest
WHILE dests #
NIL
DO
DoDest[dests.first] ENDLOOP;
FOR dests: SocketList ← fromNode.writers, dests.rest
WHILE dests #
NIL
DO
DoDest[dests.first] ENDLOOP;
RoseEvents.Notify[event: $ChangeEarly, watched: fromNode, handleAborted: TRUE];
RoseEvents.Notify[event: $ChangeLate, watched: fromNode, handleAborted: TRUE];
END;
ScheduleStep:
PROC [cell: Cell, str: Structure] =
BEGIN
IF cell.realCellStuff.schedNext # notInCellList THEN RETURN;
cell.realCellStuff.schedNext ← NIL;
IF str.schedLast = NIL THEN str.schedFirst ← cell ELSE str.schedLast.realCellStuff.schedNext ← cell;
str.schedLast ← cell;
RoseEvents.Notify[event: $Schedule, watched: cell, handleAborted: TRUE];
END;
ScheduleAllup:
PROC [cell: Cell, str: Structure] =
BEGIN
IF cell.parent #
NIL
THEN
DO
IF cell.realCellStuff.schedNext # notInCellList THEN RETURN;
cell.realCellStuff.schedNext ← NIL;
IF str.schedLast = NIL THEN str.schedFirst ← cell ELSE str.schedLast.realCellStuff.schedNext ← cell;
str.schedLast ← cell;
RoseEvents.Notify[event: $Schedule, watched: cell, handleAborted: TRUE];
IF str.running THEN RETURN;
IF (cell ← str.container).parent = NIL THEN RETURN;
str ← ContainingStr[cell];
ENDLOOP;
END;
NewToOld:
PUBLIC
PROC [cell: Cell] =
TRUSTED
BEGIN
n: WordPtr ← cell.realCellStuff.newIOAsWP;
o: WordPtr ← cell.realCellStuff.oldIOAsWP;
FOR i:
CARDINAL
IN [0 .. cell.type.ioWordCount)
DO
(o+i)^ ← (n+i)^;
ENDLOOP;
END;
PreSimple:
PUBLIC
PROC [cell: Cell] =
TRUSTED
BEGIN
n: WordPtr ← cell.realCellStuff.newIOAsWP;
o: WordPtr ← cell.realCellStuff.oldIOAsWP;
FOR i:
CARDINAL
IN [0 .. cell.type.ioWordCount)
DO
(o+i)^ ← (n+i)^;
ENDLOOP;
IF cell.type.hasASpecialPort
AND NotAgg[cell]
THEN
FOR portIndex:
CARDINAL
IN [0 .. cell.type.ports.length)
DO
port: Port ← cell.type.ports[portIndex];
IF port.special
THEN {
n: WordPtr ← cell.realCellStuff.newIOAsWP + port.firstWord;
s: WordPtr ← cell.realCellStuff.switchIOAsWP + port.firstWord;
FOR i:
CARDINAL
IN [0 .. port.wordCount)
DO
(n+i)^ ← (s+i)^;
ENDLOOP;
};
ENDLOOP;
END;
RunStr:
PROC [str: Structure] =
BEGIN
WHILE str.schedFirst #
NIL
DO
cell: Cell;
IF str.schedFirst = notInCellList THEN ERROR;
IF stop THEN SIGNAL Stop[msg: "Stopped", data: str];
cell ← PickFromSchedule[str];
IF cell.realCellStuff.evals.EvalSimple #
NIL
THEN
BEGIN
PreSimple[cell];
cell.realCellStuff.evals.EvalSimple[cell !
UNWIND => {
[] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE];
ScheduleAllup[cell, str];
}];
[] ← ReallyCleanUpAfterModify[cell, str, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE];
RoseEvents.Notify[event: $Eval, watched: cell, handleAborted: TRUE];
END;
ENDLOOP;
END;
PickFromSchedule:
PROC [str: Structure]
RETURNS [cell: Cell] =
BEGIN
abort: BOOLEAN ← FALSE;
cell ← str.schedFirst;
IF (str.schedFirst ← cell.realCellStuff.schedNext) = NIL THEN str.schedLast ← NIL;
cell.realCellStuff.schedNext ← notInCellList;
RoseEvents.Notify[event: $Schedule, watched: cell, handleAborted: TRUE];
IF str.schedFirst = NIL THEN RETURN;
RoseEvents.Notify[event: $Schedule, watched: str.schedFirst, handleAborted: TRUE];
END;
ReallyCleanUpAfterModify:
PROC [cell: Cell, str: Structure, outputsOnly, blindly, mayRescheduleSelf, simples, generals, specials:
BOOLEAN]
RETURNS [anyDiff:
BOOLEAN] =
BEGIN
anyDiff ← FALSE;
FOR portIndex:
CARDINAL
IN [0 .. cell.type.ports.length)
DO
port: Port ← cell.type.ports[portIndex];
node: Node ← cell.interfaceNodes[portIndex];
diff: BOOLEAN ← FALSE;
newWP: WordPtr;
oldWP: WordPtr;
IF (outputsOnly AND NOT port.output) THEN LOOP;
IF NOT (IF port.type.simple THEN simples ELSE IF port.special AND NotAgg[cell] THEN specials ELSE generals) THEN LOOP;
TRUSTED
BEGIN
newWP ← cell.realCellStuff.newIOAsWP + port.firstWord;
oldWP ← cell.realCellStuff.oldIOAsWP + port.firstWord;
END;
IF blindly THEN diff ← TRUE
ELSE
BEGIN
IF port.special AND (NOT port.type.simple) AND NotAgg[cell] AND (port.type.procs.ComputeQ # NIL) THEN port.type.procs.ComputeQ[node, newWP];
FOR i:
CARDINAL
IN [0 .. port.wordCount)
DO
TRUSTED
BEGIN
IF newWP^ # oldWP^ THEN {diff ← TRUE; EXIT};
newWP ← newWP + 1;
oldWP ← oldWP + 1;
END;
ENDLOOP;
END;
IF diff
THEN
TRUSTED BEGIN
anyDiff ← TRUE;
theActivityReport.node ← node;
theActivityReport.socket ← node.visible ← [cell, portIndex];
IF port.type.simple
THEN {
Distribute[
cell.realCellStuff.newIOAsWP + port.firstWord,
node,
IF NOT mayRescheduleSelf THEN cell ELSE NIL,
str];
RoseEvents.Notify[event: $SimpleChanged, watched: NIL, handleAborted: TRUE, arg: theActivityReport];
}
ELSE {
ReallyPerturb[node: node, str: str, sim: cell.sim, cell: cell];
RoseEvents.Notify[event: $NewSpecialSwitchInstructions, watched: NIL, handleAborted: TRUE, arg: theActivityReport];
};
END;
ENDLOOP;
END;
theActivityReport: RoseRun.ActivityReport ← NEW [RoseRun.ActivityReportRep];
ScheduleCell:
PUBLIC
PROC [cell: Cell] =
{ScheduleAllup[cell, ContainingStr[cell]]};
AllowToModify:
PUBLIC
PROC [cell: Cell, modifier: RoseRun.ModifyProc, blindly, mayRescheduleSelf:
BOOLEAN ←
FALSE] =
BEGIN
str: Structure ← ContainingStr[cell];
subtle: BOOL ← FALSE;
IF NOT blindly THEN NewToOld[cell];
subtle ← modifier[cell !
UNWIND =>
BEGIN
[] ← ReallyCleanUpAfterModify[cell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
END];
[] ← ReallyCleanUpAfterModify[cell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
IF subtle THEN ScheduleAllup[cell, str];
END;
AllowToModify: PUBLIC PROC [cell: Cell, modifier: RoseRun.ModifyProc, blindly, mayRescheduleSelf: BOOLEAN ← FALSE] =
BEGIN
ReallyAllowToModify: RoseRun.ModifyProc--PROC [cell: Cell] RETURNS [subtle: BOOLEAN ← FALSE]-- =
BEGIN
--GetStrLock[str];--
IF NOT blindly THEN NewToOld[theCell];
subtle ← modifier[theCell !UNWIND =>
BEGIN
subtle ← ReallyCleanUpAfterModify[theCell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
--ReleaseStrLock[str];--
END];
IF subtle THEN ScheduleStep[theCell, str];
subtle ← subtle OR ReallyCleanUpAfterModify[theCell, str, FALSE, blindly, mayRescheduleSelf, TRUE, TRUE, TRUE];
--ReleaseStrLock[str];--
END;
theCell: Cell ← cell;
str: Structure ← NIL;
IF cell.parent = NIL THEN [] ← modifier[theCell]
ELSE IF (str ← CellToStr[cell.parent]).container.parent = NIL THEN [] ← ReallyAllowToModify[NIL]
ELSE AllowToModify[str.container, ReallyAllowToModify, FALSE];
END;
notInCellList.name ← "notInCellList";
notInNodeList.name ← "notInNodeList";
END.