[Indigo]<Rosemary>2.6>Rosemary.df=>RoseCreateImpl.Mesa
Last Edited by: Spreitzer, September 1, 1984 7:23:21 pm PDT
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.