RoseRunImpl.mesa
Last Edited by: Spreitzer, July 2, 1985 8:52:17 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 Basics, BitTwiddling, IO, List, OrderedSymbolTableRef, PrincOps, PrincOpsUtils, Rope, RoseCreate, RoseEvents, RoseRun, RoseTypes;
RoseRunImpl:
CEDAR
PROGRAM
IMPORTS BitTwiddling, IO, PrincOpsUtils, RoseCreate, RoseEvents, RoseTypes
EXPORTS RoseRun, RoseTypes =
Simulator Assumptions
A cell's newIO doesn't change, except when the cell's ValsChanged or EvalSimple is called, or when this module changes it.
An effective port is transduced iff the node connected to it is switch-level and the cell type speaks simple.
Simulator Invariants
All simple effective ports are always linked according to their curStrength, which tries to track what the cell is saying, but may get behind.
For simple ports, the cell's newIO always contains the current value.
For transduced effective ports, the newIO and switchIO fields are always related by Transduce.
BEGIN OPEN BitTwiddling, RoseTypes;
stop: PUBLIC BOOLEAN ← FALSE;
notInStrList: PUBLIC Structure ← NEW [StructureRep];
notInCellList: PUBLIC Cell ← NEW [CellRep];
notInNodeList: PUBLIC Node ← NEW [NodeRep];
reportSlot: REF Slot ← NEW [Slot];
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 ← sim.str;
IF topStr.schedFirst # NIL THEN RETURN [otherStep];
IF sim.str.firstPerturbed # NIL THEN RETURN [switchStep];
stepType ← noStep;
END;
StepSim:
PUBLIC
PROC [sim: Simulation]
RETURNS [stepType: RoseRun.StepType] =
BEGIN
SELECT stepType ← Next[sim]
FROM
noStep => NULL;
switchStep => SwitchStepSim[sim];
otherStep => SimpleStepSim[sim];
ENDCASE => ERROR;
IF stepType # noStep
AND Next[sim] = noStep
THEN {
RoseEvents.Notify[event: $Settled, watched: sim, handleAborted: TRUE];
CheckDelays[sim];
};
END;
SimpleStepSim:
PROC [sim: Simulation] = {
str: Structure ← sim.str;
IF str.running
THEN
ERROR
ELSE str.running ←
TRUE;
BEGIN ENABLE UNWIND => {str.running ← FALSE};
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
PerturbPort:
PROC [portIndex: PortIndex] = {
FOR epi: EffectivePortIndex ← cell.realCellStuff.effectivePorts[portIndex].firstEffectivePortIndex, epi+1
WHILE epi < cell.realCellStuff.effectivePorts.length
AND cell.realCellStuff.effectivePorts[epi].containingPort = portIndex
DO
ReallyPerturb[cell.realCellStuff.implNodes[epi], str, cell.sim, [cell, epi], FALSE];
ENDLOOP;
};
PreSimple[cell];
cell.realCellStuff.evals.EvalSimple[
cell: cell,
perturb: PerturbPort
!
UNWIND => {
ReallyCleanUpAfterModify[cell, str, TRUE, FALSE, FALSE];
Schedule[cell, str];
}
];
ReallyCleanUpAfterModify[cell, str, TRUE, FALSE, FALSE];
RoseEvents.Notify[event: $Eval, watched: cell, handleAborted: TRUE];
END;
END;
str.running ← FALSE;
};
PickFromSchedule:
PROC [str: Structure]
RETURNS [cell: Cell] =
BEGIN
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;
ScheduleCell:
PUBLIC
PROC [cell: Cell] =
{Schedule[cell, ContainingStr[cell]]};
Schedule:
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;
PreSimple:
PUBLIC
PROC [cell: Cell, reallyCopy:
BOOL ←
TRUE] =
TRUSTED
BEGIN
IF reallyCopy
AND cell.realCellStuff.hasTransducedPort
THEN {
n: WordPtr ← cell.realCellStuff.newIOAsWP;
o: WordPtr ← cell.realCellStuff.oldIOAsWP;
FOR i:
CARDINAL
IN [0 .. cell.type.simpleWordCount)
DO
(o+i)^ ← (n+i)^;
ENDLOOP;
FOR portIndex: PortIndex
IN [0 .. cell.type.ports.length)
DO
cell.realCellStuff.oldDrive[portIndex] ← cell.realCellStuff.newDrive[portIndex];
ENDLOOP;
};
END;
ReallyCleanUpAfterModify:
PROC [cell: Cell, str: Structure, outputsOnly, blindly, mayRescheduleSelf:
BOOLEAN] =
BEGIN
bbTableSpace: PrincOps.BBTableSpace;
bbTable: PrincOps.BitBltTablePtr;
TRUSTED {bbTable ← PrincOpsUtils.AlignedBBTable[@bbTableSpace]};
FOR effectivePortIndex: EffectivePortIndex
IN [0 .. cell.realCellStuff.effectivePorts.length)
DO
ep: EffectivePort ← cell.realCellStuff.effectivePorts[effectivePortIndex];
node: Node;
newStrength: Strength;
valDiff, strengthDiff: BOOLEAN ← FALSE;
newPtr: Ptr;
simpleBits: NAT;
IF NOT ep.type.simple THEN LOOP;
newStrength ← cell.realCellStuff.newDrive[ep.containingPort];
IF (NOT ep.output) AND newStrength > ignore THEN ERROR Error[IO.PutFR["%g lied about outputness of port %g", IO.rope[RoseCreate.LongCellName[cell]], IO.rope[ep.name]]];
IF outputsOnly AND NOT ep.output THEN LOOP;
node ← cell.realCellStuff.implNodes[effectivePortIndex];
newPtr ← WPField[cell.realCellStuff.newIOAsWP, ep.simple];
simpleBits ← ep.type.procs.Bits[ep.type].data;
IF TransduceNeeded[ep.type, ep.implType]
THEN {
oldStrength: Strength ← cell.realCellStuff.oldDrive[ep.containingPort];
oldPtr: Ptr ← WPField[cell.realCellStuff.oldIOAsWP, ep.simple];
IF blindly THEN valDiff ← strengthDiff ← TRUE
ELSE {
strengthDiff ← oldStrength # newStrength;
valDiff ← NOT Equal[oldPtr, newPtr, simpleBits];
};
IF valDiff
OR strengthDiff
THEN {
implPtr: Ptr ← WPField[cell.realCellStuff.switchIOAsWP, ep.switch];
ep.type.procs.Transduce[fromS: newStrength, fromT: ep.type, toT: ep.implType, fromP: newPtr, toP: implPtr];
};
IF (valDiff
AND newStrength >= node.strength)
OR (strengthDiff
AND (newStrength >= node.strength
OR oldStrength >= node.strength))
THEN {
ReallyPerturb[node: node, str: str, sim: cell.sim, agitator: [cell, effectivePortIndex]];
};
}
ELSE {
strengthDiff ← newStrength # cell.realCellStuff.effectivePorts[effectivePortIndex].curStrength;
valDiff ← NOT Equal[newPtr, node.valPtr, node.bitCount];
IF strengthDiff
THEN {
ReStrengthLink[node, [cell, effectivePortIndex], newStrength];
IF EmptyStrengthSet[node, node.currentStrength] OR newStrength > node.currentStrength THEN UpdateCurrent[node, bbTable, [cell, effectivePortIndex]];
};
IF newStrength > node.currentStrength THEN ERROR;
IF newStrength = node.currentStrength
THEN {
IF valDiff
THEN {
alone: BOOL ← ep.strengthNext = head AND ep.strengthPrev = head AND newStrength > node.strength;
IF alone
THEN
--alone at the top-- {
Distribute[
base: newPtr,
fromNode: node,
avoidCell: IF NOT mayRescheduleSelf THEN cell ELSE NIL,
str: str,
bitCount: node.bitCount,
bbTable: bbTable,
agitator: [cell, effectivePortIndex]];
}
ELSE SIGNAL Warning["Inconsistency"];
};
};
IF newStrength < node.currentStrength
THEN {
Copy[from: node.valPtr, to: newPtr, bitCount: node.bitCount, bbTable: bbTable];
};
};
blindly ← blindly;
ENDLOOP;
blindly ← blindly;
END;
ReStrengthLink:
PROC [node: Node, slot: Slot, newStrength: Strength] = {
t: Slot;
eps: EffectivePorts ← slot.cell.realCellStuff.effectivePorts;
IF eps[slot.effectivePortIndex].curStrength
IN Strength
THEN {
oldStrength: Strength ← eps[slot.effectivePortIndex].curStrength;
IF (t ← eps[slot.effectivePortIndex].strengthNext) # head
THEN {
IF t = slot THEN ERROR;
t.cell.realCellStuff.effectivePorts[t.effectivePortIndex].strengthPrev ← eps[slot.effectivePortIndex].strengthPrev
}
ELSE node.byStrength[oldStrength].last ← eps[slot.effectivePortIndex].strengthPrev;
IF (t ← eps[slot.effectivePortIndex].strengthPrev) # head
THEN {
IF t = slot THEN ERROR;
t.cell.realCellStuff.effectivePorts[t.effectivePortIndex].strengthNext ← eps[slot.effectivePortIndex].strengthNext
}
ELSE node.byStrength[oldStrength].first ← eps[slot.effectivePortIndex].strengthNext;
};
eps[slot.effectivePortIndex].strengthNext ← node.byStrength[newStrength].first;
eps[slot.effectivePortIndex].strengthPrev ← head;
IF (t ← node.byStrength[newStrength].first) # head
THEN t.cell.realCellStuff.effectivePorts[t.effectivePortIndex].strengthPrev ← slot
ELSE node.byStrength[newStrength].last ← slot;
node.byStrength[newStrength].first ← slot;
eps[slot.effectivePortIndex].curStrength ← newStrength;
};
EmptyStrengthSet:
PROC [node: Node, strength: Strength]
RETURNS [empty:
BOOL] =
{empty ← node.byStrength[strength] = emptyHead};
UpdateCurrent:
PUBLIC
PROC [node: Node, bbTable: PrincOps.BitBltTablePtr, agitator: Slot] = {
aPtr: Ptr ← nilPtr;
IF NOT node.significances[inImpl] THEN ERROR;
IF NOT node.type.simple THEN ERROR;
FOR s: Strength
DECREASING
IN Strength
DO
IF (NOT EmptyStrengthSet[node, s]) OR (s = node.strength) THEN {node.currentStrength ← s; EXIT};
ENDLOOP;
IF node.currentStrength = node.strength THEN RETURN;
IF node.currentStrength < node.strength THEN ERROR;
FOR s: Slot ← node.byStrength[node.currentStrength].first, s.cell.realCellStuff.effectivePorts[s.effectivePortIndex].strengthNext
WHILE s # nilSlot
DO
SELECT aPtr
FROM
=nilPtr => aPtr ← SlotToPtr[s, FALSE];
#nilPtr => {
IF NOT Equal[aPtr, SlotToPtr[s, FALSE], node.bitCount] THEN SIGNAL Warning["Inconsistency"];
};
ENDCASE => ERROR;
ENDLOOP;
IF aPtr = nilPtr THEN ERROR;
Distribute[
base: aPtr,
fromNode: node,
avoidStrength: node.currentStrength,
str: node.strIn,
bitCount: node.bitCount,
bbTable: bbTable,
agitator: agitator
];
};
Distribute:
PROC
[
base: Ptr,
fromNode: Node,
avoidCell: Cell ← NIL,
avoidStrength: DriveLevel ← ignore,
str: Structure,
bitCount: NAT,
bbTable: PrincOps.BitBltTablePtr,
agitator: Slot] =
BEGIN
IF NOT fromNode.type.simple THEN ERROR;
IF base # fromNode.valPtr THEN Copy[from: base, to: fromNode.valPtr, bitCount: bitCount, bbTable: bbTable];
IF fromNode.type.procs.SetNode # NIL THEN fromNode.type.procs.SetNode[fromNode, base];
FOR s: Strength
IN Strength
DO
FOR dest: Slot ← fromNode.byStrength[s].first, dest.cell.realCellStuff.effectivePorts[dest.effectivePortIndex].strengthNext
WHILE dest # head
DO
Copy[from: base, to: SlotToPtr[dest, FALSE], bitCount: bitCount, bbTable: bbTable];
IF dest.cell # avoidCell THEN Schedule[dest.cell, str];
ENDLOOP;
ENDLOOP;
reportSlot^ ← agitator;
RoseEvents.Notify[event: $ChangeEarly, watched: fromNode, handleAborted: TRUE, arg: reportSlot];
FOR pl: PieceList ← fromNode.parentPieces, pl.rest
WHILE pl #
NIL
DO
parent: Node ← pl.first.twardDesign;
IF NOT parent.significances[fromDesign] THEN ERROR;
IF NOT parent.type.simple THEN ERROR;
Copy[from: base, to: SubPtr[parent.type, parent.valPtr, pl.first.reln], bitCount: bitCount, bbTable: bbTable];
RoseEvents.Notify[event: $ChangeEarly, watched: parent, handleAborted: TRUE, arg: reportSlot];
RoseEvents.Notify[event: $ChangeLate, watched: parent, handleAborted: TRUE, arg: reportSlot];
ENDLOOP;
RoseEvents.Notify[event: $ChangeLate, watched: fromNode, handleAborted: TRUE, arg: reportSlot];
END;
SubPtr:
PROC [parent: NodeType, p: Ptr, s: Selector]
RETURNS [sp: Ptr] = {
sp ← OffsetPtr[p, parent.procs.SelectorOffset[parent, s]];
};
SwitchStepSim:
PROC [sim: Simulation] =
BEGIN
str: Structure ← sim.str;
StrFindVicinity[str, FALSE];
StrInitQ[str];
StrPropQWork[str];
StrInitUD[str];
StrPropUDWork[str];
StrFinalUD[str];
END;
PerturbNode:
PUBLIC
PROC [node: Node, agitator: Slot, evenIfInput:
BOOL ←
FALSE] = {
str: Structure ← node.strIn;
SELECT node.significances[inImpl]
FROM
TRUE => ReallyPerturb[node, str, str.sim, agitator, evenIfInput];
FALSE =>
FOR pl: PieceList ← node.childPieces, pl.rest
WHILE pl #
NIL
DO
PerturbNode[pl.first.twardImpl, agitator, evenIfInput];
ENDLOOP;
ENDCASE => ERROR;
};
ReallyPerturb:
PROC [node: Node, str: Structure, sim: Simulation, agitator: Slot, evenIfInput:
BOOL ←
FALSE] =
BEGIN
IF node.type.simple THEN ERROR;
IF NOT node.significances[inImpl] 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;
reportSlot^ ← agitator;
NoteNews[news: $Perturbed, node: node, arg: reportSlot];
};
END;
ReallyFindVicinity:
PROC [str: Structure, n: Node, evenIfInput:
BOOL, from: Slot] =
BEGIN
IF NOT n.significances[inImpl] THEN ERROR;
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;
reportSlot^ ← from;
NoteNews[$Found, n, reportSlot];
FOR sl: SlotList ← n.switchConnections, sl.rest
WHILE sl #
NIL
DO
s: Slot ← sl.first;
rcs: RealCellStuff ← s.cell.realCellStuff;
RecursivelyFindVicinity:
PROC [portIndex: PortIndex] = {
FOR epi: EffectivePortIndex ← rcs.effectivePorts[portIndex].firstEffectivePortIndex, epi+1
WHILE epi < rcs.effectivePorts.length
AND rcs.effectivePorts[epi].containingPort = portIndex
DO
ReallyFindVicinity[str, rcs.implNodes[epi], evenIfInput, [s.cell, epi]];
ENDLOOP;
};
IF rcs.evals.EnumerateVicinity #
NIL
THEN rcs.evals.EnumerateVicinity[
cell: s.cell,
portIndex: rcs.effectivePorts[s.effectivePortIndex].containingPort,
evenIfInput: evenIfInput,
consume: RecursivelyFindVicinity
];
rcs.affectedFlags[Specialty[s]] ← TRUE;
ENDLOOP;
END;
Specialty:
PROC [st: Slot]
RETURNS [sy: Speciality] = {
ep: EffectivePort ← st.cell.realCellStuff.effectivePorts[st.effectivePortIndex];
IF ep.implType.simple THEN ERROR;
sy ← IF TransduceNeeded[ep.type, ep.implType] THEN transducedToSwitch ELSE modeledAsSwitch;
};
StrFindVicinity:
PROC [str: Structure, evenIfInput:
BOOL] =
BEGIN
this: Node;
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, nilSlot];
ENDLOOP;
END;
Need1:
PROC [str: Structure, n: Node, also: CellProc] =
BEGIN
FOR sl: SlotList ← n.switchConnections, 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: SlotList ← n.switchConnections, 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:
PROC [str: Structure] =
BEGIN
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];
NoteNews[news: $NewNodeQ, node: n, arg: NIL];
Need1[str, n, InitQ];
ENDLOOP;
END;
StrPropQWork:
PROC [str: Structure] =
BEGIN
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.realCellStuff.hasTransducedPort) THEN LOOP;
IF needed.realCellStuff.evals.PropQ #
NIL
THEN {
FOR epi: EffectivePortIndex
IN [0 .. needed.realCellStuff.effectivePorts.length)
DO
ep: EffectivePort ← needed.realCellStuff.effectivePorts[epi];
IF (NOT ep.implType.simple) AND (NOT TransduceNeeded[ep.type, ep.implType]) THEN ep.implType.procs.QFromNode[ needed.realCellStuff.implNodes[epi], SlotToPtr[[needed, epi], TRUE]];
ENDLOOP;
needed.realCellStuff.evals.PropQ[needed];
};
FOR epi: EffectivePortIndex
IN [0 .. needed.realCellStuff.effectivePorts.length)
DO
n: Node ← needed.realCellStuff.implNodes[epi];
IF n.type.simple THEN LOOP;
IF n.type.procs.NewQ = NIL THEN ERROR;
IF n.nextAffected = notInNodeList THEN ERROR;
IF n.type.procs.NewQ[n, SlotToPtr[[needed, epi],
TRUE]]
THEN {
reportSlot^ ← [needed, epi];
NoteNews[news: $NewNodeQ, node: n, arg: reportSlot];
Need2[str, n, needed];
};
ENDLOOP;
ENDLOOP;
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:
PROC [str: Structure] =
BEGIN
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];
NoteNews[news: $NewNodeUD, node: n, arg: NIL];
Need1[str, n, InitUD];
ENDLOOP;
END;
StrPropUDWork:
PROC [str: Structure] =
BEGIN
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.realCellStuff.hasTransducedPort) THEN LOOP;
IF needed.realCellStuff.evals.PropUD #
NIL
THEN {
FOR epi: EffectivePortIndex
IN [0 .. needed.realCellStuff.effectivePorts.length)
DO
ep: EffectivePort ← needed.realCellStuff.effectivePorts[epi];
IF (NOT ep.implType.simple) AND (NOT TransduceNeeded[ep.type, ep.implType]) THEN ep.implType.procs.UDFromNode[ needed.realCellStuff.implNodes[epi], SlotToPtr[[needed, epi], TRUE]];
ENDLOOP;
needed.realCellStuff.evals.PropUD[needed];
};
FOR epi: EffectivePortIndex
IN [0 .. needed.realCellStuff.effectivePorts.length)
DO
n: Node ← needed.realCellStuff.implNodes[epi];
IF n.type.simple THEN LOOP;
IF n.type.procs.NewUD = NIL THEN ERROR;
IF n.nextAffected = notInNodeList THEN ERROR;
IF n.type.procs.NewUD[n, SlotToPtr[[needed, epi],
TRUE]]
THEN {
reportSlot^ ← [needed, epi];
NoteNews[news: $NewNodeUD, node: n, arg: reportSlot];
Need2[str, n, needed];
};
ENDLOOP;
ENDLOOP;
END;
NoteNews:
PROC [news:
ATOM, node: Node, arg:
REF
ANY] = {
RoseEvents.Notify[event: news, watched: node, handleAborted: TRUE, arg: arg];
FOR pl: PieceList ← node.parentPieces, pl.rest
WHILE pl #
NIL
DO
NoteNews[news, pl.first.twardDesign, arg];
ENDLOOP;
};
StrFinalUD:
PROC [str: Structure] =
BEGIN
firstNoted, next: Cell ← NIL;
bbTableSpace: PrincOps.BBTableSpace;
bbTable: PrincOps.BitBltTablePtr;
TRUSTED {bbTable ← PrincOpsUtils.AlignedBBTable[@bbTableSpace]};
FOR n: Node ← str.firstAffected, n.nextAffected
WHILE n #
NIL
DO
delay: BOOL ← FALSE;
IF n = notInNodeList THEN ERROR;
n.found ← FALSE;
IF n.type.procs.NewVal # NIL THEN delay ← n.type.procs.NewVal[n];
SetDelayedness[n, delay];
IF NOT delay THEN DistributeSwitch[n, bbTable, FALSE];
FOR sl: SlotList ← n.switchConnections, 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;
IF firstNoted.realCellStuff.evals.FinalUD # NIL THEN firstNoted.realCellStuff.evals.FinalUD[firstNoted];
IF firstNoted.realCellStuff.affectedFlags[transducedToSwitch] THEN ScheduleCell[firstNoted];
ValsChanged[firstNoted, str];
firstNoted.realCellStuff.affectedFlags ← ALL[FALSE];
ENDLOOP;
END;
Delayed:
PUBLIC
PROC [n: Node]
RETURNS [delayed:
BOOL] =
{delayed ← n.nextDelayed # notInNodeList};
SetDelayedness:
PROC [n: Node, delay:
BOOL] = {
str: Structure;
IF delay = (n.nextDelayed # notInNodeList) THEN RETURN;
str ← n.strIn;
IF delay
THEN {
IF str.firstDelayed = notInNodeList THEN ERROR;
n.nextDelayed ← str.firstDelayed;
n.prevDelayed ← NIL;
IF n.nextDelayed = NIL THEN str.lastDelayed ← n ELSE n.nextDelayed.prevDelayed ← n;
str.firstDelayed ← n;
}
ELSE {
IF n.nextDelayed = NIL THEN str.lastDelayed ← n.prevDelayed ELSE n.nextDelayed.prevDelayed ← n.prevDelayed;
IF n.prevDelayed = NIL THEN str.firstDelayed ← n.nextDelayed ELSE n.prevDelayed.nextDelayed ← n.nextDelayed;
n.nextDelayed ← n.prevDelayed ← notInNodeList;
};
};
CheckDelays:
PROC [sim: Simulation] = {
str: Structure ← sim.str;
names: RopeList ← NIL;
FOR n: Node ← str.firstDelayed, n.nextDelayed
WHILE n #
NIL
DO
IF n = notInNodeList THEN ERROR;
names ← CONS[RoseCreate.LongNodeName[n, sim.root], names];
PerturbNode[n, nilSlot];
ENDLOOP;
IF names # NIL THEN SIGNAL Warning["Nodes want Xes", names];
};
DistributeSwitch:
PROC [node: Node, bbTable: PrincOps.BitBltTablePtr, perturb:
BOOL] = {
IF node.type.simple OR NOT node.significances[inImpl] THEN ERROR;
IF perturb THEN PerturbNode[node, nilSlot, TRUE];
FOR sl: SlotList ← node.switchConnections, sl.rest
WHILE sl #
NIL
DO
cell: Cell ← sl.first.cell;
epi: EffectivePortIndex ← sl.first.effectivePortIndex;
ep: EffectivePort ← cell.realCellStuff.effectivePorts[epi];
implPtr: Ptr ← SlotToPtr[[cell, epi], TRUE];
IF NOT ep.implType.simple THEN ep.implType.procs.ValFromNode[cell.realCellStuff.implNodes[epi], implPtr];
IF TransduceNeeded[ep.type, ep.implType]
THEN {
modelPtr: Ptr ← SlotToPtr[[cell, epi], FALSE];
ep.type.procs.Transduce[fromS: FIRST[Strength], fromT: ep.implType, toT: ep.type, fromP: implPtr, toP: modelPtr];
};
ENDLOOP;
RoseEvents.Notify[event: $ChangeEarly, watched: node, handleAborted: TRUE];
FOR pl: PieceList ← node.parentPieces, pl.rest
WHILE pl #
NIL
DO
pn: Node ← pl.first.twardDesign;
Copy[node.valPtr, SubPtr[pn.type, pn.valPtr, pl.first.reln], node.bitCount, bbTable];
IF perturb THEN PerturbNode[pn, nilSlot, TRUE];
RoseEvents.Notify[event: $ChangeEarly, watched: pn, handleAborted: TRUE];
RoseEvents.Notify[event: $ChangeLate, watched: pn, handleAborted: TRUE];
ENDLOOP;
RoseEvents.Notify[event: $ChangeLate, watched: node, handleAborted: TRUE];
};
ValsChanged:
PROC [cell: Cell, str: Structure] =
BEGIN
IF cell.realCellStuff.evals.ValsChanged #
NIL
THEN {
PerturbPort:
PROC [portIndex: PortIndex] = {
FOR epi: EffectivePortIndex ← cell.realCellStuff.effectivePorts[portIndex].firstEffectivePortIndex, epi+1
WHILE epi < cell.realCellStuff.effectivePorts.length
AND cell.realCellStuff.effectivePorts[epi].containingPort = portIndex
DO
ReallyPerturb[cell.realCellStuff.implNodes[epi], str, cell.sim, [cell, epi], FALSE];
ENDLOOP;
};
PreSimple[cell];
cell.realCellStuff.evals.ValsChanged[
cell: cell,
perturb: PerturbPort
!UNWIND => ReallyCleanUpAfterModify[cell: cell, str: str, outputsOnly: TRUE, blindly: FALSE, mayRescheduleSelf: TRUE]];
ReallyCleanUpAfterModify[cell: cell, str: str, outputsOnly: TRUE, blindly: FALSE, mayRescheduleSelf: TRUE];
};
END;
ValueChanged:
PUBLIC
PROC [node: Node] =
BEGIN
bbTableSpace: PrincOps.BBTableSpace;
bbTable: PrincOps.BitBltTablePtr;
TRUSTED {bbTable ← PrincOpsUtils.AlignedBBTable[@bbTableSpace]};
SELECT node.significances[inImpl]
FROM
TRUE =>
SELECT node.type.simple
FROM
FALSE => {
DistributeSwitch[node, bbTable, TRUE];
};
TRUE => {
Distribute[
base: node.valPtr,
fromNode: node,
str: node.strIn,
bitCount: node.bitCount,
bbTable: bbTable,
agitator: nilSlot];
};
ENDCASE => ERROR;
FALSE => {
FOR pl: PieceList ← node.childPieces, pl.rest
WHILE pl #
NIL
DO
cn: Node ← pl.first.twardImpl;
IF cn.type.simple # node.type.simple THEN ERROR;
Copy[SubPtr[node.type, node.valPtr, pl.first.reln], cn.valPtr, cn.bitCount, bbTable];
ValueChanged[cn];
ENDLOOP;
};
ENDCASE => ERROR;
END;
AllowToModify:
PUBLIC
PROC [cell: Cell, modifier: CellProc, blindly, mayRescheduleSelf:
BOOLEAN ←
FALSE] =
BEGIN
str: Structure ← ContainingStr[cell];
PreSimple[cell, NOT blindly];
modifier[cell !
UNWIND =>
BEGIN
ReallyCleanUpAfterModify[cell, str, FALSE, blindly, mayRescheduleSelf];
END];
ReallyCleanUpAfterModify[cell, str, FALSE, blindly, mayRescheduleSelf];
END;
Start:
PROC = {
notInCellList.name ← "notInCellList";
notInNodeList.name ← "notInNodeList";
};
Start[];
END.