DIRECTORY Basics, Convert, FS, IO, List, OrderedSymbolTableRef, Rope, RoseCreate, RoseEvents, RoseRun, RoseTypes; RoseCreateImpl: CEDAR PROGRAM IMPORTS Convert, FS, IO, List, OSTR: OrderedSymbolTableRef, Rope, RoseCreate, RoseEvents, RoseRun, RoseTypes EXPORTS RoseCreate, RoseTypes = BEGIN OPEN RoseCreate, RoseTypes; LORA: TYPE = LIST OF REF ANY; cellTypes: SymbolTable _ OSTR.CreateTable[CompareCellTypes]; roots: PUBLIC SymbolTable _ OSTR.CreateTable[CompareComponents]; bogosityKey: ATOM = $bogosityKey; simERClass: ERClass _ NEW [ERClassRep _ [ CellInstance: CellInstance, NodeInstance: NodeInstance, SplitJoin: SplitJoin, ChangeReps: ChangeReps]]; CompareCellTypes: -- --OSTR.CompareProc = BEGIN ToKey: SAFE PROC [ref: REF ANY] RETURNS [ROPE] = {RETURN [WITH ref SELECT FROM r: ROPE => r, ct: CellType => ct.name, ENDCASE => ERROR]}; RETURN [ToKey[r1].Compare[ToKey[r2]]]; END; CompareComponents: PUBLIC PROC [r1, r2: REF ANY] RETURNS [Basics.Comparison] --OSTR.CompareProc-- = BEGIN ToKey: SAFE PROC [ref: REF ANY] RETURNS [ROPE] = {RETURN [WITH ref SELECT FROM r: ROPE => r, c: Cell => c.name, ENDCASE => ERROR]}; RETURN [ToKey[r1].Compare[ToKey[r2]]]; END; CompareNodes: PUBLIC PROC [r1, r2: REF ANY] RETURNS [Basics.Comparison] --OSTR.CompareProc-- = BEGIN k1, k2: ROPE; WITH r1 SELECT FROM r: ROPE => k1 _ r; n: Node => k1 _ n.name; ENDCASE => ERROR; k2 _ WITH r2 SELECT FROM r: ROPE => r, n: Node => n.name, ENDCASE => ERROR; RETURN [k1.Compare[k2]]; END; RegisterCellType: PUBLIC PROC [name: ROPE, expandProc: ExpandProc _ NIL, ioCreator: IOCreator _ NIL, initializer: Initializer _ NIL, evals: EvalProcs, blackBox, stateToo: CellTestProc _ NIL, ports: Ports, drivePrototype: REF ANY _ NIL, typeData: REF ANY _ NIL] RETURNS [type: CellType] = BEGIN type _ NARROW[cellTypes.Lookup[name]]; IF type = NIL THEN { type _ NEW [CellTypeRep _ [name: name, ioWordCount: 0, firstInstance: NIL]]; cellTypes.Insert[type]; FOR portIndex: CARDINAL IN [0 .. ports.length) DO port: Port _ ports[portIndex]; type.ioWordCount _ MAX[type.ioWordCount, port.firstWord + port.wordCount]; IF port.type = NIL THEN ERROR Error[IO.PutFR["No NodeType given for Port %g", IO.rope[port.name]]]; IF port.special THEN type.hasASpecialPort _ TRUE; ENDLOOP; } ELSE BEGIN IF type.firstInstance # NIL THEN BEGIN ok: BOOLEAN _ TRUE; IF ports.length # type.ports.length THEN ok _ FALSE ELSE BEGIN FOR portIndex: CARDINAL IN [0 .. type.ports.length) DO IF ( ports[portIndex].firstWord # type.ports[portIndex].firstWord OR ports[portIndex].wordCount # type.ports[portIndex].wordCount OR ports[portIndex].type # type.ports[portIndex].type OR ports[portIndex].input # type.ports[portIndex].input OR ports[portIndex].output # type.ports[portIndex].output OR NOT ports[portIndex].name.Equal[type.ports[portIndex].name]) THEN {ok _ FALSE; EXIT}; ENDLOOP; END; IF NOT ok THEN ERROR Error[IO.PutFR["Redefinition of Type %g not allowed because of different interface", IO.rope[name]]]; END; FOR instance: Cell _ type.firstInstance, instance.nextInstance WHILE instance # NIL DO IF instance.type # type THEN ERROR; IF instance.expansion = Leaf THEN BEGIN IF instance.realCellStuff.evals # type.evals THEN ERROR; instance.realCellStuff.evals _ evals; END; ENDLOOP; END; type.expand _ expandProc; type.ioCreator _ ioCreator; type.initializer _ initializer; type.evals _ evals; type.blackBox _ blackBox; type.stateToo _ stateToo; type.ports _ ports; type.drivePrototype _ drivePrototype; type.typeData _ typeData; END; GetCellType: PUBLIC PROC [name: ROPE] RETURNS [type: CellType] = {type _ NARROW[cellTypes.Lookup[name]]}; CreateSim: PUBLIC PROC [steady: BOOL, captureDirectory, captureRoot: ROPE _ NIL, quick: BOOL _ TRUE] RETURNS [sim: Simulation] = { sc: SimCapture _ NIL; IF captureRoot # NIL THEN { dfName: ROPE _ captureRoot.Cat[".DF"]; sc _ NEW [SimCaptureRep _ [fileRoot: captureRoot, quick: quick, DFOut: FS.StreamOpen[dfName, create]]]; sc.DFOut.PutF["-- %g written by Rosemary structure capturer at %g\n", IO.rope[dfName], IO.time[]]; sc.DFOut.PutF["\n\nDirectory %g\n %g\n", IO.rope[captureDirectory], IO.rope[dfName]]; }; sim _ NEW [SimulationRep _ [ steady: steady, root: NIL, other: List.PutAssoc[key: capKey, val: sc, aList: NIL]]]; RoseEvents.Notify[event: $NewSim, arg: sim]; }; capKey: REF ANY _ NEW [ROPE _ "Capture Key"]; CreateTopCell: PUBLIC PROC [instanceName, typeName: ROPE, decider: ExpandDeciderClosure, sim: Simulation] RETURNS [cell: Cell] = BEGIN sc: SimCapture _ NARROW[List.Assoc[key: capKey, aList: sim.other]]; type: CellType; type _ NARROW[cellTypes.Lookup[typeName]]; IF type = NIL THEN ERROR Error[IO.PutFR["No such type: %g", IO.rope[typeName]]]; sim.root _ cell _ NEW [CellRep _ [ name: instanceName, type: type, sim: sim, parent: NIL, leftChild: NIL, rightSibling: NIL, firstInternalNode: NIL, internalNodes: OSTR.CreateTable[CompareNodes], components: OSTR.CreateTable[CompareComponents], interfaceNodes: NEW [NodeSR[0]], props: NIL, substantiality: Shadow, expansion: Inline, realCellStuff: NIL]]; cell.props _ List.PutAssoc[$ExpandDeciderClosure, decider, cell.props]; FinishCreatingCell[cell, NIL, TRUE, sc]; IF sc # NIL THEN sc.DFOut.Close[]; END; CellInstance: PROC [erInstance: REF ANY, instanceName, typeName, interfaceNodes: ROPE] RETURNS [cell: Cell] = BEGIN within: Cell _ NARROW[erInstance]; sc: SimCapture _ NARROW[List.Assoc[key: capKey, aList: within.sim.other]]; type: CellType; type _ NARROW[cellTypes.Lookup[typeName]]; IF type = NIL THEN ERROR Error[IO.PutFR["No such type: %g", IO.rope[typeName]]]; cell _ NEW [CellRep _ [ name: instanceName, type: type, sim: within.sim, parent: within, leftChild: NIL, rightSibling: NIL, firstInternalNode: NIL, internalNodes: OSTR.CreateTable[CompareNodes], components: OSTR.CreateTable[CompareComponents], interfaceNodes: NEW [NodeSR[type.ports.length]], props: NIL, substantiality: Shadow, expansion: Inline, realCellStuff: NIL]]; FinishCreatingCell[cell, interfaceNodes, FALSE, sc]; END; OldHat: PROC [ct: CellType, sc: SimCapture] RETURNS [uninteresting: BOOL] = {uninteresting _ sc.quick AND (List.Assoc[key: capKey, aList: ct.props] = sc)}; SimCapture: TYPE = REF SimCaptureRep; SimCaptureRep: TYPE = RECORD [ fileRoot: ROPE, quick: BOOL, DFOut: IO.STREAM, gen: CARDINAL _ 0 ]; FinishCreatingCell: PROC [cell: Cell, interfaceNodes: ROPE, isRoot: BOOL, sc: SimCapture] = BEGIN type: CellType _ cell.type; thisChild, lastChild: Cell; thisNode, lastNode: Node; capturing: BOOL _ sc # NIL; IF (cell.parent = NIL) AND (type.ports.length > 0) THEN ERROR Error["Can't make root with non-empty interface", cell]; IF cell.parent # NIL THEN BEGIN cell.parent.components.Insert[cell !OSTR.DuplicateKey => ERROR Error[IO.PutFR["Duplicated Cell name: %g", IO.rope[cell.name]]]]; cell.rightSibling _ cell.parent.leftChild; --do it in wrong order for now; parent will fix up after done expanding-- cell.parent.leftChild _ cell; END; cell.nextInstance _ type.firstInstance; type.firstInstance _ cell; FillInInterfaceNodes[cell, interfaceNodes]; cell.expansion _ FindAndUseExpandDecider[cell]; SELECT cell.expansion FROM Inline => BEGIN cell.substantiality _ Shadow; cell.realCellStuff _ NIL; FOR index: CARDINAL IN [0 .. type.ports.length) DO interfaceNode: Node _ cell.interfaceNodes[index]; IF NOT type.ports[index].output THEN interfaceNode.unwriteability _ interfaceNode.unwriteability + 1; ENDLOOP; type.expand[thisCell: cell, to: [cell, simERClass]]; FOR index: CARDINAL IN [0 .. type.ports.length) DO interfaceNode: Node _ cell.interfaceNodes[index]; IF NOT type.ports[index].output THEN interfaceNode.unwriteability _ interfaceNode.unwriteability - 1; ENDLOOP; END; Leaf, Nested => BEGIN oldHat: BOOL _ capturing AND OldHat[type, sc]; cell.substantiality _ Real; cell.realCellStuff _ NEW [RealCellStuffRep _ [schedNext: notInCellList, nextNeeded: notInCellList, nextNoted: notInCellList, newIO: NIL, oldIO: NIL, switchIO: NIL, newIOAsWP: NIL, oldIOAsWP: NIL, switchIOAsWP: NIL, state: NIL, evals: type.evals]]; FOR portIndex: CARDINAL IN [0..type.ports.length) DO node: Node _ cell.interfaceNodes[portIndex]; targType: NodeType _ cell.type.ports[portIndex].type; IF node.type = NIL THEN ERROR--node.type _ targType--; IF targType # node.type THEN ERROR InterfaceMismatch[cell: cell, index: portIndex, expected: targType, got: node.type]; IF cell.type.ports[portIndex].XPhobic THEN node.XPhobic _ TRUE; NoteConnection[node, [cell, portIndex], cell.type.ports[portIndex].input, cell.type.ports[portIndex].output]; NoteMaybeVisible[node, [cell, portIndex]]; ENDLOOP; IF type.ioCreator # NIL THEN type.ioCreator[cell: cell] ELSE IF type.ioWordCount > 0 THEN ERROR Error[IO.PutFR["No IOCreator for type %g", IO.rope[type.name]]]; cell.realCellStuff.newIOAsWP _ LOOPHOLE[cell.realCellStuff.newIO]; cell.realCellStuff.oldIOAsWP _ LOOPHOLE[cell.realCellStuff.oldIO]; cell.realCellStuff.switchIOAsWP _ LOOPHOLE[cell.realCellStuff.switchIO]; FOR portIndex: CARDINAL IN [0 .. type.ports.length) DO targType: NodeType _ cell.type.ports[portIndex].type; node: Node _ cell.interfaceNodes[portIndex]; IF targType.procs.InitPort # NIL THEN targType.procs.InitPort[ node, SocketToWP[[cell, portIndex]]]; IF node.initialValue # NIL AND node.type.simple THEN Initialize[node, SocketToWP[[cell, portIndex]]]; ENDLOOP; IF type.initializer # NIL THEN type.initializer[cell: cell, leafily: cell.expansion = Leaf]; IF cell.expansion = Nested THEN BEGIN insides: Structure; cell.realCellStuff.evals _ RoseRun.StrEvals; cell.realCellStuff.state _ insides _ NEW [StructureRep _ [ container: cell, mirror: NIL, schedFirst: NIL, schedLast: NIL, insideNodes: NEW [NodeSR[type.ports.length]], nextPerturbed: notInStrList, nextWasPerturbed: notInStrList ]]; IF cell.parent # NIL THEN insides.mirror _ NEW [CellRep _ [ name: cell.name.Cat["-mirror"], type: GetMirrorType[cell.type], sim: cell.sim, parent: cell, leftChild: NIL, rightSibling: NIL, firstInternalNode: NIL, internalNodes: NIL, components: NIL, interfaceNodes: insides.insideNodes, props: NIL, substantiality: Real, expansion: Leaf, realCellStuff: NEW [RealCellStuffRep _ [ schedNext: notInCellList, nextNeeded: notInCellList, nextNoted: notInCellList, newIO: cell.realCellStuff.newIO, oldIO: cell.realCellStuff.oldIO, switchIO: cell.realCellStuff.switchIO, newIOAsWP: cell.realCellStuff.newIOAsWP, oldIOAsWP: cell.realCellStuff.oldIOAsWP, switchIOAsWP: cell.realCellStuff.switchIOAsWP, state: ContainingStr[cell], evals: RoseRun.StrMirrorEvals]]]]; IF NOT oldHat THEN FOR index: CARDINAL IN [0 .. type.ports.length) DO outsideNode: Node _ cell.interfaceNodes[index]; insideNode: Node _ NodeInstance[erInstance: cell, name: type.ports[index].name, type: outsideNode.type, initialValue: outsideNode.initialValue]; insides.insideNodes[index] _ insideNode; IF cell.parent # NIL THEN { NoteMaybeVisible[insideNode, [insides.mirror, index]]; NoteConnection[insideNode, [insides.mirror, index], cell.type.ports[index].output, cell.type.ports[index].input]; }; IF NOT type.ports[index].output THEN insideNode.unwriteability _ insideNode.unwriteability + 1; ENDLOOP; IF capturing THEN BEGIN IF NOT oldHat THEN { co: IO.STREAM _ StartRecording[sc, cell]; type.expand[thisCell: cell, to: [cell, simERClass]]; StopRecording[sc, cell, co]; }; END ELSE type.expand[thisCell: cell, to: [cell, simERClass]]; END ELSE BEGIN IF capturing THEN BEGIN IF NOT oldHat THEN { co: IO.STREAM _ StartRecording[sc, cell]; WritePorts[sc, type, co]; co.PutRope["(PrivateFollows)\n(InsidesUnspecified)\n"]; co.Close[]; }; END; END; END; ENDCASE => ERROR; lastChild _ NIL; thisChild _ cell.leftChild; WHILE thisChild # NIL DO nextChild: Cell _ thisChild.rightSibling; thisChild.rightSibling _ lastChild; lastChild _ thisChild; thisChild _ nextChild; ENDLOOP; cell.leftChild _ lastChild; lastNode _ NIL; thisNode _ cell.firstInternalNode; WHILE thisNode # NIL DO nextNode: Node _ thisNode.next; thisNode.next _ lastNode; lastNode _ thisNode; thisNode _ nextNode; ENDLOOP; cell.firstInternalNode _ lastNode; IF isRoot THEN roots.Insert[cell !OSTR.DuplicateKey => ERROR Error[IO.PutFR["Duplicated Root name: %g", IO.rope[cell.name]]]] ELSE IF cell.substantiality = Real THEN RoseRun.ScheduleCell[cell]; END; StartRecording: PROC [sc: SimCapture, cell: Cell] RETURNS [cellOut: STREAM] = BEGIN fileName: ROPE _ IO.PutFR["%g-%g.sch", IO.rope[sc.fileRoot], IO.card[sc.gen _ sc.gen + 1]]; cellOut _ FS.StreamOpen[fileName, create]; sc.DFOut.PutF["-- (CellType %g)\n %g\n", IO.refAny[cell.type.name], IO.rope[fileName]]; cellOut.PutF["(CellTypeName %g)\n(CreationTime \"%g\")\n", IO.refAny[cell.type.name], IO.time[]]; cell.type.props _ List.PutAssoc[key: capKey, val: sc, aList: cell.type.props]; END; Best: PROC [ra: REF ANY] RETURNS [w: Wire] = {w _ NARROW[ra]; WHILE w.better # NIL DO w _ w.better ENDLOOP}; StopRecording: PROC [sc: SimCapture, cell: Cell, cellOut: STREAM] = BEGIN WriteNode: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { WriteWires: PROC [type: NodeType, ra: REF ANY] = { WITH type SELECT FROM ant: ArrayNodeType => {list: LORA _ NARROW[ra]; FOR i: INT IN [ant.first .. ant.last] DO WriteWires[ant.element, list.first]; list _ list.rest; ENDLOOP}; ant: AtomNodeType => {w: Wire _ NARROW[ra]; IF w.better = NIL THEN { cellOut.PutF["(N %g)\n", IO.refAny[w.name]]}}; ENDCASE => ERROR}; n: Node _ NARROW[ra]; w: REF ANY _ List.Assoc[key: wireKey, aList: n.props]; stop _ FALSE; WriteWires[n.type, w]; }; DestroyNode: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { n: Node _ NARROW[ra]; stop _ FALSE; IF cell.internalNodes.Delete[n] # n THEN ERROR; n.type _ NIL; n.data _ NIL; n.initialValue _ NIL; n.cellIn _ NIL; n.visible _ [NIL, LAST[CARDINAL]]; n.readers _ n.bidirs _ n.writers _ NIL; n.nextPerturbed _ notInNodeList; IF n.nextAffected # notInNodeList OR n.nextX # notInNodeList OR n.prevX # notInNodeList THEN ERROR; n.watchers _ ALL[NIL]; n.next _ NIL; n.props _ NIL; }; WriteComponent: PROC [ra: REF ANY] RETURNS [stop: BOOL] = { WriteConnection: PROC [type: NodeType, portName: ROPE, ra: REF ANY] = {WITH type SELECT FROM ant: ArrayNodeType => {list: LORA _ NARROW[ra]; FOR i: INTEGER IN [ant.first .. ant.last] DO WriteConnection[ant.element, Sub[portName, i], list.first]; list _ list.rest; ENDLOOP}; ant: AtomNodeType => {w: Wire _ Best[ra]; cellOut.PutF["\n\t\t(%g %g)", IO.refAny[portName], IO.refAny[w.name]]; }; ENDCASE => ERROR}; c: Cell _ NARROW[ra]; prev: Cell _ NIL; bogosity: REF ANY _ List.Assoc[key: bogosityKey, aList: c.props]; stop _ FALSE; IF bogosity = NIL THEN { cellOut.PutF["(CI %g %g\n\t(CIC", IO.refAny[c.name], IO.refAny[c.type.name]]; FOR index: CARDINAL IN [0 .. c.type.ports.length) DO w: REF ANY_ List.Assoc[key: wireKey, aList: c.interfaceNodes[index].props]; WriteConnection[c.type.ports[index].type, c.type.ports[index].name, w]; ENDLOOP; cellOut.PutRope["))\n"]} ELSE IF bogosity = $T THEN NULL ELSE ERROR; IF cell.components.Delete[c] # c THEN ERROR; c.realCellStuff.schedWatchers _ c.realCellStuff.evalWatchers _ NIL; c.realCellStuff.state _ NIL; c.realCellStuff.newIOAsWP _ c.realCellStuff.oldIOAsWP _ c.realCellStuff.switchIOAsWP _ NIL; c.realCellStuff.newIO _ c.realCellStuff.oldIO _ c.realCellStuff.switchIO _ NIL; c.realCellStuff.schedNext _ notInCellList; IF c.realCellStuff.nextNeeded # notInCellList OR c.realCellStuff.nextNoted # notInCellList THEN ERROR; c.realCellStuff _ NIL; c.props _ NIL; c.interfaceNodes _ NIL; IF c.internalNodes.Size[] > 0 OR c.components.Size[] > 0 THEN ERROR; c.internalNodes.DestroyTable[]; c.components.DestroyTable[]; c.internalNodes _ c.components _ NIL; IF c.firstInternalNode # NIL THEN ERROR; IF c.leftChild # NIL THEN ERROR; c.parent _ c.rightSibling _ NIL; c.sim _ NIL; FOR cur: Cell _ c.type.firstInstance, cur.nextInstance WHILE cur # NIL DO IF cur = c THEN {IF prev = NIL THEN c.type.firstInstance _ c.nextInstance ELSE prev.nextInstance _ c.nextInstance; EXIT}; prev _ cur; REPEAT FINISHED => ERROR ENDLOOP; c.nextInstance _ NIL; c.type _ NIL; }; asStr: Structure _ NARROW[cell.realCellStuff.state]; WritePorts[sc, cell.type, cellOut]; cellOut.PutRope["(PrivateFollows)\n"]; cell.internalNodes.EnumerateIncreasing[WriteNode]; WritePortNets[sc, cell.type, cellOut, asStr.insideNodes]; cell.components.EnumerateIncreasing[WriteComponent]; cell.internalNodes.EnumerateIncreasing[DestroyNode]; asStr.firstPerturbed _ NIL; cell.firstInternalNode _ NIL; cell.leftChild _ NIL; cellOut.Close[]; END; Sub: PROC [name: ROPE, i: INTEGER] RETURNS [s: ROPE] = { s _ name.Cat["[", Convert.RopeFromInt[i], "]"]}; WritePorts: PROC [sc: SimCapture, ct: CellType, to: IO.STREAM] = BEGIN WritePort: PROC [type: NodeType, portName: ROPE] = { WITH type SELECT FROM ant: ArrayNodeType => { FOR i: INTEGER IN [ant.first .. ant.last] DO WritePort[ant.element, Sub[portName, i]]; ENDLOOP}; ant: AtomNodeType => to.PutF["\n\t(%g (EC %g \"Structure\"))", IO.refAny[portName], IO.refAny[portName]]; ENDCASE => ERROR}; to.PutRope["(Ports"]; FOR pi: CARDINAL IN [0 .. ct.ports.length) DO WritePort[ct.ports[pi].type, ct.ports[pi].name]; ENDLOOP; to.PutRope[")\n"]; END; WritePortNets: PROC [sc: SimCapture, ct: CellType, to: IO.STREAM, insideNodes: NodeS] = BEGIN WritePortNet: PROC [type: NodeType, portName: ROPE, node: REF ANY] = { WITH type SELECT FROM ant: ArrayNodeType => {l: LORA _ NARROW[node]; FOR i: INTEGER IN [ant.first .. ant.last] DO WritePortNet[ant.element, Sub[portName, i], l.first]; l _ l.rest; ENDLOOP; IF l # NIL THEN ERROR}; ant: AtomNodeType => to.PutF["(PN %g %g)\n", IO.refAny[portName], IO.refAny[Best[node].name]]; ENDCASE => ERROR}; FOR pi: CARDINAL IN [0 .. ct.ports.length) DO WritePortNet[ct.ports[pi].type, ct.ports[pi].name, List.Assoc[key: wireKey, aList: insideNodes[pi].props]]; ENDLOOP; END; NoteConnection: PROC [node: Node, socket: Socket, input, output: BOOLEAN] = BEGIN w: REF ANY _ List.Assoc[key: wireKey, aList: node.props]; IF input THEN BEGIN IF output THEN node.bidirs _ CONS[socket, node.bidirs] ELSE node.readers _ CONS[socket, node.readers]; END ELSE IF output THEN node.writers _ CONS[socket, node.writers] ELSE ERROR; IF w # NIL THEN NoteWireConnection[node.type, w]; END; NoteWireConnection: PROC [type: NodeType, ra: REF ANY] = {WITH type SELECT FROM ant: ArrayNodeType => {list: LORA _ NARROW[ra]; FOR i: INTEGER IN [ant.first .. ant.last] DO NoteWireConnection[ant.element, list.first]; list _ list.rest; ENDLOOP; IF list # NIL THEN ERROR}; ant: AtomNodeType => {w: Wire _ Best[ra]; w.connections _ w.connections + 1}; ENDCASE => ERROR}; FillInInterfaceNodes: PUBLIC PROC [cell: Cell, interfaceNodes: ROPE] = BEGIN index: CARDINAL _ 0; in: IO.STREAM _ IO.RIS[interfaceNodes]; [] _ in.GetIndex[]; --wake up generic GetIndex impl [] _ in.SkipWhitespace[]; IF NOT in.EndOf[] THEN DO name: ROPE _ in.GetTokenRope[IDBreak].token; key: ROPE; this: CARDINAL; [] _ in.SkipWhitespace[]; IF (IF in.EndOf[] THEN FALSE ELSE in.PeekChar[] = ':) THEN BEGIN key _ name; IF in.GetChar[] # ': THEN ERROR; IF in.EndOf[] THEN ERROR Error[IO.PutFR["Interface spec syntax error, at %g", IO.int[in.GetIndex[]]]]; name _ in.GetTokenRope[IDBreak].token; IF (this _ GetIndex[cell.type.ports, key]) = notFound THEN ERROR Error[IO.PutFR["No such port (%g) for CellType %g", IO.rope[key], IO.rope[cell.type.name]]]; END ELSE BEGIN IF index >= cell.interfaceNodes.length THEN ERROR Error[IO.PutFR["No %g'th element in %g's Interface", IO.int[index], IO.rope[cell.type.name]]]; key _ cell.type.ports[this _ index].name; END; IF cell.interfaceNodes[this] # NIL THEN ERROR Error[IO.PutFR["Port %g specified twice in \"%g\"", IO.rope[key], IO.rope[interfaceNodes]]]; cell.interfaceNodes[this] _ LookupCellNode[cell.parent, name]; IF cell.interfaceNodes[this] = NIL THEN ERROR Error[IO.PutFR["Node %g not found", IO.rope[name]]]; IF cell.type.ports[this].output AND cell.interfaceNodes[this].unwriteability > 0 THEN SIGNAL Warning[IO.PutFR["Node %g is, but shouldn't be, written to by port %g of cell %g", IO.rope[cell.interfaceNodes[this].name], IO.rope[cell.type.ports[this].name], IO.rope[cell.name]]]; index _ index + 1; [] _ in.SkipWhitespace[]; IF in.EndOf[] THEN EXIT; IF in.GetChar[] # ', THEN ERROR Error[IO.PutFR["Interface spec syntax error (missing comma), at %g", IO.int[in.GetIndex[]]]]; ENDLOOP; FOR this: CARDINAL IN [0 .. cell.interfaceNodes.length) DO IF cell.interfaceNodes[this] = NIL THEN BEGIN name: ROPE _ cell.type.ports[this].name; cell.interfaceNodes[this] _ LookupCellNode[cell.parent, name]; IF cell.interfaceNodes[this] = NIL THEN ERROR Error[IO.PutFR["Port %g not specified in \"%g\"", IO.rope[name], IO.rope[interfaceNodes]]] ELSE IF cell.type.ports[this].output AND cell.interfaceNodes[this].unwriteability > 0 THEN SIGNAL Warning[IO.PutFR["Node %g is, but shouldn't be, written to by port %g of cell %g", IO.rope[cell.interfaceNodes[this].name], IO.rope[cell.type.ports[this].name], IO.rope[cell.name]]]; END; ENDLOOP; in.Close[]; END; IDBreak: IO.BreakProc = {RETURN [SELECT char FROM IO.SP, IO.CR, IO.LF, IO.TAB => sepr, ',, ': => break, ENDCASE => other]}; GetIndex: PUBLIC PROC [ports: Ports, key: ROPE] RETURNS [index: CARDINAL] = BEGIN FOR i: CARDINAL IN [0..ports.length) DO IF key.Equal[ports[i].name] THEN RETURN [i]; ENDLOOP; RETURN [notFound]; END; FindAndUseExpandDecider: PROC [cell: Cell] RETURNS [ExpandDecision] = BEGIN ed: ExpandDecision; possibilities: [0..3]; [ed, possibilities] _ PickOne[cell]; IF possibilities = 1 THEN RETURN [ed]; IF possibilities = 0 THEN ERROR Error[IO.PutFR["Can't do anything with type %g", IO.rope[cell.type.name]]]; FOR temp: Cell _ cell, temp.parent WHILE temp # NIL DO asAny: REF ANY _ List.Assoc[$ExpandDeciderClosure, temp.props]; edc: ExpandDeciderClosure; try: ExpandDecision; IF asAny = NIL THEN LOOP; edc _ NARROW[asAny]; try _ edc.Decide[cell, edc.otherData]; RETURN [IF Possible[cell, try] THEN try ELSE ed]; ENDLOOP; RETURN [ed]; END; PickOne: PROC [cell: Cell] RETURNS [whatToDo: ExpandDecision, possibilities: [0..3]] = BEGIN possibilities _ 0; FOR i: [1..3] IN [1..3] DO d: ExpandDecision _ orderedChoices[i]; IF Possible[cell, d] THEN {whatToDo _ d; possibilities _ possibilities + 1}; ENDLOOP; END; orderedChoices: ARRAY [1..3] OF ExpandDecision = [Leaf, Nested, Inline]; NoteMaybeVisible: PROC [node: Node, socket: Socket] = INLINE BEGIN IF node.visible.cell = NIL THEN node.visible _ socket ELSE IF node.visible.cell.type.ports[node.visible.index].output THEN RETURN ELSE node.visible _ socket; END; GetMirrorType: PROC [type: CellType] RETURNS [mirrorType: CellType] = BEGIN name: ROPE _ type.name.Concat["-mirror"]; asAny: REF ANY; IF (asAny _ cellTypes.Lookup[name]) # NIL THEN RETURN [NARROW[asAny]]; mirrorType _ RegisterCellType[ name: name, evals: RoseRun.StrMirrorEvals, ports: MirrorPorts[type.ports]]; END; Possible: PUBLIC PROC [cell: Cell, whatToDo: ExpandDecision] RETURNS [possible: BOOLEAN] = BEGIN evalable: BOOL _ cell.type.evals.EvalSimple # NIL OR cell.type.evals.PropUD # NIL; iok: BOOL _ cell.type.ioWordCount = 0 OR cell.type.ioCreator # NIL; capturing: BOOL _ List.Assoc[key: capKey, aList: cell.sim.other] # NIL; RETURN [SELECT whatToDo FROM Leaf => evalable AND iok, Nested => cell.type.expand # NIL AND iok, Inline => cell.type.expand # NIL AND cell.parent # NIL AND NOT capturing, ENDCASE => ERROR]; END; XPhobicize: PUBLIC PROC [n: Node] RETURNS [m: Node-- = n --] = { m _ n; m.XPhobic _ TRUE}; NodeInstance: PROC [erInstance: REF ANY, name: ROPE, type: NodeType, initialValue: ROPE _ NIL, initData: REF ANY _ NIL] RETURNS [node: Node] = BEGIN within: Cell _ NARROW[erInstance]; bits: CARDINAL _ type.procs.Bits[type]; words: CARDINAL _ (bits + 15)/16; sc: SimCapture _ NARROW[List.Assoc[key: capKey, aList: within.sim.other]]; capturing: BOOL _ sc # NIL; node _ NEW [NodeRep _ [ name: name, type: type, cellIn: within, initialValue: initialValue, nextPerturbed: notInNodeList, nextAffected: notInNodeList, nextX: notInNodeList, prevX: notInNodeList, next: within.firstInternalNode ]]; within.internalNodes.Insert[node !OSTR.DuplicateKey => ERROR Error[IO.PutFR["Duplicated Node name: %g", IO.rope[name]]]]; within.firstInternalNode _ node; --link in wrong order now; fix up when done expanding-- IF type.procs.InitNode # NIL THEN type.procs.InitNode[node, initData, within.sim.steady]; IF initialValue # NIL AND NOT node.type.simple THEN Initialize[node, NIL]; IF NOT node.type.simple THEN RoseRun.PerturbNode[node, within]; IF capturing THEN node.props _ List.PutAssoc[key: wireKey, val: CreateWires[type, name], aList: node.props]; END; wireKey: REF ANY _ NEW [ROPE _ "wire key"]; CreateWires: PROC [type: NodeType, name: ROPE] RETURNS [ra: REF ANY] = BEGIN WITH type SELECT FROM ant: ArrayNodeType => { list: LORA _ NIL; FOR i: INTEGER DECREASING IN [ant.first .. ant.last] DO list _ CONS[CreateWires[ant.element, Sub[name, i]], list]; ENDLOOP; ra _ list}; ant: AtomNodeType => ra _ NEW [WireRep _ [name: name]]; ENDCASE => ERROR END; Wire: TYPE = REF WireRep; WireRep: TYPE = RECORD [name: ROPE, better: Wire _ NIL, connections: CARDINAL _ 0]; Initialize: PROC [node: Node, wp: WordPtr] = BEGIN ivs: IO.STREAM _ IO.RIS[node.initialValue]; fmt: Format _ node.type.procs.GetFormat[node.type, NIL]; ok: BOOLEAN _ fmt.ParseValue[ node, fmt, wp, ivs]; ivs.Close[]; IF NOT ok THEN { SIGNAL Warning[IO.PutFR[ "Unable to parse %g by default format (%g) for node %g (of type %g)", IO.rope[Convert.RopeFromRope[node.initialValue]], IO.rope[fmt.key], IO.rope[node.name], IO.rope[node.type.procs.UserDescription[node.type]]]]; node.initialValue _ NIL}; END; SplitJoin: PROC [erInstance: REF ANY, a, b: StretchList, writeA, writeB: BOOLEAN] = BEGIN within: Cell _ NARROW[erInstance]; sc: SimCapture _ NARROW[List.Assoc[key: capKey, aList: within.sim.other]]; c: Cell; IF (a = NIL) # (b = NIL) THEN ERROR; IF a = NIL THEN RETURN; c _ a.first.node.type.procs.MakeSplitJoin[within, a, b, writeA, writeB, [erInstance, simERClass]]; IF c = NIL THEN ERROR; c.props _ List.PutAssoc[key: bogosityKey, val: $T, aList: c.props]; IF sc # NIL THEN { aWires: LIST OF Wire _ Squash[a]; bWires: LIST OF Wire _ Squash[b]; DO IF (aWires = NIL) # (bWires = NIL) THEN ERROR; IF aWires = NIL THEN EXIT; bWires.first.better _ aWires.first; aWires _ aWires.rest; bWires _ bWires.rest; ENDLOOP; }; END; Squash: PROC [sl: StretchList] RETURNS [wl: LIST OF Wire] = BEGIN SquashStretch: PROC [s: Stretch] = {WITH s SELECT FROM ss: SingleStretch => {w: Wire _ NARROW[List.Assoc[key: wireKey, aList: s.node.props]]; wl _ CONS[w, wl]}; ss: SubStretch => {l: LORA _ NARROW[List.Assoc[key: wireKey, aList: s.node.props]]; ant: ArrayNodeType _ NARROW[s.node.type]; FOR i: INTEGER IN [ant.first .. ant.last] DO IF i IN [ss.first .. ss.last] THEN wl _ CONS[NARROW[l.first], wl]; l _ l.rest; ENDLOOP; IF l # NIL THEN ERROR}; ENDCASE => ERROR}; wl _ NIL; FOR sl _ sl, sl.rest WHILE sl # NIL DO SquashStretch[sl.first] ENDLOOP; END; ChangeReps: PROC [erInstance: REF ANY, a, b: Node, writeA, writeB: BOOLEAN] = BEGIN within: Cell _ NARROW[erInstance]; wa: REF ANY _ List.Assoc[key: wireKey, aList: a.props]; wb: REF ANY _ List.Assoc[key: wireKey, aList: b.props]; c: Cell _ NIL; IF c = NIL AND a.type.procs.MakeTransducer # NIL THEN c _ a.type.procs.MakeTransducer[a, b, within, writeA, writeB, [erInstance, simERClass]]; IF c = NIL AND b.type.procs.MakeTransducer # NIL THEN c _ b.type.procs.MakeTransducer[b, a, within, writeB, writeA, [erInstance, simERClass]]; IF c = NIL THEN ERROR; c.props _ List.PutAssoc[key: bogosityKey, val: $T, aList: c.props]; IF (wa # NIL) # (wb # NIL) THEN ERROR; IF wa # NIL THEN ChangeWires[a.type, b.type, wa, wb]; END; ChangeWires: PROC [aType, bType: NodeType, a, b: REF ANY] = {WITH aType SELECT FROM ant: ArrayNodeType => {bnt: ArrayNodeType _ NARROW[bType]; aList: LORA _ NARROW[a]; bList: LORA _ NARROW[b]; IF ant.first # bnt.first OR ant.last # bnt.last THEN ERROR; FOR i: INTEGER IN [ant.first .. ant.last] DO ChangeWires[ant.element, bnt.element, aList.first, bList.first]; aList _ aList.rest; bList _ bList.rest; ENDLOOP}; ant: AtomNodeType => {bnt: AtomNodeType _ NARROW[bType]; wa: Wire _ Best[a]; wb: Wire _ Best[b]; wb.better _ wa; wa.connections _ wa.connections + wb.connections}; ENDCASE => ERROR}; END. z[Indigo]2.6>Rosemary.df=>RoseCreateImpl.Mesa Last Edited by: Spreitzer, September 1, 1984 7:23:21 pm PDT Κ#œ– "cedar" style˜J™6J™;J˜IcodešΟk œœœP˜qK˜šΠbxœœ˜Kšœ œœœI˜lKšœ˜—K˜Kšœœ˜!K˜Kš œœœœœœ˜K˜Kšœœ˜Kšœ˜Kšœ˜—šœœœ˜4Kšœ0˜0—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šœ ˜ Kšœ ˜ Kšœ&˜&Kšœ(˜(Kšœ(˜(Kšœ.˜.Kšœ˜Kšœ"˜"——š œœœœœœ˜EKšœ/˜/Kšœ˜Kšœ(˜(šœœœ˜Kšœ6˜6Kšœq˜qKšœ˜—Kšœœœ;˜_Kšœ˜—šœ ˜Kš˜šœœœ˜Kšœœœ˜)K˜4Kšœ˜K˜—Kš˜—Kšœ5˜9Kš˜—šœ˜ šœ ˜Kš˜šœœœ˜Kšœœœ˜)Kšœ˜Kšœ7˜7K˜ K˜—Kšœ˜—Kšœ˜—Kšœ˜—Kšœœ˜—Kšœ œ˜K˜šœ œ˜K˜)K˜#K˜K˜Kšœ˜—K˜Kšœ œ˜K˜"šœ œ˜K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ"˜"šœ˜ Kš œœœœ#œ˜sKšœœœ˜C—Kšœ˜—K˜šŸœœœ œ˜MKš˜Kš œ œœœœ˜[Kšœ œ˜*Kšœ*œœ˜XKšœ;œœ ˜aKšœN˜NKšœ˜—K˜š Ÿœœœœœœ˜=Kšœ œœœ˜.—K˜šŸ œœ'œ˜CKš˜š Ÿ œœœœœœ˜6šŸ œœœœ˜2šœœ˜šœœœ˜/šœœœ˜(K˜6Kšœ˜ ——šœ œ˜+šœ œœ˜Kšœœ˜.——Kšœœ˜——Kšœ œ˜Kšœœœ,˜6Kšœœ˜ K˜K˜—š Ÿ œœœœœœ˜8Kšœ œ˜Kšœœ˜ Kšœ"œœ˜/Kšœ œ˜ Kšœ œ˜ Kšœœ˜Kšœ œ˜Kšœ œœœ˜"Kšœ#œ˜'Kšœ ˜ Kš œ œœœœ˜cKšœ œœ˜Kšœ œ˜ Kšœ œ˜K˜—š Ÿœœœœœœ˜;š Ÿœœœœœ˜Ešœœœ˜šœœœ˜/šœœœ˜,Kšœ;˜;Kšœ˜Kšœ˜ ——šœ)˜)Kšœœœ˜FK˜—Kšœœ˜——Kšœ œ˜Kšœ œ˜Kšœ œœ0˜AKšœœ˜ šœ œœ˜Kšœ"œœ˜Mšœœœ˜4KšœœœA˜KKšœG˜GKšœ˜—Kšœ˜—Kš œœœœœœ˜+Kšœœœ˜,Kšœ?œ˜CKšœœ˜KšœWœ˜[KšœKœ˜OKšœ*˜*Kšœ,œ,œœ˜gKšœœ˜Kšœ œ˜Kšœœ˜Kšœœœœ˜DKšœ˜Kšœ˜Kšœ!œ˜%Kšœœœœ˜(Kšœœœœ˜ Kšœœ˜ Kšœœ˜ šœ4œœ˜IKšœ œœœœ'œ%œ˜yK˜ Kšœœœœ˜!—Kšœœ˜Kšœ œ˜ K˜—Kšœœ˜4Kšœ#˜#K˜&Kšœ2˜2Kšœ9˜9Kšœ4˜4Kšœ4˜4Kšœœ˜Kšœœ˜Kšœœ˜Kšœ˜Kšœ˜—K˜š Ÿœœœœœœ˜8K˜0—K˜šŸ œœ$œœ˜@Kš˜šŸ œœœ˜4šœœ˜šœ˜šœœœ˜,Kšœ)˜)Kšœ˜ ——Kšœ?œœ˜iKšœœ˜——K˜šœœœ˜-Kšœ0˜0Kšœ˜—K˜Kšœ˜—K˜šŸ œœ$œœ˜WKš˜š Ÿ œœœœœ˜Fšœœ˜šœœœ˜.šœœœ˜,Kšœ5˜5K˜ Kšœ˜—Kšœœœœ˜—Kšœ-œœ˜^Kšœœ˜——šœœœ˜-šœ˜Kšœ˜Kšœ8˜8—Kšœ˜—Kšœ˜—K˜šŸœœ-œ˜KKš˜Kšœœœ/˜9šœ˜ Kš˜Kšœœœ˜6Kšœœ˜/Kš˜—Kšœœœœ˜=Kšœœ˜ Kšœœœ"˜1Kšœ˜—K˜šŸœœœœ˜8šœœœ˜šœœœ˜/šœœœ˜,Kšœ,˜,K˜Kšœ˜—Kšœœœœ˜—šœ)˜)Kšœ#˜#—Kšœœ˜——K˜šŸœœœœ˜FKš˜Kšœœ˜Kš œœœœœ˜'Kšœ ˜3Kšœ˜šœœ œ˜Kšœœ"˜,Kšœœ˜ Kšœœ˜Kšœ˜š œœ œœœ˜:Kš˜K˜ Kšœœœ˜ Kš œ œœœ-œ˜fKšœ&˜&Kš œ4œœœ,œ œ˜Kš˜—šœ˜ Kš œ%œœœ-œ œ˜Kšœ)˜)Kšœ˜—Kšœœœœœ,œ œ˜ŠK˜>Kš œœœœœœ˜bKšœœ.œœ œIœ'œ#œ˜“K˜Kšœ˜Kšœ œœ˜Kš œœœœ=œ˜}Kšœ˜—šœœœ#˜:šœœ˜'Kš˜Kšœœ˜(K˜>Kšœœœœœ*œ œ˜ˆKšœœœ.œœ œIœ'œ#œ˜˜Kšœ˜—Kšœ˜—K˜ Kšœ˜—K˜šŸœœ ˜šœœœ˜Kšœœœœœœœœ ˜$Kšœ˜Kšœ ˜——K˜š Ÿœœœœœ œ˜KKš˜šœœœ˜'Kšœœœ˜,Kšœ˜—Kšœ ˜Kšœ˜—K˜šŸœœœ˜EKš˜K˜K˜K˜$Kšœœœ˜&Kš œœœœ)œ˜kšœ œœ˜6Kšœœœ1˜?K˜Kšœ˜Kšœ œœœ˜Kšœœ˜Kšœ&˜&Kšœœœœ˜1Kšœ˜—Kšœ˜ Kšœ˜—K˜šŸœœœ4˜VKš˜K˜šœ œ˜Kšœ&˜&Kšœœ3˜LKšœ˜—Kšœ˜—K˜Kšœœœ)˜HK˜šŸœœ ˜