<> <> <> <> 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.connections, 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[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.connections, 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.connections, 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 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: 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 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.connections, 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[special] THEN ScheduleCell[firstNoted]; ValsChanged[firstNoted, str]; firstNoted.realCellStuff.affectedFlags _ ALL[FALSE]; ENDLOOP; END; ValsChanged: PROC [cell: Cell, str: Structure] = BEGIN FOR portIndex: NAT IN [0 .. cell.type.ports.length) DO port: Port _ cell.type.ports[portIndex]; IF NOT port.type.simple THEN port.type.procs.ValFromNode[ cell.interfaceNodes[portIndex], SocketToWP[[cell, portIndex], TRUE]]; ENDLOOP; IF cell.realCellStuff.evals.ValsChanged # NIL THEN { PreSimple[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.connections, 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; <> <> <> <> <> <<(o+i)^ _ (n+i)^;>> <> <> PreSimple: PUBLIC PROC [cell: Cell, reallyCopy: BOOL _ TRUE] = TRUSTED BEGIN IF reallyCopy THEN { 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 { newWP: WordPtr _ SocketToWP[[cell, portIndex], FALSE]; port.type.procs.ClearUD[nt: port.type, at: newWP]; port.type.procs.ValFromNode[cell.interfaceNodes[portIndex], newWP]; }; 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 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 port.special AND (NOT port.type.simple) AND NotAgg[cell] THEN port.type.procs.ComputeQ[node, newWP]; IF blindly THEN diff _ TRUE ELSE BEGIN IF port.special AND (NOT port.type.simple) AND NotAgg[cell] THEN { diff _ port.type.procs.CompareUD[nt: port.type, wp1: newWP, wp2: oldWP]; } ELSE 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 PreSimple[cell, NOT blindly]; 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; notInCellList.name _ "notInCellList"; notInNodeList.name _ "notInNodeList"; END.