LichenData2Impl.Mesa
Last tweaked by Mike Spreitzer on October 19, 1987 3:48:56 pm PDT
DIRECTORY AMBridge, Asserting, Basics, Convert, FS, GList, InterpreterOps, IntHashTable, IO, LichenArrayStuff, Collections, LichenDataOps, LichenDataStructure, IntFunctions, IntStuff, LichenNavigation, PairCollections, LichenPrinting, List, Rope, StructuredStreams, SymTab, TiogaAccess, UnparserBuffer, ViewerIO;
LichenData2Impl:
CEDAR
PROGRAM
IMPORTS AMBridge, Asserting, Convert, FS, InterpreterOps, IO, LichenArrayStuff, Collections, LichenDataOps, LichenDataStructure, IntFunctions, LichenNavigation, PairCollections, List, Rope, StructuredStreams, TiogaAccess, UnparserBuffer
EXPORTS LichenDataStructure, LichenPrinting
=
BEGIN OPEN LichenDataOps, LichenPrinting, LichenArrayStuff, LichenDataStructure, Colls:Collections, PairColls:PairCollections, Ints:IntStuff, IntFns:IntFunctions, SS:StructuredStreams, UB:UnparserBuffer;
DimName: ARRAY Dim OF ROPE = [Foo: "Foo", Bar: "Bar"];
step: ROPE = ".";
Describe:
PUBLIC
PROC [subject:
REF
ANY, relativeTo:
REF
ANY ←
NIL, nameGen: NameGenerator ←
NIL]
RETURNS [name:
ROPE] = {
name ← UnparseSteppyName[SteppyDescribe[subject, relativeTo, nameGen]];
RETURN};
SteppyDescribe:
PUBLIC
PROC [subject:
REF
ANY, relativeTo:
REF
ANY ←
NIL, nameGen: NameGenerator ←
NIL]
RETURNS [name: SteppyName] = {
GetShort:
PROC [oldAssns: Assertions]
RETURNS [newAssns: Assertions, name:
ROPE] = {
name ← NARROW[Asserting.FnVal[nameReln, newAssns ← oldAssns]];
IF name =
NIL
THEN {
name ← nameGen.GenerateName[nameGen.data, subject];
WITH subject
SELECT
FROM
v: Vertex => KnowVertexName[v, LIST[name]];
ENDCASE => newAssns ← Asserting.Assert1[nameReln, name, newAssns];
name ← name};
RETURN};
IF nameGen = NIL THEN nameGen ← defaultNameGen;
IF subject = relativeTo
THEN name ←
NIL
ELSE
WITH subject
SELECT
FROM
d: Design => {
short: ROPE;
[d.other, short] ← GetShort[d.other];
name ← LIST[short];
RETURN};
ct: CellType => {
short: ROPE;
[ct.otherPublic, short] ← GetShort[ct.otherPublic];
name ← LIST[short];
IF ct.designs.HasMember[relativeTo] OR ct.designs.Size[]=0 THEN NULL ELSE name ← List.Append[SteppyDescribe[GetADesign[ct], relativeTo, nameGen], name];
RETURN};
v: Vertex => {
parent: REF ANY;
IF v.VertexNames.Size[]=0 THEN KnowVertexName[v, name ← LIST[nameGen.GenerateName[nameGen.data, subject]]] ELSE name ← NARROW[v.VertexNames.First[].val];
WITH v
SELECT
FROM
ci: CellInstance => parent ← v.containingCT;
im: Intermediary => parent ← ImParent[im];
w: Wire => parent ← WireContainer[w];
ENDCASE => ERROR;
IF relativeTo#parent AND parent#NIL THEN name ← List.Append[SteppyDescribe[parent, relativeTo, nameGen], name];
RETURN};
port: Port => {
parent: REF ANY ~ port.parent;
IF port.PortNames.Size[]=0 THEN [] ← port.PortNames.AddElt[name ← LIST[nameGen.GenerateName[nameGen.data, subject]]] ELSE name ← NARROW[port.PortNames.First[].val];
IF relativeTo#parent AND parent#NIL THEN name ← List.Append[SteppyDescribe[parent, relativeTo, nameGen], name];
RETURN};
ENDCASE => ERROR;
};
GetADesign:
PROC [ct: CellType]
RETURNS [d: Design] = {
See: PROC [ra: REF ANY] = {d ← NARROW[ra]};
IF ct.designs.Size[] = 0 THEN RETURN [NIL];
ct.designs.Enumerate[See];
};
WireContainer:
PROC [w: Wire]
RETURNS [container:
REF
ANY] = {
container ←
SELECT w.containingWire
FROM
NIL => w.containingCT,
ENDCASE => w.containingWire;
};
defaultNameGen: NameGenerator =
NEW [NameGeneratorPrivate ← [
GenerateBlandName,
NEW [NameCountsPrivate ← []]
]];
NameCounts: TYPE = REF NameCountsPrivate;
NameCountsPrivate:
TYPE =
RECORD [
design, cellType, port, vertex: INT ← 0
];
GenerateBlandName:
PROC [data, subject:
REF
ANY]
RETURNS [name:
ROPE] = {
nc: NameCounts = NARROW[data];
name ← GenByCount[nc, subject];
};
TVNameGenerator: TYPE = REF TVNameGeneratorPrivate;
TVNameGeneratorPrivate:
TYPE =
RECORD [
nc: NameCounts,
symTab: SymTab.Ref
];
MakeTVNameGen:
PROC [symTab: SymTab.Ref]
RETURNS [ng: NameGenerator] = {
ng ←
NEW [NameGeneratorPrivate ← [
GenerateTVName,
NEW [TVNameGeneratorPrivate ← [
nc: NEW [NameCountsPrivate ← []],
symTab: symTab
]]
]];
};
GenerateTVName:
PROC [data, subject:
REF
ANY]
RETURNS [name:
ROPE] = {
tvng: TVNameGenerator = NARROW[data];
name ← Rope.Concat["&", GenByCount[tvng.nc, subject]];
TRUSTED {InterpreterOps.RegisterTV[
name: name,
tv: AMBridge.TVForReferent[
WITH subject
SELECT
FROM
d: Design => NEW [Design ← d],
ct: CellType => NEW [CellType ← ct],
p: Port => NEW [Port ← p],
v: Vertex => NEW [Vertex ← v],
ENDCASE => ERROR],
symbolsList: LIST[tvng.symTab]]};
};
GenByCount:
PROC [nc: NameCounts, subject:
REF
ANY]
RETURNS [name:
ROPE] = {
n: INT ← 0;
WITH subject
SELECT
FROM
d: Design => {n ← nc.design ← nc.design + 1; name ← "D#"};
ct: CellType => {n ← nc.cellType ← nc.cellType + 1; name ← "CT#"};
p: Port => {n ← nc.port ← nc.port + 1; name ← "P#"};
v: Vertex => {n ← nc.vertex ← nc.vertex + 1; name ← "V#"};
ENDCASE => ERROR;
name ← name.Concat[Convert.RopeFromInt[n]];
};
PrintObject:
PROC [to:
IO.
STREAM, united:
BOOL,
PrintIt:
PROC] = {
SS.Bp[to, IF united THEN united ELSE lookLeft, printStep];
SS.Begin[to];
PrintIt[!UNWIND => SS.End[to]];
SS.End[to];
};
printStep: INT ← 2;
printWidth: INT ← 69;
PrintDesignOnFile:
PUBLIC
PROC [design: Design, nameGen: NameGenerator ←
NIL, fileName:
ROPE ←
NIL, tioga:
BOOL ←
FALSE, pacify:
IO.
STREAM ←
NIL,
Filter: CellTypeFilter ←
NIL] = {
realFileName: ROPE = IF fileName # NIL THEN fileName ELSE Rope.Cat[Describe[design], ".design"];
ss, fs: IO.STREAM;
taw: TiogaAccess.Writer;
IF tioga
THEN {
taw ← TiogaAccess.Create[];
ss ← SS.Create[UB.NewInittedHandle[[output: [access[taw, printStep]], margin: printWidth]]];
}
ELSE {
fs ← FS.StreamOpen[fileName: realFileName, accessOptions: create, keep: 10];
ss ← SS.Create[UB.NewInittedHandle[[output: [stream[fs]], margin: printWidth]]];
};
PrintDesignSubset[ss, design, nameGen, pacify, Filter];
IF tioga THEN TiogaAccess.WriteFile[taw, realFileName] ELSE IO.Close[fs];
ss.Close[];
};
PrintDesign:
PUBLIC
PROC [to:
IO.
STREAM, design: Design, nameGen: NameGenerator ←
NIL, pacify:
IO.
STREAM ←
NIL] = {
PrintDesignSubset[to, design, nameGen, pacify, NIL];
};
PrintDesignSubset:
PUBLIC
PROC [to:
IO.
STREAM, design: Design, nameGen: NameGenerator ←
NIL, pacify:
IO.
STREAM ←
NIL,
Filter: CellTypeFilter ←
NIL] = {
n: NAT ← 0;
CTPrint:
PROC [ra:
REF
ANY] = {
ct: CellType = NARROW[ra];
Inner:
PROC = {
IF pacify#NIL THEN pacify.PutF["%g: %g ", [integer[n ← n+1]], [rope[Describe[ct, design, nameGen]]]];
PrintCellType[to, ct, nameGen];
IF pacify#NIL THEN pacify.PutRope[" .\n"];
};
IF Filter=NIL OR Filter[ct] THEN PrintObject[to, TRUE, Inner];
};
IF pacify#NIL AND Filter=NIL THEN pacify.PutF["Total: %g\n", [integer[design.cellTypes.Size]]];
IF NOT SS.IsAnSS[to] THEN to ← SS.Create[UB.NewInittedHandle[[output: [stream[to]], margin: printWidth]]];
to.PutF["%g: Design {", [rope[Describe[design, NIL, nameGen]]]];
design.cellTypes.Enumerate[CTPrint];
to.PutF["}"];
};
PrintNameAndAliases:
PROC [to:
IO.
STREAM, name:
ROPE, names: Set
--of SteppyName--] ~ {
first, second: BOOL ← TRUE;
PerName:
PROC [val:
REF
ANY] ~ {
name: SteppyName ~ NARROW[val];
IF first
THEN first ←
FALSE
ELSE {
IF second THEN second ← FALSE ELSE to.PutRope[","];
SS.Bp[to, width, printStep, " "];
to.PutRope[UnparseSteppyName[name]];
};
RETURN};
to.PutRope[name];
IF names.Size[2]>1
THEN {
to.PutRope["(a.k.a."];
names.Enumerate[PerName];
to.PutRope[")"];
};
RETURN};
PrintCellType:
PUBLIC
PROC [to:
IO.
STREAM, ct: CellType, nameGen: NameGenerator ←
NIL] = {
PortPrint:
PROC = {
to.PutF["port: "];
PrintPort[to, ct.port, nameGen];
};
IWPrint:
PROC = {
to.PutF["internal wire: "];
PrintWire[to, ct.asUnorganized.internalWire, nameGen];
};
CIPrint:
PROC = {
to.PutF["contained instances: "];
PrintInstances[to, ct.asUnorganized.containedInstances, ct.asUnorganized.mirror, nameGen];
};
AyPrint:
PROC = {
to.PutRope["asArray: "];
PrintArray[to, ct, nameGen]
};
IF NOT SS.IsAnSS[to] THEN to ← SS.Create[UB.NewInittedHandle[[output: [stream[to]], margin: printWidth]]];
to.PutRope[Describe[ct, GetADesign[ct], nameGen]];
to.PutRope[": CellType["];
PrintObject[to, TRUE, PortPrint];
IF ct.asUnorganized #
NIL
THEN {
to.PutRope[", "]; PrintObject[to, TRUE, IWPrint];
to.PutRope[", "]; PrintObject[to, TRUE, CIPrint];
};
IF ct.asArray #
NIL
THEN {
to.PutRope[", "]; PrintObject[to, TRUE, AyPrint];
};
to.PutRope["]"];
};
limitPort: BOOL ← TRUE;
portLimit: NAT ← 69;
MaybePrintSeq:
PROC [to:
IO.
STREAM, parent:
REF
ANY, toKids: Function
--parent
b Seq of child--, toName: Function
--child
b SteppyName--]
RETURNS [did:
BOOL] ~ {
kids: Seq--of child-- ~ IntFns.DeRef[toKids.Apply[parent].val];
bounds: Ints.Interval ~ kids.GetBounds[];
is: BOOL ← TRUE;
FOR i:
INT
IN [bounds.min .. bounds.max]
DO
child: REF ANY ~ kids.Apply[i].DVal;
IF child=NIL THEN EXIT;
{name: SteppyName ~ NARROW[toName.Apply[child].DVal];
IF name#
NIL
AND name.rest=
NIL
THEN
WITH name.first
SELECT
FROM
x:
REF
INT =>
IF x^ = i
THEN {
grandKids: Seq ~ IntFns.DeRef[toKids.Apply[child].val];
IF grandKids.Size[]=0 THEN LOOP;
};
x: ROPE => NULL;
ENDCASE => ERROR;
EXIT;
};
REPEAT
FINISHED => {
IF bounds.min=0
THEN to.PutF["*%g", [integer[bounds.max+1]]]
ELSE to.PutF["*%g..%g", [integer[bounds.min]], [integer[bounds.max]]];
RETURN [TRUE]};
ENDLOOP;
RETURN [FALSE]};
PrintPort:
PUBLIC
PROC [to:
IO.
STREAM, port: Port, nameGen: NameGenerator ←
NIL] = {
first: BOOL ← TRUE;
i: INT ← 0;
PrintNameAndAliases[to, Describe[port, port.parent, nameGen], port.PortNames];
IF port.FirstChildPort[] = NIL THEN RETURN;
IF MaybePrintSeq[to, port, LichenNavigation.portToChildren, LichenNavigation.bestPortShortName] THEN RETURN;
to.PutRope["["];
FOR subPort: Port ← port.FirstChildPort[], subPort.NextChildPort[]
WHILE subPort#
NIL
DO
PortPrint: PROC = {PrintPort[to, subPort, nameGen]};
PrintElipsis: PROC = {to.PutF["..%g.., ", [integer[i-portLimit]]]};
IF (
NOT limitPort)
OR i < portLimit
OR subPort.NextChildPort[] =
NIL
THEN {
IF first THEN first ← FALSE ELSE to.PutRope[", "];
IF limitPort AND i > portLimit THEN PrintObject[to, FALSE, PrintElipsis];
PrintObject[to, FALSE, PortPrint]
};
i ← i + 1;
ENDLOOP;
to.PutRope["]"];
};
PrintWire:
PUBLIC
PROC [to:
IO.
STREAM, wire: Wire, nameGen: NameGenerator ←
NIL] = {
first: BOOL ← TRUE;
PrintNameAndAliases[to, Describe[wire, WireContainer[wire], nameGen], wire.VertexNames];
IF wire.FirstChildWire[] = NIL THEN RETURN;
IF MaybePrintSeq[to, wire, LichenNavigation.wireToChildren, LichenNavigation.bestVertexShortName] THEN RETURN;
to.PutRope["["];
FOR subWire: Wire ← wire.FirstChildWire[], subWire.NextChildWire[]
WHILE subWire #
NIL
DO
WirePrint: PROC = {PrintWire[to, subWire, nameGen]};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, FALSE, WirePrint];
ENDLOOP;
to.PutRope["]"];
};
PrintInstances:
PUBLIC
PROC [to:
IO.
STREAM, set: Set
--OF CellInstance--, mirror: CellInstance, nameGen: NameGenerator ←
NIL] = {
first: BOOL ← TRUE;
PrintIt:
PROC [ra:
REF
ANY] = {
ci: CellInstance = NARROW[ra];
IPrint: PROC = {PrintInstance[to, ci, nameGen]};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, TRUE, IPrint];
};
to.PutRope["["];
set.Enumerate[PrintIt];
IF printMirror THEN PrintIt[mirror];
to.PutRope["]"];
};
printMirror: BOOL ← FALSE;
PrintInstance:
PUBLIC
PROC [to:
IO.
STREAM, ci: CellInstance, nameGen: NameGenerator ←
NIL] = {
PrintConnections:
PROC [v: Vertex] = {
first: BOOL ← TRUE;
PrintConnection:
PROC [port: Port, w: Vertex] = {
CPrint:
PROC = {
to.PutF["%g: ", [rope[Describe[port, port.parent, nameGen]]]];
WITH w
SELECT
FROM
im: Intermediary => {
subbing, first: BOOL ← TRUE;
min, max: INT;
parent: Wire;
TestConnection:
PROC [p: Port, u: Vertex] ~ {
ow: Wire ~
WITH u
SELECT
FROM
x: Wire => x,
x: Intermediary => NIL,
x: CellInstance => ERROR,
ENDCASE => ERROR;
IF ow=NIL THEN subbing ← FALSE;
IF NOT subbing THEN RETURN;
{pn: SteppyName ~ NARROW[p.PortNames.First.DVal];
IF pn#
NIL
AND pn.rest=
NIL
THEN
WITH pn.first
SELECT
FROM
x:
REF
INT => {
wn: SteppyName ~ NARROW[ow.VertexNames.First.DVal];
IF wn#
NIL
AND wn.rest=
NIL
THEN
WITH wn.first
SELECT
FROM
y:
REF
INT =>
IF x^ = y^
THEN {
IF first
THEN {
first ← FALSE;
parent ← ow.containingWire;
min ← max ← x^;
RETURN}
ELSE {
min ← MIN[min, x^];
max ← MAX[max, x^];
IF parent=ow.containingWire THEN RETURN};
};
y: ROPE => NULL;
ENDCASE => ERROR;
};
x: ROPE => NULL;
ENDCASE => ERROR;
subbing ← FALSE;
}};
EnumerateImmediateConnections[im, TestConnection, [cellward: FALSE, wireward: TRUE]];
IF subbing
THEN {
to.PutRope[Describe[parent, ci.containingCT.asUnorganized.internalWire, nameGen]];
to.PutF["[%g..%g]", [integer[min]], [integer[max]]];
}
ELSE PrintConnections[im];
};
wire: Wire => {
to.PutRope[Describe[wire, ci.containingCT.asUnorganized.internalWire, nameGen]];
};
ci: CellInstance => ERROR;
ENDCASE => ERROR;
};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, FALSE, CPrint];
};
to.PutRope["["];
EnumerateImmediateConnections[v, PrintConnection, [cellward: FALSE, wireward: TRUE]];
to.PutRope["]"];
};
PrintNameAndAliases[to, Describe[ci, ci.containingCT, nameGen], ci.VertexNames];
to.PutF[": %g", [rope[Describe[ci.type, GetADesign[ci.type], nameGen]]] ];
PrintConnections[ci];
};
Array: TYPE ~ LichenDataStructure.Array;
printStatRep: BOOL ← TRUE;
printDumbRep: BOOL ← FALSE;
PrintArray:
PUBLIC
PROC [to:
IO.
STREAM, ct: CellType, nameGen: NameGenerator ←
NIL] = {
a: Array = ct.asArray;
groupName: VarFunction = PairColls.CreateHashFn[];
nGroups: NAT ← 0;
BasePrint:
PROC = {
to.PutF["base period = [%g, %g]", [integer[a.basePeriod[Foo]]], [integer[a.basePeriod[Bar]]]]};
StatPrint:
PROC = {
to.PutRope["static graph = ["];
PrintStatRep[to, a, nameGen];
to.PutRope["]"];
};
to.PutF["{%g BY %g OF %g, ",
[integer[a.size2[Foo]]], [integer[a.size2[Bar]]],
[rope[Describe[a.eltType, GetADesign[ct], nameGen]]]
];
PrintObject[to, FALSE, BasePrint];
IF printStatRep
THEN {
to.PutRope[", "];
PrintObject[to, TRUE, StatPrint];
};
IF printDumbRep THEN ERROR nyet;
to.PutRope["}"];
};
PrintStatRep:
PROC [to:
IO.
STREAM, a: Array, nameGen: NameGenerator] ~ {
firstEdge: BOOL ← TRUE;
PrintEdge:
PROC [ra:
REF
ANY] ~ {
se: StatEdge ~ NARROW[ra];
EdgePrint:
PROC ~ {
Put:
PROC [b:
BOOL] ~ {
ep: Port ~ se.vs[b].port;
to.PutRope[Describe[ep, PortCCT[ep].port, nameGen]];
IF a.basePeriod#ALL[1] THEN to.PutF["@<%g,%g>", [integer[se.vs[b].phase[Foo]]], [integer[se.vs[b].phase[Bar]]]];
RETURN};
Put[FALSE];
to.PutRope[" -> "];
Put[TRUE];
to.PutRope[" by "];
to.PutRope[FmtInt2[a, se.d]];
RETURN};
IF firstEdge THEN firstEdge ← FALSE ELSE to.PutRope[", "];
PrintObject[to, TRUE, EdgePrint];
RETURN};
a.statrep.edges.Enumerate[PrintEdge];
RETURN};
FmtRange2:
PROC [a: Array, r: Range2]
RETURNS [asRope:
ROPE] = {
RETURN [
SELECT
TRUE
FROM
a.size2[Bar]=1 => FmtRange[r[Foo]],
a.size2[Foo]=1 => FmtRange[r[Bar]],
ENDCASE => FmtRange[r[Foo]].Cat[":", FmtRange[r[Bar]]]
]};
FmtRange:
PUBLIC
PROC [r: Range]
RETURNS [asRope:
ROPE] = {
asRope ← Convert.RopeFromInt[r.min];
IF r.min+1 # r.maxPlusOne THEN asRope ← asRope.Cat["~", Convert.RopeFromInt[r.maxPlusOne-1]];
};
FmtInt2:
PROC [a: Array, i2: Int2]
RETURNS [
ROPE] ~ {
RETURN [
SELECT
TRUE
FROM
a.size2[Bar]=1 => Convert.RopeFromInt[i2[Foo]],
a.size2[Foo]=1 => Convert.RopeFromInt[i2[Bar]],
ENDCASE => IO.PutFR["<%g, %g>", [integer[i2[Foo]]], [integer[i2[Bar]]]]
]};
IsArray: PROC [ct: CellType] RETURNS [pass: BOOL] = {pass ← ct.asArray # NIL};
Is1D:
PROC [ct: CellType]
RETURNS [
BOOL]
~ {RETURN [ct.asArray#NIL AND (ct.asArray.size2[Foo]=1 OR ct.asArray.size2[Bar]=1)]};
Is2D:
PROC [ct: CellType]
RETURNS [
BOOL]
~ {RETURN [ct.asArray#NIL AND ct.asArray.size2[Foo]#1 AND ct.asArray.size2[Bar]#1]};
PrintArrays:
PROC [to:
IO.
STREAM, design: Design, nameGen: NameGenerator ←
NIL, pacify:
IO.
STREAM ←
NIL] = {
PrintDesignSubset[to, design, nameGen, pacify, IsArray];
};
PrintIncompletes:
PROC [to:
IO.
STREAM, design: Design, nameGen: NameGenerator ←
NIL, pacify:
IO.
STREAM ←
NIL] = {
PrintDesignSubset[to, design, nameGen, pacify, IsIncompleteArray];
};
END.