LichenWrite.Mesa
Last Edited by: Spreitzer, July 15, 1985 7:47:05 pm PDT
DIRECTORY AssertingIO, Basics, Convert, DFUtilities, FS, IO, LichenDataStructure, LichenOps, List, RedBlackTree, RedBlackTreeExtras, Rope, ViewerIO;
LichenWrite: CEDAR PROGRAM
IMPORTS AssertingIO, Convert, FS, IO, LichenDataStructure, LichenOps, RedBlackTree, RedBlackTreeExtras, Rope =
BEGIN OPEN LichenDataStructure, LichenOps;
WriteDesign: PROC [design: Design, root, sub, directory: ROPE] = {
dfName: ROPE ← root.Cat["-Str.DF"];
dfOut: IO.STREAMFS.StreamOpen[sub.Cat[">", dfName], create];
count: NAT ← 0;
NameAndOpen: PROC [cellTypeName: ROPE] RETURNS [fileName: ROPE, stream: IO.STREAM] = {
stream ← NIL;
fileName ← cellTypeName.Cat[".sch"];
stream ← FS.StreamOpen[sub.Cat[">", fileName], create !FS.Error => CONTINUE];
IF stream # NIL THEN RETURN;
fileName ← IO.PutFR["%g-%g.sch", IO.rope[root], IO.card[count ← count+1]];
stream ← FS.StreamOpen[sub.Cat[">", fileName], create];
};
PerCellType: PROC [ra: REF ANY] RETURNS [quit: BOOL] = {
ct: CellType ← NARROW[ra];
cellFileName: ROPE;
cellOut: IO.STREAM;
quit ← FALSE;
[cellFileName, cellOut] ← NameAndOpen[PickAName[ct.names]];
dfOut.PutF["\n-- (CellType %g)\n %g\n", IO.rope[NameStuff[ct.names]], IO.rope[cellFileName]];
cellOut.PutF["(CellTypeName %g)\n", IO.rope[NameStuff[ct.names]]];
IF (ct.equivClass # implicitClass) THEN cellOut.PutF["(EC %g \"Structure\")\n", IO.refAny[ct.equivClass]];
AssertingIO.WriteTail[cellOut, ct.otherPublic];
cellOut.PutRope["\n"];
EnsurePorts[ct];
WritePorts[cellOut, ct];
cellOut.PutRope["(PrivateFollows)\n"];
EnsureParts[ct];
IF NOT ExpansionKnown[ct]
THEN cellOut.PutRope["(InsidesUnspecified)\n"]
ELSE SELECT GetInternalStyle[ct] FROM
graph => {
WriteNets[cellOut, ct];
WritePortNets[cellOut, ct];
WriteComponents[cellOut, ct];
};
array => WriteArray[cellOut, ct];
ENDCASE => ERROR;
AssertingIO.WriteTail[cellOut, ct.otherPrivate];
cellOut.PutRope["\n"];
cellOut.Close[];
};
dfOut.PutF["-- %g written by CompareWrite at %g\n", IO.rope[dfName], IO.time[]];
FOR al: Assertions ← design.other, al.rest WHILE al # NIL DO
dfOut.PutRope["-- "];
AssertingIO.WriteAssn[dfOut, al.first];
dfOut.PutRope["\n"];
ENDLOOP;
AssertingIO.WriteTail[dfOut, design.other];
dfOut.PutRope["\n"];
dfOut.PutF["\nExports %g%g>\n %g\n", IO.rope[directory], IO.rope[sub], IO.rope[dfName]];
RedBlackTreeExtras.StatelessEnumerateIncreasing[design.cellTypesByAddress, PerCellType, GetIDKey];
dfOut.Close[];
};
WritePorts: PROC [to: IO.STREAM, ct: CellType] = {
to.PutRope["(Ports"];
FOR pi: NAT IN [0 .. ct.ports.length) DO
to.PutF["\n\t(%g", IO.rope[NameStuff[ct.ports[pi].names]]];
IF ct.ports[pi].equivClass # implicitClass THEN to.PutF[" (EC %g \"Structure\")", IO.refAny[ct.ports[pi].equivClass]];
AssertingIO.WriteTail[to, ct.ports[pi].other];
to.PutRope[")"];
ENDLOOP;
to.PutRope[")\n"];
};
WritePortNets: PROC [to: IO.STREAM, ct: CellType] = {
FOR pi: NAT IN [0 .. ct.ports.length) DO
aName: ROPE ← PickAName[ct.ports[pi].names];
FOR nnl: RopeList ← ct.ports[pi].netNames, nnl.rest WHILE nnl # NIL DO
to.PutF["(PN %g %g)\n", IO.refAny[aName], IO.refAny[nnl.first]];
ENDLOOP;
ENDLOOP;
};
WriteNets: PROC [to: IO.STREAM, ct: CellType] = {
PerPart: PROC [asAny: REF ANY] RETURNS [stop: BOOL] = {
a: Alias ← NARROW[asAny];
v: Vertex ← NARROW[a.thing];
stop ← FALSE;
IF PickAName[v.names] # a.name THEN RETURN;
SELECT v.class FROM
net => {
to.PutF["(N %g", IO.rope[NameStuff[v.names]]];
AssertingIO.WriteTail[to, v.other];
to.PutRope[")\n"];
};
cell => NULL;
ENDCASE => ERROR;
};
ct.parts.EnumerateIncreasing[PerPart];
};
WriteComponents: PROC [to: IO.STREAM, ct: CellType] = {
PerPart: PROC [asAny: REF ANY] RETURNS [stop: BOOL] = {
a: Alias ← NARROW[asAny];
v: Vertex ← NARROW[a.thing];
stop ← FALSE;
IF PickAName[v.names] # a.name THEN RETURN;
AM1 tells us we don't have to worry about this being the mirror.
SELECT v.class FROM
net => NULL;
cell => {
WriteEC: PROC [item: REF ANY] RETURNS [stop: BOOL] = {
ec: ExtraConnection ← NARROW[item];
stop ← FALSE;
to.PutF["\n\t(%g %g)",
IO.refAny[PickAName[ec.childNet.names]],
IO.refAny[PickAName[ec.parentNet.names]]];
};
e: Edge ← v.firstEdge;
nameFirst, nameRest: ROPE;
[nameFirst, nameRest] ← NameParts[v.names];
to.PutF["(CI %g %g%g", IO.rope[nameFirst], IO.refAny[PickAName[v.type.names]], IO.rope[nameRest]];
AssertingIO.WriteTail[to, v.other];
to.PutRope[" (CIC"];
FOR pi: NAT IN [0 .. v.type.ports.length) DO
IF e.sides[cell].v # v THEN ERROR;
IF e.portIndex # pi THEN ERROR;
to.PutF["\n\t(%g %g)", IO.refAny[PickAName[v.type.ports[pi].names]], IO.refAny[PickAName[e.sides[net].v.names]]];
e ← e.sides[cell].next;
ENDLOOP;
IF e # NIL THEN ERROR;
IF v.extraConnections # NIL THEN v.extraConnections.EnumerateIncreasing[WriteEC];
to.PutRope["))\n"];
};
ENDCASE => ERROR;
};
ct.parts.EnumerateIncreasing[PerPart];
};
WriteArray: PROC [to: IO.STREAM, ct: CellType] = {
a: Array ← ct.asArray;
to.PutF["(Array %g ((%g %g) (%g %g))",
IO.refAny[PickAName[a.eltType.names]],
IO.int[a.shape[Foo].min],
IO.int[a.shape[Foo].maxPlusOne-1],
IO.int[a.shape[Bar].min],
IO.int[a.shape[Bar].maxPlusOne-1]];
FOR dim: Dim IN Dim DO
FOR perp: EO IN EO DO
FOR para: EO IN EO DO
j: Joint ← a.joints[dim][perp][para];
IF j # NIL THEN {
to.PutF["\n\t(J %g %g %g (", IO.rope[DimName[dim]], IO.rope[EOName[perp]], IO.rope[EOName[para]]];
FOR lpi: PortIndex IN [0 .. a.eltType.ports.length) DO
hpi: PortIndex ← j[lpi].high;
IF hpi = NullPortIndex THEN LOOP;
IF j[hpi].low # lpi THEN ERROR;
to.PutF["\n\t\t(%g %g)",
IO.refAny[PickAName[a.eltType.ports[lpi].names]],
IO.refAny[PickAName[a.eltType.ports[hpi].names]]];
ENDLOOP;
to.PutRope["))"];
};
ENDLOOP;
ENDLOOP;
ENDLOOP;
FOR pi: PortIndex IN [0 .. a.eltType.ports.length) DO
p: Porting ← a.porting[pi];
SELECT p FROM
notPorted => NULL;
unknownPorting => ERROR;
ENDCASE => WITH p SELECT FROM
dp: DetailedPorting => {
to.PutF["\n\t(AP %g", IO.refAny[PickAName[a.eltType.ports[pi].names]]];
FOR f: End IN End DO FOR b: End IN End DO
IF dp.corners[f][b] # NullPortIndex THEN to.PutF["\n\t\t(C %g %g %g)", IO.rope[EndName[f]], IO.rope[EndName[b]], IO.refAny[PickAName[ct.ports[dp.corners[f][b]].names]]];
ENDLOOP ENDLOOP;
FOR e: End IN End DO FOR d: Dim IN Dim DO
od: Dim ← OtherDim[d];
inners: NATMAX[a.shape[od].maxPlusOne - a.shape[od].min, 2] - 2;
Say: PROC [pi: PortIndex] RETURNS [saying: ROPE] = {
saying ← IF pi = NullPortIndex THEN "NC" ELSE Convert.RopeFromRope[PickAName[ct.ports[pi].names]];
};
IF inners > 0 THEN {
to.PutF["\n\t\t(S %g %g", IO.rope[EndName[e]], IO.rope[DimName[d]]];
SELECT dp.sideIndices[e][d].same FROM
TRUE => to.PutF[" (S %g))", IO.rope[Say[dp.slots[dp.sideIndices[e][d].firstSlot]]]];
FALSE => {
to.PutRope[" (V"];
FOR i: NAT IN [0 .. inners) DO
to.PutChar[' ];
to.PutRope[Say[dp.slots[dp.sideIndices[e][d].firstSlot+i]]];
ENDLOOP;
to.PutRope["))"];
};
ENDCASE => ERROR;
};
ENDLOOP ENDLOOP;
to.PutRope[")"];
};
ENDCASE => ERROR;
ENDLOOP;
to.PutRope[")\n"];
};
NameStuff: PROC [names: Names] RETURNS [stuff: ROPE] = {
nameFirst, nameRest: ROPE;
[nameFirst, nameRest] ← NameParts[names];
stuff ← nameFirst.Concat[nameRest]};
NameParts: PROC [names: Names] RETURNS [nameFirst, nameRest: ROPE] = {
aliasing: BOOLFALSE;
Do: PROC [rl: RopeList, ns: ATOM] = {
FOR rl ← rl, rl.rest WHILE rl # NIL DO
SELECT TRUE FROM
nameFirst = NIL => {
nameFirst ← IO.PutFR["%g", IO.refAny[rl.first]];
IF ns # $U THEN nameRest ← IO.PutFR[" (G %g)", IO.atom[ns]];
};
nameFirst # NIL => {
IF NOT aliasing THEN {
nameRest ← nameRest.Cat[" (A"];
aliasing ← TRUE};
nameRest ← IO.PutFR["%g (%g", IO.rope[nameRest], IO.refAny[rl.first]];
IF ns # $U THEN nameRest ← IO.PutFR["%g (G %g)", IO.rope[nameRest], IO.atom[ns]];
nameRest ← nameRest.Cat[")"];
};
ENDCASE => ERROR;
ENDLOOP;
};
nameFirst ← nameRest ← NIL;
Do[names.designed, $D];
Do[names.unknown, $U];
Do[names.progged, $P];
IF nameFirst = NIL THEN ERROR;
IF aliasing THEN nameRest ← nameRest.Cat[")"];
};
NameParts: PROC [names: Names] RETURNS [nameFirst, nameRest: ROPE] = {
Do: PROC [rl: RopeList, ns: ATOM] = {
FOR rl ← rl, rl.rest WHILE rl # NIL DO
SELECT TRUE FROM
nameFirst = NIL => {
nameFirst ← IO.PutFR["%g", IO.refAny[rl.first]];
IF ns # $U THEN nameRest ← IO.PutFR[" (G %g)", IO.atom[ns]];
};
nameFirst # NIL => {
nameRest ← IO.PutFR["%g (A %g", IO.rope[nameRest], IO.refAny[rl.first]];
IF ns # $U THEN nameRest ← IO.PutFR["%g (G %g)", IO.rope[nameRest], IO.atom[ns]];
nameRest ← nameRest.Cat[")"];
};
ENDCASE => ERROR;
ENDLOOP;
};
nameFirst ← nameRest ← NIL;
Do[names.designed, $D];
Do[names.unknown, $U];
Do[names.progged, $P];
IF nameFirst = NIL THEN ERROR;
};
END.