[Indigo]<Rosemary>3.0>Rosemary.df=>RoseCaptureImpl.Mesa
Last Edited by: Spreitzer, May 8, 1985 3:19:11 pm PDT
DIRECTORY Asserting, AssertingIO, Convert, FS, GetMe, IO, OrderedSymbolTableRef, PupDefs, Rope, RoseCapture, RoseCreate, RoseTypes, UserCredentials;
RoseCaptureImpl:
CEDAR
PROGRAM
IMPORTS Asserting, AssertingIO, Convert, FS, GetMe, IO, OrderedSymbolTableRef, PupDefs, Rope, RoseCreate, RoseTypes, UserCredentials
EXPORTS RoseCapture =
BEGIN OPEN RoseTypes;
LORA: TYPE = LIST OF REF ANY;
DesignCapture: TYPE = REF DesignCaptureRep;
DesignCaptureRep:
TYPE =
RECORD [
fileNameRoot: ROPE,
dfOut: STREAM,
genCount: INT ← 0
];
CTCapture: TYPE = REF CTCaptureRep;
CTCaptureRep:
TYPE =
RECORD [
dc: DesignCapture,
cellOut: STREAM,
cell: Cell
];
Wire: TYPE = REF WireRep;
WireRep: TYPE = RECORD [name: ROPE, better: Wire ← NIL, worse: WireList ← NIL];
WireList: TYPE = LIST OF Wire;
machineName: ROPE ← "??";
userName: ROPE ← "??";
capKey: ATOM ← $Capture;
wireKey: ATOM ← $Wire;
captureExpansion: ERClass ←
NEW [ERClassRep ← [
CellInstance: CellInstance,
NodeInstance: NodeInstance,
Equivalence: Equivalence
]];
Log:
PROC [format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] =
BEGIN
msg: ROPE ← IO.PutFR[format, v1, v2, v3, v4, v5];
SIGNAL Warning[msg];
END;
CaptureDesign:
PUBLIC
PROC [directory, designName, topCellTypeName:
ROPE] =
BEGIN
fileNameRoot: ROPE ← designName;
dfName: ROPE ← fileNameRoot.Cat["-Str.DF"];
dc: DesignCapture ← NEW [DesignCaptureRep ← [fileNameRoot, FS.StreamOpen[dfName, create]]];
topCellType: CellType ← RoseCreate.GetCellType[topCellTypeName];
IF topCellType = NIL THEN {Log["No such cell type as %g", IO.refAny[topCellTypeName]]; RETURN};
machineName ← PupDefs.GetMyName[];
userName ← UserCredentials.Get[].name;
dc.dfOut.PutF["-- (DesignName %g)\n", IO.refAny[designName]];
dc.dfOut.PutF["-- (CreatingUser %g)\n", IO.refAny[userName]];
dc.dfOut.PutF["-- (CreationTime \"%g\")\n", IO.time[]];
dc.dfOut.PutF["-- (CreationSite \"MilkyWay Sol III USA Xerox PARC ComputerResearch %q\")\n", IO.rope[machineName]];
dc.dfOut.PutF["-- (DerivingProgram \"Rosemary Structure Capturer\" %g)\n", IO.refAny[GetMe.StandardScrewyEncoding[GetMe.GetVersion[]]]];
dc.dfOut.PutF["\n\nDirectory %g\n %g\n", IO.rope[directory], IO.rope[dfName]];
CaptureCellType[dc, topCellType];
dc.dfOut.Close[];
END;
CaptureCellType:
PROC [dc: DesignCapture, cellType: CellType] =
BEGIN
cell: Cell ←
NEW [CellRep ← [
name: Rope.Cat["An instance of ", cellType.name, ", which is being captured"],
type: cellType,
parent: NIL,
internalNodes: OrderedSymbolTableRef.CreateTable[ RoseCreate.CompareNodes],
components: OrderedSymbolTableRef.CreateTable[ RoseCreate.CompareComponents],
interfaceNodes: NEW [NodeSR[cellType.ports.length]],
substantiality: Shadow,
expansion: Expand
]];
WriteNode:
PROC [ra:
REF
ANY]
RETURNS [stop:
BOOL] = {
WriteAliases:
PROC [worse: WireList] = {
FOR worse ← worse, worse.rest
WHILE worse #
NIL
DO
ctc.cellOut.PutF[" (%g (G P))", IO.refAny[worse.first.name]];
WriteAliases[worse.first.worse];
ENDLOOP};
WriteWires:
PROC [type: NodeType, ra:
REF
ANY, other: Assertions] = {
WITH type
SELECT
FROM
ant: ArrayNodeType => {list:
LORA ←
NARROW[ra];
FOR i:
INT
IN [0 .. ant.length)
DO
WriteWires[ant.element, list.first, other]; list ← list.rest;
ENDLOOP};
ant: AtomNodeType => {w: Wire ←
NARROW[ra];
IF w.better =
NIL
THEN {
ctc.cellOut.PutF["(N %g (G D)", IO.refAny[w.name]];
IF w.worse #
NIL
THEN {
ctc.cellOut.PutRope[" (A"];
WriteAliases[w.worse];
ctc.cellOut.PutRope[")"]};
FOR ol: Assertions ← other, ol.rest
WHILE ol #
NIL
DO
ctc.cellOut.PutRope[" "];
AssertingIO.WriteAssn[ctc.cellOut, ol.first];
ENDLOOP;
ctc.cellOut.PutRope[")\n"];
};
};
ENDCASE => ERROR};
n: Node ← NARROW[ra];
w: REF ANY ← Asserting.FnVal[fn: wireKey, from: n.other];
stop ← FALSE;
WriteWires[n.type, w, Asserting.Filter[reln: wireKey, from: n.other].notAbout];
};
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.cellIn ← NIL;
IF n.nextPerturbed # notInNodeList OR n.nextAffected # notInNodeList OR n.nextDelayed # notInNodeList OR n.prevDelayed # notInNodeList THEN ERROR;
n.watchers ← ALL[NIL];
n.designNext ← NIL;
n.other ← 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 [0 .. ant.length)
DO
WriteConnection[ant.element, Sub[portName, i], list.first];
list ← list.rest;
ENDLOOP};
ant: AtomNodeType => {w: Wire ← Best[ra];
ctc.cellOut.PutF["\n\t\t(%g %g)", IO.refAny[portName], IO.refAny[w.name]];
};
ENDCASE => ERROR};
c: Cell ← NARROW[ra];
prev: Cell ← NIL;
stop ← FALSE;
ctc.cellOut.PutF["(CI %g %g (G D)\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← Asserting.FnVal[fn: wireKey, from: c.interfaceNodes[index].other];
WriteConnection[c.type.ports[index].type, c.type.ports[index].name, w];
ENDLOOP;
ctc.cellOut.PutRope[")"];
FOR ol: Assertions ← c.other, ol.rest
WHILE ol #
NIL
DO
ctc.cellOut.PutRope["\n\t"];
AssertingIO.WriteAssn[ctc.cellOut, ol.first];
ENDLOOP;
ctc.cellOut.PutRope[")\n"];
SELECT Asserting.FnVal[fn: capKey, from: c.type.other]
FROM
ctc.dc => NULL;
ENDCASE => CaptureCellType[ctc.dc, c.type];
IF cell.components.Delete[c] # c THEN ERROR;
IF c.realCellStuff # NIL THEN ERROR;
c.other ← NIL;
c.interfaceNodes ← NIL;
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;
c.nextInstance ← NIL;
c.type ← NIL;
};
cellFileName: ROPE ← CellTypeFileName[dc, cellType];
ctc: CTCapture ←
NEW [CTCaptureRep ← [
dc: dc,
cellOut: FS.StreamOpen[cellFileName, create],
cell: cell
]];
cellType.other ← Asserting.AssertFn1[fn: capKey, val: dc, inAdditionTo: cellType.other];
dc.dfOut.PutF["\n-- (CellType %g)\n %g\n", IO.refAny[cellType.name], IO.rope[cellFileName]];
ctc.cellOut.PutF["(CellTypeName %g)\n", IO.refAny[cellType.name]];
ctc.cellOut.PutF["(CreationTime \"%g\")\n", IO.time[]];
ctc.cellOut.PutF["(CreatingUser %g)\n", IO.refAny[userName]];
ctc.cellOut.PutF["(CreationSite \"MilkyWay Sol III USA Xerox PARC ComputerResearch %q\")\n", IO.rope[machineName]];
ctc.cellOut.PutF["(DerivingProgram \"Rosemary Structure Capturer\" %g)\n", IO.refAny[GetMe.StandardScrewyEncoding[GetMe.GetVersion[]]]];
WritePorts[cellType, ctc.cellOut];
WriteAssertions[cellType.other, ctc.cellOut];
ctc.cellOut.PutRope["(PrivateFollows)\n"];
IF cellType.expand #
NIL
THEN {
FOR pi: PortIndex
IN [0 .. cellType.ports.length)
DO
port: Port ← cellType.ports[pi];
cell.interfaceNodes[pi] ← captureExpansion.NodeInstance[ctc, port.name, port.type];
ENDLOOP;
cellType.expand[ctc.cell, [ctc, captureExpansion]];
cell.internalNodes.EnumerateIncreasing[WriteNode];
WritePortNets[cellType, ctc.cellOut, cell.interfaceNodes];
cell.components.EnumerateIncreasing[WriteComponent];
cell.internalNodes.EnumerateIncreasing[DestroyNode];
}
ELSE ctc.cellOut.PutRope["(InsidesUnspecified)\n"];
ctc.cellOut.Close[];
END;
CellTypeFileName:
PROC [dc: DesignCapture, cellType: CellType]
RETURNS [cellFileName:
ROPE] = {
fullCellFileName: ROPE;
cp: FS.ComponentPositions;
cellFileName ← NIL;
[fullCellFileName, cp, ] ← FS.ExpandName[cellType.name !FS.Error => CONTINUE];
IF fullCellFileName # NIL AND fullCellFileName.Substr[start: cp.base.start, len: cp.base.length].Equal[cellType.name] THEN RETURN [cellType.name.Cat[".sch"]];
cellFileName ← IO.PutFR["%g-%g.sch", IO.rope[dc.fileNameRoot], IO.card[dc.genCount ← dc.genCount + 1]];
};
WriteAssertions:
PROC [assertions: Assertions, to:
IO.
STREAM] =
BEGIN
FOR assertions ← assertions, assertions.rest
WHILE assertions #
NIL
DO
AssertingIO.WriteAssn[to: to, assertion: assertions.first];
to.PutRope["\n"];
WITH assertions.first.first SELECT FROM
a: ATOM => SELECT a FROM
$Capture => LOOP;
ENDCASE;
ENDCASE => ERROR;
to.PutF["%g\n", IO.refAny[assertions.first]];
ENDLOOP;
END;
WritePorts:
PROC [ct: CellType, to:
IO.
STREAM] =
BEGIN
dir: ROPE;
other: Assertions;
WritePort:
PROC [type: NodeType, portName, ecName:
ROPE] = {
WITH type
SELECT
FROM
ant: ArrayNodeType => {
IF ecName # NIL THEN Log["undoable equivalence class (%g) for port %g of cell type %g", IO.refAny[ecName], IO.refAny[portName], IO.refAny[ct.name]];
FOR i:
INTEGER
IN [0 .. ant.length)
DO
WritePort[ant.element, Sub[portName, i], NIL];
ENDLOOP};
ant: AtomNodeType => {
to.PutF["\n\t(%g (G D) (%g)", IO.refAny[portName], IO.rope[dir]];
IF (ecName # NIL) AND (NOT ecName.Equal[portName]) THEN to.PutF[" (EC \"Structure\" %g)", IO.refAny[ecName]];
FOR al: Assertions ← other, al.rest
WHILE al #
NIL
DO
to.PutChar[' ];
AssertingIO.WriteAssn[to, al.first];
ENDLOOP;
to.PutRope[")"];
};
ENDCASE => ERROR};
to.PutRope["(Ports"];
FOR pi:
CARDINAL
IN [0 .. ct.ports.length)
DO
ec: ROPE ← NARROW[Asserting.FnVal[$EC, ct.ports[pi].other, LIST[NARROW["Structure", ROPE]]]];
dir ← IF ct.ports[pi].input THEN (IF ct.ports[pi].output THEN "BIDIR" ELSE "IN") ELSE IF ct.ports[pi].output THEN "OUT" ELSE ERROR;
other ← Asserting.Filter[$EC, ct.ports[pi].other].notAbout;
WritePort[ct.ports[pi].type, ct.ports[pi].name, ec];
ENDLOOP;
to.PutRope[")\n"];
END;
WritePortNets:
PROC [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 [0 .. ant.length)
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,
Asserting.FnVal[fn: wireKey, from: insideNodes[pi].other]];
ENDLOOP;
END;
NodeInstance:
PROC [erInstance:
REF
ANY, name:
ROPE, type: NodeType, initialValue, initialValueFormat:
ROPE ←
NIL, initData:
REF
ANY ←
NIL, other: Assertions ←
NIL]
RETURNS [node: Node] =
BEGIN
ctc: CTCapture ← NARROW[erInstance];
node ←
NEW [NodeRep ← [
name: name,
type: type,
cellIn: ctc.cell,
nextPerturbed: notInNodeList,
nextAffected: notInNodeList,
nextDelayed: notInNodeList,
prevDelayed: notInNodeList,
significances: designOnly,
other: other]];
ctc.cell.internalNodes.Insert[node !OrderedSymbolTableRef.DuplicateKey => {Log["Duplicated Node name: %g", IO.rope[name]]; CONTINUE}];
node.other ← Asserting.AssertFn1[fn: wireKey, val: CreateWires[type, name], inAdditionTo: node.other];
END;
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 [0 .. ant.length)
DO
list ← CONS[CreateWires[ant.element, Sub[name, i]], list];
ENDLOOP;
ra ← list};
ant: AtomNodeType =>
ra ← NEW [WireRep ← [name: name]];
ENDCASE => ERROR
END;
CellInstance:
PROC [erInstance:
REF
ANY, instanceName, typeName, interfaceNodes:
ROPE, other: Assertions ←
NIL]
RETURNS [cell: Cell] =
BEGIN
ctc: CTCapture ← NARROW[erInstance];
type: CellType ← RoseCreate.GetCellType[typeName];
IF type =
NIL
THEN Log["No such cell type as %g", IO.refAny[typeName]]
ELSE {
cell ←
NEW [CellRep ← [
name: instanceName,
type: type,
parent: ctc.cell,
internalNodes: OrderedSymbolTableRef.CreateTable[ RoseCreate.CompareNodes],
components: OrderedSymbolTableRef.CreateTable[ RoseCreate.CompareComponents],
interfaceNodes: NEW [NodeSR[type.ports.length]],
substantiality: Shadow,
expansion: Expand,
other: other
]];
RoseCreate.FillInInterfaceNodes[cell, interfaceNodes];
ctc.cell.components.Insert[cell !OrderedSymbolTableRef.DuplicateKey => {Log["Duplicated Cell name: %g", IO.rope[instanceName]]; CONTINUE}];
};
END;
Equivalence:
PROC [erInstance:
REF
ANY, a, b: NodeExpression] =
BEGIN
aWires: LORA ← Flatten[[NIL, NIL], a].head;
bWires: LORA ← Flatten[[NIL, NIL], b].head;
IF (a = NIL) # (b = NIL) THEN ERROR;
IF a = NIL THEN RETURN;
DO
IF (aWires = NIL) # (bWires = NIL) THEN ERROR;
IF aWires = NIL THEN EXIT;
MergeWires[aWires.first, bWires.first];
aWires ← aWires.rest;
bWires ← bWires.rest;
ENDLOOP;
END;
TList: TYPE = RECORD [head, tail: LORA];
Flatten:
PROC [prefix: TList, ne: NodeExpression]
RETURNS [wtl: TList] = {
WITH ne
SELECT
FROM
x: PrimaryNE => {
wl: LORA ← GetNodeWires[x.node];
wtl ← TLCat[prefix, WLSelect[wl, x.selector]];
};
x: UnnamedConsNE => {
wtl ← prefix;
FOR elts:
LIST
OF PrimaryNE ← x.elts, elts.rest
WHILE elts #
NIL
DO
wtl ← Flatten[wtl, elts.first];
ENDLOOP;
};
x: CatenateNE => {
wtl ← prefix;
FOR pieces:
LIST
OF NodeExpression ← x.pieces, pieces.rest
WHILE pieces #
NIL
DO
wtl ← Flatten[wtl, pieces.first];
ENDLOOP;
};
ENDCASE => ERROR;
};
GetNodeWires:
PROC [n: Node]
RETURNS [wl:
LORA] = {
ra: REF ANY ← Asserting.FnVal[fn: wireKey, from: n.other];
WITH ra
SELECT
FROM
w: Wire => RETURN [LIST[w]];
x: LORA => RETURN [x];
ENDCASE => ERROR;
};
WLSelect:
PROC [wl:
LORA, s: Selector]
RETURNS [wtl: TList] = {
WITH s
SELECT
FROM
whole => {
wtl ← [NIL, NIL];
FOR wl ← wl, wl.rest
WHILE wl #
NIL
DO
wtl ← TLAppend[wtl, wl.first];
ENDLOOP;
};
number => {
FOR i:
INT
IN [0 .. index)
DO
wl ← wl.rest;
ENDLOOP;
wl ← LIST[wl.first];
wtl ← [wl, wl];
};
range => {
min, max: INT;
IF up
THEN {min ← first; max ← first + count - 1}
ELSE {min ← first + 1 - count; max ← first};
FOR i: INT IN [0 .. min) DO wl ← wl.rest ENDLOOP;
wtl ← [NIL, NIL];
FOR i:
INT
IN [min .. max)
DO
wtl ← TLAppend[wtl, wl.first];
wl ← wl.rest;
ENDLOOP;
};
ENDCASE => ERROR;
};
TLAppend:
PROC [wtl: TList, r:
REF
ANY]
RETURNS [wul: TList] = {
this: LORA ← LIST[r];
wul ← wtl;
IF wul.tail # NIL THEN wul.tail.rest ← this ELSE wul.head ← this;
wul.tail ← this;
};
TLCat:
PROC [a, b: TList]
RETURNS [c: TList] = {
IF a = [NIL, NIL] THEN RETURN [b];
IF b = [NIL, NIL] THEN RETURN [a];
c ← [a.head, b.tail];
a.tail.rest ← b.head;
};
MergeWires:
PROC [a, b:
REF
ANY] = {
wa: Wire ← Best[a];
wb: Wire ← Best[b];
IF wa # wb
THEN {wb.better ← wa; wa.worse ← CONS[wb, wa.worse]}
ELSE ERROR;
};
Best:
PROC [ra:
REF
ANY]
RETURNS [w: Wire] = {w ←
NARROW[ra];
WHILE w.better # NIL DO w ← w.better ENDLOOP};
Sub:
PROC [name:
ROPE, i:
INTEGER]
RETURNS [s:
ROPE] = {
s ← name.Cat["[", Convert.RopeFromInt[i], "]"]};
Setup:
PROC = {
AssertingIO.SetWriter[capKey, AssertingIO.DontWrite];
};
Setup[];
END.