LichenData2Impl.Mesa
Last tweaked by Mike Spreitzer on September 10, 1987 5:42:22 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, LichenDataStructure, LichenArrayStuff, Colls:Collections, PairColls:PairCollections, Ints:IntStuff, IntFns:IntFunctions, SS:StructuredStreams, UB:UnparserBuffer;
DimName: ARRAY Dim OF ROPE = [Foo: "Foo", Bar: "Bar"];
EndName: ARRAY End OF ROPE = [low: "low", high: "high"];
step: ROPE = ".";
Describe: PUBLIC PROC [subject: REF ANY, relativeTo: REF ANYNIL, nameGen: NameGenerator ← NIL] RETURNS [name: ROPE] = {
name ← UnparseSteppyName[SteppyDescribe[subject, relativeTo, nameGen]];
RETURN};
SteppyDescribe: PUBLIC PROC [subject: REF ANY, relativeTo: REF ANYNIL, 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: ROPENIL, tioga: BOOLFALSE, pacify: IO.STREAMNIL] = {
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[realFileName, create];
ss ← SS.Create[UB.NewInittedHandle[[output: [stream[fs]], margin: printWidth]]];
};
PrintDesign[ss, design, nameGen, pacify];
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.STREAMNIL] = {
Filter: PROC [CellType] RETURNS [BOOL] = {RETURN [TRUE]};
IF pacify#NIL THEN pacify.PutF["Total: %g\n", [integer[design.cellTypes.Size]]];
PrintDesignSubset[to, design, nameGen, Filter, pacify];
};
PrintDesignSubset: PUBLIC PROC [to: IO.STREAM, design: Design, nameGen: NameGenerator, Filter: PROC [CellType] RETURNS [BOOL], pacify: IO.STREAMNIL] = {
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[ct] THEN PrintObject[to, TRUE, Inner];
};
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: BOOLTRUE;
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: BOOLTRUE;
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: BOOLTRUE;
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: BOOLTRUE;
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: BOOLTRUE;
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: BOOLTRUE;
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: BOOLFALSE;
PrintInstance: PUBLIC PROC [to: IO.STREAM, ci: CellInstance, nameGen: NameGenerator ← NIL] = {
PrintConnections: PROC [v: Vertex] = {
first: BOOLTRUE;
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: BOOLTRUE;
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];
};
PrintArray: PUBLIC PROC [to: IO.STREAM, ct: CellType, nameGen: NameGenerator ← NIL] = {
a: Array = ct.asArray;
groupName: VarFunction = PairColls.CreateHashFn[];
nGroups: NAT ← 0;
JPPrint: PROC = {
to.PutF["joints period = [%g, %g]", [integer[a.jointsPeriod[Foo]]], [integer[a.jointsPeriod[Bar]]]]};
GMPrint: PROC = {
to.PutF["groupingMiddles = [%g, %g]", [rope[FmtGP[a.groupingParmses[Foo]]]], [rope[FmtGP[a.groupingParmses[Bar]]]]];
};
AWPrint: PROC = {
to.PutRope["wires = ["];
PrintArrayWires[to, a, groupName, nameGen];
to.PutRope["]"];
};
to.PutF["{%g BY %g OF %g, ",
[integer[a.size[Foo]]], [integer[a.size[Bar]]],
[rope[Describe[a.eltType, GetADesign[ct], nameGen]]]
];
PrintObject[to, FALSE, JPPrint];
to.PutRope[", "];
PrintObject[to, FALSE, GMPrint];
FOR gif: NAT IN [0 .. a.groupingParmses[Foo].sum) DO FOR gib: NAT IN [0 .. a.groupingParmses[Bar].sum) DO
gi: NAT = a.groupingParmses[Bar].sum * gif + gib;
gs: Groupings = NARROW[a.groupingses[gi]];
PrintGroups: PROC = {
first: BOOLTRUE;
PrintGroup: PROC [ra: REF ANY] = {
g: Group = NARROW[ra];
name: ROPE = IO.PutFR["G%g", [integer[nGroups ← nGroups+1]]];
GPrint: PROC = {
to.PutF["%g: ", [rope[name]]];
PrintGroupContents[to, a, g, nameGen];
};
IF NOT groupName.Store[[g, name]].new THEN ERROR;
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, FALSE, GPrint];
};
to.PutF["groups[%g, %g] = [", [integer[gif]], [integer[gib]]];
gs.groups.Enumerate[PrintGroup];
to.PutRope["]"];
};
to.PutRope[", "];
PrintObject[to, TRUE, PrintGroups];
ENDLOOP ENDLOOP;
FOR d: Dim IN Dim DO
PrintJoints: PROC = {
first: BOOLTRUE;
to.PutF["joints[%g] = [", [rope[DimName[d]]]];
FOR ff: NAT IN [0 .. a.jointsPeriod[Foo]) DO
FOR fb: NAT IN [0 .. a.jointsPeriod[Bar]) DO
phase: Nat2 = [ff, fb];
JPrint: PROC = {
to.PutF["[%g,%g]: ", [integer[ff]], [integer[fb]]];
PrintJoint[to, ct, d, phase, GetArrayJoint[a, d, phase], nameGen, groupName];
};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, TRUE, JPrint];
ENDLOOP;
ENDLOOP;
to.PutRope["]"];
};
to.PutRope[", "];
PrintObject[to, TRUE, PrintJoints];
ENDLOOP;
to.PutRope[", "];
PrintObject[to, TRUE, AWPrint];
to.PutRope["}"];
};
PrintArrayWires: PROC [to: IO.STREAM, a: Array, groupName: VarFunction, nameGen: NameGenerator] ~ {
first: BOOLTRUE;
dull: ARRAY Dim OF BOOL ~ [a.size[Foo]=1, a.size[Bar]=1];
twod: BOOL ~ dull=ALL[FALSE];
PrintPerAW: PROC [ra: REF ANY] ~ {
aw: ArrayWire ~ NARROW[ra];
AWPrint: PROC ~ {
first: BOOLTRUE;
size1: BOOL ~ aw.members.Size[2]=1;
PerGroup: PROC [pair: PairColls.Pair] ~ {
g: Group ~ NARROW[pair[left]];
bs: BoolSeq ~ NARROW[pair[right]];
air: Range2 ~ Gi2ToAir[a, g.gi2].air;
shape: Nat2 ~ RangeShape[air];
EltPrint: PROC ~ {
firstRow: BOOLTRUE;
f0: NAT ← air[Foo].min;
f1, fi0, fi1: NAT ← 0;
to.PutRope[NARROW[groupName.Apply[g].val]];
to.PutRope["["];
WHILE f0 < air[Foo].maxPlusOne DO
base: NAT ~ shape[Bar] * fi0;
RowSame: PROC [fi1: NAT] RETURNS [BOOL] ~ {
base1: NAT ~ shape[Bar] * fi1;
b: NAT ← air[Bar].min;
bi: NAT ← 0;
WHILE b < air[Bar].maxPlusOne DO
IF bs[base+bi] # bs[base1+bi] THEN RETURN [FALSE];
b ← b+a.jointsPeriod[Bar];
bi ← bi + 1;
ENDLOOP;
RETURN [TRUE]};
firstCol: BOOLTRUE;
b0: NAT ← air[Bar].min;
b1, bi0, bi1: NAT ← 0;
f1 ← f0 + a.jointsPeriod[Foo];
fi1 ← fi0 + 1;
UNTIL f1 >= air[Foo].maxPlusOne OR NOT RowSame[fi1] DO
f1 ← f1+a.jointsPeriod[Foo];
fi1 ← fi1 + 1;
ENDLOOP;
WHILE b0 < air[Bar].maxPlusOne DO
bit0: BOOL ~ bs[base + bi0];
b1 ← b0+a.jointsPeriod[Bar];
bi1 ← bi0 + 1;
UNTIL b1 >= air[Bar].maxPlusOne OR bs[base+bi1] # bit0 DO
b1 ← b1 + a.jointsPeriod[Bar];
bi1 ← bi1 + 1;
ENDLOOP;
IF bit0 THEN {
IF firstCol THEN {
IF firstRow THEN firstRow ← FALSE ELSE to.PutRope[", "];
SS.Bp[to, lookLeft, printStep];
SS.Begin[to];
firstCol ← FALSE;
SELECT dull FROM
[FALSE, FALSE] => to.PutF["{%g: ", [rope[FmtRange[[f0, f1]]]]];
[FALSE, TRUE] => to.PutRope[FmtRange[[f0, f1]]];
[TRUE, FALSE] => NULL;
[TRUE, TRUE] => to.PutRope["X"];
ENDCASE => ERROR;
}
ELSE to.PutRope[", "];
IF twod THEN SS.Bp[to, lookLeft, printStep];
IF NOT dull[Bar] THEN to.PutRope[FmtRange[[b0, b1]]];
};
b0 ← b1;
bi0 ← bi1;
ENDLOOP;
IF NOT firstCol THEN {
IF twod THEN to.PutRope["}"];
SS.End[to];
};
f0 ← f1;
fi0 ← fi1;
ENDLOOP;
to.PutRope["]"];
};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, FALSE, EltPrint];
};
IF NOT size1 THEN to.PutRope["{"];
aw.members.Enumerate[PerGroup];
IF NOT size1 THEN to.PutRope["}"];
};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, FALSE, AWPrint];
};
a.wires.Enumerate[PrintPerAW];
};
PrintGroupContents: PROC [to: IO.STREAM, a: Array, g: Group, nameGen: NameGenerator] = {
first: BOOLTRUE;
to.PutRope["{"];
FOR pl: PortList ← g.ports, pl.rest WHILE pl # NIL DO
p: Port = pl.first;
name: ROPE = Describe[p, a.eltType.port, nameGen];
IF first THEN first ← FALSE ELSE to.PutRope[", "];
SS.Bp[to, lookLeft, printStep];
to.PutRope[name];
ENDLOOP;
to.PutRope["}"];
};
PrintJoint: PROC [to: IO.STREAM, act: CellType, d: Dim, phase: Nat2, j: Joint, nameGen: NameGenerator, groupName: VarFunction] = {
GPFPrint: PROC = {
to.PutF["grouping middles = [%g, %g]", [rope[FmtGP[j.groupingParmses[Foo]]]], [rope[FmtGP[j.groupingParmses[Bar]]]]]};
to.PutRope["{"];
PrintObject[to, FALSE, GPFPrint];
FOR jgif: NAT IN [0 .. j.groupingParmses[Foo].sum) DO FOR jgib: NAT IN [0 .. j.groupingParmses[Bar].sum) DO
jgi2: Nat2 = [jgif, jgib];
jgi: NAT = j.groupingParmses[Bar].sum * jgif + jgib;
ties: Set = Colls.DeRef[j.ties[jgi]];
GIPrint: PROC = {
first: BOOLTRUE;
PerTie: PROC [ra: REF ANY] = {
tie: Tie = NARROW[ra];
TPrint: PROC = {PrintTie[to, act, d, phase, j, jgi2, tie, nameGen, groupName]};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, FALSE, TPrint];
};
to.PutF["@[%g, %g] {", [integer[jgif]], [integer[jgib]]];
[] ← ties.Enumerate[PerTie];
to.PutRope["}"];
};
to.PutRope[", "];
PrintObject[to, TRUE, GIPrint];
ENDLOOP ENDLOOP;
to.PutRope["}"];
};
printIncompleteness: BOOLTRUE;
PrintTie: PROC [to: IO.STREAM, act: CellType, d: Dim, phase: Nat2, j: Joint, jgi2: Nat2, tie: Tie, nameGen: NameGenerator, groupName: VarFunction] = {
Bitch: PROC = {
CPrint: PROC = {
to.PutRope[" "];
PrintCliques[to, act, d, phase, j, jgi2, tie, nameGen];
};
to.PutF["(%g/%g incomplete", [integer[tie.completion.nIncomplete]], [integer[tie.completion.length]]];
IF printIncompleteness THEN CPrint[];
to.PutRope[")"];
};
FmtGrp: PROC [g: Group] RETURNS [name: ROPE] = {
IF g = NIL THEN RETURN ["?nil?"];
name ← NARROW[groupName.Apply[g].DVal[noName]];
};
to.PutF["%g—%g", [rope[FmtGrp[tie.groups[low]]]], [rope[FmtGrp[tie.groups[high]]]]];
IF tie.completion # NIL THEN Bitch[];
};
noName: ROPE ~ "??";
FmtGP: PROC [gp: GroupingParms] RETURNS [asRope: ROPE] = {
asRope ← IO.PutFR["[%g..%g]", [integer[gp.middle.min]], [integer[gp.middle.maxPlusOne-1]]]};
PrintCliques: PROC [to: IO.STREAM, act: CellType, d: Dim, phase: Nat2, j: Joint, jgi2: Nat2, tie: Tie, nameGen: NameGenerator] = {
a: Array = act.asArray;
jSize: Nat2 = Nat2Tweak[a.size, d, -1];
jiir: Range2 = Jgi2ToLair[a, phase, j, jgi2].jiir;
jif0, jif1: NAT ← 0;
RowSame: PROC [f0, f1: NAT] RETURNS [same: BOOL] = {
clai00f: NAT = jSize[Bar] * f0;
clai00b: NAT = jiir[Bar].min * a.jointsPeriod[Bar] + phase[Bar];
FOR side: End IN End DO
g: Group = tie.groups[side];
IF g # NIL THEN {
FOR ports: PortList ← g.ports, ports.rest WHILE ports # NIL DO
port: Port = ports.first;
rpd: SidedPortData = FetchRPD[a, d, [side, port]];
clai0: NAT ← clai00f + clai00b;
clai1: NAT ← jSize[Bar] * f1 + clai00b;
IF rpd = NIL THEN ERROR;
FOR jib: INT IN [jiir[Bar].min .. jiir[Bar].maxPlusOne) DO
IF GetRoot[a, d, rpd, clai0] # GetRoot[a, d, rpd, clai1] THEN RETURN [FALSE];
clai0 ← clai0 + a.jointsPeriod[Bar];
clai1 ← clai1 + a.jointsPeriod[Bar];
ENDLOOP;
ENDLOOP;
};
ENDLOOP;
same ← TRUE;
};
to.PutRope["["];
FOR jif0 ← jiir[Foo].min, jif1 WHILE jif0 < jiir[Foo].maxPlusOne DO
f0: NAT = jif0 * a.jointsPeriod[Foo] + phase[Foo];
f1: NAT ← f0 + a.jointsPeriod[Foo];
RPrint: PROC = {
to.PutRope[FmtRange[[jif0, jif1]]];
to.PutRope[": "];
PrintRowCliques[to, act, d, phase, j, jiir, tie, f0, nameGen];
};
FOR jif1 ← jif0+1, jif1+1 UNTIL jif1 = jiir[Foo].maxPlusOne OR NOT RowSame[f0, f1] DO
f1 ← f1 + a.jointsPeriod[Foo];
ENDLOOP;
IF jif0 > jiir[Foo].min THEN to.PutRope[", "];
PrintObject[to, FALSE, RPrint];
ENDLOOP;
to.PutRope["]"];
};
PrintRowCliques: PROC [to: IO.STREAM, act: CellType, d: Dim, phase: Nat2, j: Joint, jiir: Range2, tie: Tie, f: NAT, nameGen: NameGenerator] = {
a: Array = act.asArray;
jSize: Nat2 = Nat2Tweak[a.size, d, -1];
claiBase: NAT = jSize[Bar] * f;
ColSame: PROC [b0, b1: NAT] RETURNS [same: BOOL] = {
FOR side: End IN End DO
g: Group = tie.groups[side];
IF g # NIL THEN {
FOR ports: PortList ← g.ports, ports.rest WHILE ports # NIL DO
port: Port = ports.first;
rpd: SidedPortData = FetchRPD[a, d, [side, port]];
IF GetRoot[a, d, rpd, claiBase+b0] # GetRoot[a, d, rpd, claiBase+b1] THEN RETURN [FALSE];
ENDLOOP;
};
ENDLOOP;
same ← TRUE;
};
jib0, jib1: NAT ← 0;
to.PutRope["("];
FOR jib0 ← jiir[Bar].min, jib1 WHILE jib0 < jiir[Bar].maxPlusOne DO
b0: NAT = jib0 * a.jointsPeriod[Bar] + phase[Bar];
b1: NAT ← b0 + a.jointsPeriod[Bar];
CPrint: PROC = {
to.PutRope[FmtRange[[jib0, jib1]]];
to.PutRope[": "];
PrintColCliques[to, act, d, j, tie, [f, b0], nameGen];
};
FOR jib1 ← jib0+1, jib1+1 UNTIL jib1 = jiir[Bar].maxPlusOne OR NOT ColSame[b0, b1] DO
b1 ← b1 + a.jointsPeriod[Foo];
ENDLOOP;
IF jib0 > jiir[Bar].min THEN to.PutRope[", "];
PrintObject[to, FALSE, CPrint];
ENDLOOP;
to.PutRope[")"];
};
cliques: RefTable--root rpd b member rpd list-- = CreateRefTable[];
PrintColCliques: PROC [to: IO.STREAM, act: CellType, d: Dim, j: Joint, tie: Tie, lai: Nat2, nameGen: NameGenerator] = {
a: Array = act.asArray;
jSize: Nat2 = Nat2Tweak[a.size, d, -1];
clai: NAT = jSize[Bar] * lai[Foo] + lai[Bar];
to.PutRope["{"];
cliques.Erase[];
FOR side: End IN End DO
g: Group = tie.groups[side];
IF g # NIL THEN {
FOR ports: PortList ← g.ports, ports.rest WHILE ports # NIL DO
port: Port = ports.first;
rpd: SidedPortData = FetchRPD[a, d, [side, port]];
rootIndex: NAT = GetRoot[a, d, rpd, clai];
root: SidedPortData = NARROW[a.roles[d].refs[rootIndex]];
members: SidedPortDataList ← NARROW[cliques.Fetch[root].val];
members ← CONS[rpd, members];
[] ← cliques.Store[root, members];
ENDLOOP;
};
ENDLOOP;
{first: BOOLTRUE;
PrintClique: PROC [key, val: REF ANY] RETURNS [quit: BOOLFALSE] --RefTab.EachPairAction-- = {
members: SidedPortDataList = NARROW[val];
CPrint: PROC = {
first: BOOLTRUE;
to.PutRope["("];
FOR rpds: SidedPortDataList ← members, rpds.rest WHILE rpds # NIL DO
rpd: SidedPortData = rpds.first;
IF first THEN first ← FALSE ELSE to.PutRope[", "];
SS.Bp[to, width, printStep];
to.PutRope[FmtRPD[a, rpd, nameGen]];
ENDLOOP;
to.PutRope[")"];
};
IF first THEN first ← FALSE ELSE to.PutRope[", "];
PrintObject[to, FALSE, CPrint];
};
[] ← cliques.Pairs[PrintClique];
to.PutRope["}"];
}};
FmtRPD: PROC [a: Array, rpd: SidedPortData, nameGen: NameGenerator] RETURNS [asRope: ROPE] = {
asRope ← EndName[rpd.side].Cat["/", Describe[rpd.port, a.eltType.port, nameGen]];
};
FmtRange: 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]];
};
PrintArrays: PROC [to: IO.STREAM, design: Design, nameGen: NameGenerator ← NIL, pacify: IO.STREAMNIL] = {
Filter: PROC [ct: CellType] RETURNS [pass: BOOL] = {
pass ← ct.asArray # NIL;
};
PrintDesignSubset[to, design, nameGen, Filter, pacify];
};
PrintIncompletes: PROC [to: IO.STREAM, design: Design, nameGen: NameGenerator ← NIL, pacify: IO.STREAMNIL] = {
PrintDesignSubset[to, design, nameGen, IsIncompleteArray, pacify];
};
END.