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 = 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]]]; 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. 2RoseRunImpl.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 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. IF outputsOnly AND NOT ep.output THEN LOOP; Κ˜Jšœ™J™:J™4J™6Icode˜KšΟk œœi˜‹K˜šΠbx œœœ˜Kšœœ2˜JKšœ˜—head™Kšœz™zK™m—™K™ŽK™EK™^—K˜K˜Kšœœ˜#K˜Kšœœœœ˜K˜Kšœœ œ˜4Kšœœœ ˜+Kšœœœ ˜+K˜Kšœ œœ˜"K˜šΟnœœœ˜$Kš˜šœ˜Kšœœœ!˜4Kšœ˜—Kšœ˜—K˜šŸœœœœ˜JKš˜Kšœ˜Kšœœœœ ˜3Kšœœœœ˜9K˜Kšœ˜—K˜šŸœœœœ˜MKš˜šœ˜ Kšœ œ˜K˜!Kšœ ˜ Kšœœ˜—šœœœ˜2Kšœ@œ˜FK˜K˜—Kšœ˜—K˜šŸ œœ˜)Kšœ˜š œ œœœœ˜2Kšœœœœ˜-Kšœ ˜ Kšœ œœ˜-Kšœœœ!˜4Kšœ˜šœ'œ˜1Kš˜šŸ œœ˜,šœgœ0œC˜ηKšœMœ˜TKšœ˜—Kšœ˜—K˜šœ$˜$Kšœ ˜ K˜šœœ˜ Kšœ$œœœ˜8Kšœ˜Kšœ˜—Kšœ˜—Kšœ$œœœ˜8Kšœ>œ˜DKšœ˜—Kšœ˜—Kšœœ˜K˜—K˜šŸœœœ˜>Kš˜K˜Kšœ3œœœ˜RK˜-KšœBœ˜HKšœœœœ˜$KšœLœ˜RKšœ˜—K˜šŸ œœœ˜(Kšœ&˜&—K˜šŸœœ˜-Kš˜Kšœ.œœ˜˜>Kšœ.œ$œ:˜”K˜—Kšœ$œœ˜1šœ$œ˜,šœ œ˜Kšœœœœ˜`šœœΟcœ˜$˜ Kšœ ˜ Kšœ˜Kš œ œœœœœ˜7Kšœ ˜ Kšœ˜Kšœ˜Kšœ&˜&—K˜—Kšœœ˜%K˜—K˜—šœ$œ˜,KšœO˜OK˜—K˜—Kšœ˜Kšœ˜—Kšœ˜Kšœ˜—K˜•StartOfExpansion[]šŸœœ4˜HK˜Kšœ=˜=šœ*œ œ˜>KšœA˜Ašœ8œ˜@Kšœ œœ˜Kšœr˜rKšœ˜—KšœO˜Sšœ8œ˜@Kšœ œœ˜Kšœr˜rKšœ˜—KšœP˜TK˜—KšœO˜OKšœ1˜1šœ0˜2KšœN˜RKšœ*˜.—Kšœ*˜*Kšœ7˜7K˜—K˜šŸœœ"œ œ˜OK˜0—K˜šŸ œœœC˜]K˜Kšœœœœ˜-Kšœœœœ˜#šœ  œœ ˜)Kš œœœœœ˜`Kšœ˜—Kšœ&œœ˜4Kšœ&œœ˜3šœœ ˜–šœ˜Kšœœ˜&˜ Kš œœœœœ˜\K˜—Kšœœ˜—Kšœ˜—Kšœœœ˜šœ ˜ K˜ K˜Kšœ$˜$K˜K˜K˜K˜K˜—K˜—K˜šŸ œ˜šœ˜Kšœ ˜ Kšœ˜Kšœœ˜Kšœ#˜#Kšœ˜Kšœ œ˜Kšœ!˜!Kšœ˜—Kš˜Kšœœœœ˜'KšœœM˜kKšœœœ-˜Všœ œ ˜šœyœ ˜Kšœ%œ)˜SKšœœ˜7Kšœ˜—Kšœ˜—K˜KšœIœ˜`šœ0œœ˜DK˜$Kšœœ"œœ˜3Kšœœœœ˜%Kšœn˜nKšœGœ˜^KšœFœ˜]Kšœ˜—KšœHœ˜_Kšœ˜—K˜šŸœœ)œ˜JKšœ:˜:K˜—K˜šŸ œœ˜'Kš˜K˜Kšœœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—K˜š Ÿ œœœ+œœ˜TKšœ˜šœ˜&Kšœ=˜Aš œœ+œœ˜HKšœ7˜7Kšœ˜—Kšœœ˜—Kšœ˜—K˜šŸ œœLœœ˜nKš˜Kšœœœ˜Kšœœœœ˜-Kš œœœ œœ˜0šœ$œ˜,Kšœ$œœ˜1Kšœ(˜(Kšœ˜Kšœ˜Kšœ8˜8K˜—Kšœ˜—K˜šŸœœ(œ˜SKš˜Kšœœœœ˜*Kšœ œœ˜Kš œ œœ œœ˜-Kšœ œ˜Kšœ#œœ˜0K˜#K˜K˜Kšœ ˜ šœ-œœ˜AK˜Kšœ*˜*šŸœœ˜8šœXœ!œ4˜ΊKšœH˜HKšœ˜—K˜—šœœœ˜FKšœ ˜ KšœC˜CKšœ˜K˜ Kšœ˜—Kšœ"œ˜'Kšœ˜—Kšœ˜—K˜šŸ œœ œ˜7KšœP˜PKšœœœ˜!Kšœœ'œœ˜[Kšœ˜—K˜šŸœœœ˜;Kš˜K˜ šœœ˜!Kšœ$œœ˜1Kšœ˜Kšœ(˜(Kšœ#˜#Kšœ5˜5Kšœ˜—Kšœ˜—K˜šŸœœ,˜7Kš˜šœ-œœ˜Ašœ8˜>Kš˜Kšœ!œœ˜.Kšœ9˜9K˜ Kšœœœ˜'Kšœ˜—Kšœ˜—Kšœ˜—K˜šŸœœ*˜5Kš˜šœ-œœ˜Ašœ8œ˜YKš˜Kšœ!œœ˜.Kšœ9˜9K˜ Kšœ˜—Kšœ˜—Kšœ˜—K˜šŸœ  œ˜(šœœœ˜(Kšœœ˜"Kšœ"œœ(˜T——K˜šŸœœ˜!Kš˜šœ-œœ˜@Kšœœœ˜ Kšœœœ˜7Kšœ(œ˜-Kšœ˜Kšœ˜—Kšœ˜—K˜šŸ œœ˜%Kš˜šœœ˜K˜Kšœœœ˜%Kšœ2˜2Kšœ0˜0Kšœœ˜%Kš œ%œœœ)œœ˜gšœ$œœ˜0šœœ3˜SKšœ=˜=Kš œœœœ(œ\œ˜³Kšœ˜—Kšœ)˜)K˜—šœœ3˜SKšœ.˜.Kšœœœ˜Kšœœœœ˜&Kšœ œœ˜-šœ/œœ˜>Kšœ˜Kšœ4˜4Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—K˜šŸœ  œ˜)šœœœ˜)Kšœœ˜#Kšœ#œœ)˜V——K˜šŸ œœ˜"Kš˜šœ-œœ˜@Kšœœœ˜ Kšœœœ˜9Kšœ)œ˜.Kšœ˜Kšœ˜—Kšœ˜—K˜šŸ œœ˜&Kš˜šœœ˜K˜Kšœœœ˜%Kšœ2˜2Kšœ0˜0Kšœ œ˜&Kš œ&œœœ)œœ˜hšœ%œœ˜1šœœ3˜SKšœ=˜=Kš œœœœ(œ]œ˜΄Kšœ˜—K˜*K˜—šœœ3˜SKšœ.˜.Kšœœœ˜Kšœœœœ˜'Kšœ œœ˜-šœ0œœ˜?Kšœ˜Kšœ5˜5Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜—Kšœ˜—K˜š Ÿœœœœœ˜9Kšœ=œ ˜Mšœ,œœ˜@Kšœ*˜*Kšœ˜—K˜—K˜šŸ œœ˜#Kš˜Kšœœ˜Kšœ$˜$Kšœ!˜!Kšœ9˜@šœ-œœ˜@Kšœœœ˜Kšœœœ˜ Kšœ œ˜Kšœœœ ˜AK˜Kšœœœœ˜6šœ-œœ˜Ašœ7˜=K˜Q—Kšœ˜—Kšœ˜—Kšœœ˜šœœœ˜;Kšœœœ˜)K˜*Kšœ3˜3Kšœ*œœ4˜hKšœ<œ˜\Kšœ˜Kšœ)œœ˜4Kšœ˜—Kšœ˜—K˜š Ÿœœœ œ œ˜8Kšœ*˜*—K˜šŸœœœ˜/K˜Kšœ)œœ˜7K˜šœœ˜Kšœ"œœ˜/K˜!Kšœœ˜Kšœœœœ˜SKšœ˜K˜—šœ˜Kšœœœ!œ+˜kKšœœœ"œ+˜lK˜.K˜—K˜—K˜šŸ œœ˜'K˜Kšœœ˜šœ+œœ˜>Kšœœœ˜ Kšœœ.˜:Kšœ˜Kšœ˜—Kšœ œœœ"˜œœ˜jKš˜K˜%Kšœœ ˜šœœ˜Kš˜Kšœ$œ˜GKšœ˜—Kšœ$œ˜GKšœ˜—K˜šŸœœ˜K˜%K˜%K˜—K˜K˜K˜Kšœ˜—…—[Ζy