LichenCounting.Mesa
Last tweaked by Mike Spreitzer on May 12, 1989 1:37:43 pm PDT
DIRECTORY AbSets, BiRels, FS, Histograms, HistogramsViewing, HistogramsViewingExtras, IntStuff, IO, LichenDataOps, LichenDataStructure, LichenIntBasics, Process, Real, RealFns, Rope, SetBasics;
LichenCounting: CEDAR PROGRAM
IMPORTS AbSets, BiRels, FS, Histograms, HistogramsViewing, HistogramsViewingExtras, IntStuff, IO, LichenDataStructure, Process, Real, RealFns, Rope, SetBasics
=
BEGIN OPEN IS:IntStuff, LichenIntBasics, LichenDataOps, LichenDataStructure, Sets:AbSets;
Histogram: TYPE ~ Histograms.Histogram;
Viewer: TYPE ~ HistogramsViewing.Viewer;
base2: REAL ← RealFns.Power[base: 2.0, exponent: 0.25];
offset2: REAL ← RealFns.Power[base: base2, exponent: Real.Round[RealFns.Log[base: base2, arg: 0.1]]];
Status: TYPE ~ RECORD [i, n: INT ← 0, prefix, path, type: ROPENIL];
status: REF Status ← NEW [Status ← []];
Hists: TYPE ~ RECORD [sizeCorr, combSize, wireSize, instSize: HV];
HV: TYPE ~ RECORD [h: Histogram, v: Viewer];
CountDesign: PROC [d: Design, histPrefix: ROPE, root: CellType ← NIL, fakeAtoms: Set--of CellType-- ← nilSet] RETURNS [cmpCellTypeSet, atmCellTypeSet: Set, cmpCellTypes, atmCellTypes, cellInstances, totWires, pubAtmWires, pvtAtmWires, pubCmpWires, pvtCmpWires, exblCmpWires, stuckWires, arrayFudge, atmPorts, cmpPorts, tNames, iNames, wNames, pNames: INT ← 0] ~ {
counted: Set ~ Sets.CreateHashSet[d.eSpace];
unorgUse: BiRel--parent CT child CT-- ~ d.cct[i].Invert.Compose[d.ciType, ALL[TRUE]];
CountCellType: PROC [ctv: Sets.Value] RETURNS [BOOL] ~ {
IF NOT counted.AddElt[ctv] THEN RETURN [FALSE];
Process.CheckForAbort[];
{ct: CellType ~ NARROW[ctv.VA];
cmp: BOOL ~ (ct.asu#NIL OR ct.asArray#NIL) AND NOT fakeAtoms.HasMemA[ct];
ports: Set ~ ct.CTParts[p];
oldInsts: INT ~ cellInstances;
oldWires: INT ~ totWires;
status.type ← d.Describe[ct, d];
IF NOT Sets.AddA[IF cmp THEN cmpCellTypeSet ELSE atmCellTypeSet, ct] THEN ERROR;
pNames ← pNames + ct.fullName[p].Size.EN;
IF cmp THEN {
IF unorgUse.ScanMapping[ctv, CountCellType].found THEN ERROR;
IF d.arrayElt.ScanMapping[ctv, CountCellType].found THEN ERROR;
};
IF NOT cmp THEN d ← d
ELSE IF ct.asu#NIL THEN {
wires: Set ~ ct.CTParts[w];
atmWires: Set ~ wires.Intersection[d.isAtomic];
cmpWires: Set ~ wires.Intersection[d.isComposite];
nonPubs: Set ~ ct.asu.notPublics;
pvts: Set ~ wires.Difference[d.ancest.Image[ct.asu.publics]].CreateHashCopy;
exCands: Set ~ nonPubs.Difference[pvts].CreateHashCopy;
pvtAtms: Set ~ nonPubs.Intersection[d.isAtomic];
pvtCmps: Set ~ pvts.Difference[atmWires];
troubled: Set ~ ct.asu.troubled.CreateHashCopy;
cellInstances ← cellInstances + ct.CTParts[i].Size.EN;
pubAtmWires ← pubAtmWires + atmWires.Intersection[ct.asu.publics].Size.EN;
pvtAtmWires ← pvtAtmWires + atmWires.Intersection[pvts].Size.EN;
pubCmpWires ← pubCmpWires + cmpWires.Intersection[ct.asu.publics].Size.EN;
pvtCmpWires ← pvtCmpWires + pvtCmps.Size.EN;
exblCmpWires ← exblCmpWires + exCands.Difference[troubled].Size.EN;
stuckWires ← stuckWires + exCands.Intersection[troubled].Size.EN;
totWires ← totWires + wires.Size.EN;
IF totWires # pubAtmWires + pvtAtmWires + pubCmpWires + pvtCmpWires + exblCmpWires + stuckWires THEN ERROR;
iNames ← iNames + ct.fullName[i].Size.EN;
wNames ← wNames + ct.fullName[w].Size.EN;
}
ELSE IF ct.asArray#NIL THEN {
a: Array ~ ct.asArray;
ect: CellType ~ ct.EltType[];
epa: Set ~ ect.CTParts[p].Intersection[d.isAtomic];
dr: DumRep ~ a.dumrep;
cmpWires: Set ~ dr.dwParent.Image[dr.wires].CreateHashCopy;
pubWires: Set ~ dr.apToWire.SetOn[right];
someAtmWires: Set ~ dr.wires.Difference[cmpWires].CreateHashCopy;
somePvtAtmWires: Set ~ someAtmWires.Difference[pubWires];
pvtParents: Set ~ dr.dwParent.Image[somePvtAtmWires].CreateHashCopy;
pubParents: Set ~ dr.dwParent.Image[pubWires].CreateHashCopy;
fudge: INT ~ SumFudge[ct, a];
IF dr.dwParent.ImageSize[cmpWires, leftToRight, IS.one]#IS.zero THEN ERROR;
IF pubParents.Difference[pubWires].NonEmpty THEN ERROR nyet--need to decide whether exportable or stuck--;
cellInstances ← cellInstances + a.size;
pubAtmWires ← pubAtmWires + someAtmWires.Intersection[pubWires].Size.EN;
pvtAtmWires ← pvtAtmWires + somePvtAtmWires.Size.EN + fudge;
pubCmpWires ← pubCmpWires + pubParents.Size.EN;
pvtCmpWires ← pvtCmpWires + pvtParents.Size.EN;
totWires ← totWires + dr.wires.Size.EN + fudge;
arrayFudge ← arrayFudge + fudge;
IF totWires # pubAtmWires + pvtAtmWires + pubCmpWires + pvtCmpWires + exblCmpWires + stuckWires THEN ERROR;
}
ELSE ERROR;
atmPorts ← atmPorts + ports.Intersection[d.isAtomic].Size[].EN;
cmpPorts ← cmpPorts + ports.Intersection[d.isComposite].Size.EN;
status.i ← status.i + 1;
IF cmp THEN {
di: INT ~ MAX[cellInstances - oldInsts, 1];
dw: INT ~ MAX[totWires - oldWires, 1];
hists.sizeCorr.h.ChangeTransformed[di, dw];
hists.combSize.h.ChangeTransformed[di+dw];
hists.wireSize.h.ChangeTransformed[dw];
hists.instSize.h.ChangeTransformed[di];
d ← d};
RETURN [FALSE]}};
hists: Hists;
tNames ← d.ctName.Size.EN;
status^ ← [n: d.cellTypes.Size.EN];
IF fakeAtoms=nilSet THEN fakeAtoms ← Sets.CreateEmptySet[d.eSpace];
hists.sizeCorr.h ← Histograms.Create2D[iFactor: base2, jFactor: base2, iOffset: offset2, jOffset: offset2, logI: TRUE, logJ: TRUE];
hists.combSize.h ← Histograms.Create1D[factor: 5];
hists.wireSize.h ← Histograms.Create1D[factor: 5];
hists.instSize.h ← Histograms.Create1D[factor: 5];
hists.sizeCorr.v ← HistogramsViewing.Show[h: hists.sizeCorr.h, viewerInit: [name: Rope.Cat[histPrefix, "sizeCorr"]], base: 2.0, updatePeriod: 15];
hists.combSize.v ← HistogramsViewing.Show[h: hists.combSize.h, viewerInit: [name: Rope.Cat[histPrefix, "combSize"]], base: 2.0, updatePeriod: 15];
hists.wireSize.v ← HistogramsViewing.Show[h: hists.wireSize.h, viewerInit: [name: Rope.Cat[histPrefix, "wireSize"]], base: 2.0, updatePeriod: 15];
hists.instSize.v ← HistogramsViewing.Show[h: hists.instSize.h, viewerInit: [name: Rope.Cat[histPrefix, "instSize"]], base: 2.0, updatePeriod: 15];
cmpCellTypeSet ← Sets.CreateHashSet[d.eSpace];
atmCellTypeSet ← Sets.CreateHashSet[d.eSpace];
IF CountCellType[AV[IF root=NIL THEN d.root ELSE root]] THEN ERROR;
cmpCellTypes ← cmpCellTypeSet.Size.EN;
atmCellTypes ← atmCellTypeSet.Size.EN;
WriteHV[hists.sizeCorr]; WriteHV[hists.combSize];
WriteHV[hists.wireSize]; WriteHV[hists.instSize];
RETURN};
WriteHV: PROC [hv: HV] ~ {
IF NOT hv.v.destroyed THEN HistogramsViewingExtras.ViewerWriteToFile[hv.v, hv.v.name.Cat[".hist"]];
RETURN};
anonymous: Sets.Value ~ SnV[OSn[R["?"]]];
FlatCount: PROC [d: Design, start: CellType ← NIL] RETURNS [cmpCellTypes, atmCellTypes, cellInstances, atmWires, cmpWires: INT ← 0] ~ {
cmpCts: Set ~ Sets.CreateHashSet[d.eSpace];
atmCts: Set ~ Sets.CreateHashSet[d.eSpace];
Work: PROC [ct: CellType, n: NATURAL, root: BOOL, path: ROPE] ~ {
p1: ROPE ~ IF path#NIL THEN path.Concat["/"] ELSE "";
Process.CheckForAbort[];
status.path ← path;
status.type ← d.Describe[ct, d];
status.i ← status.i + 1;
IF ct.asu#NIL THEN {
subcells: Set ~ ct.CTParts[i];
defWires: Set ~ ct.CTParts[w];
intros: Set ~ IF NOT root THEN defWires.Difference[d.ancest.Image[ct.asu.publics]].CreateHashCopy ELSE defWires;
PerSub: PROC [civ: Sets.Value] RETURNS [BOOL] ~ {
ci: CellInstance ~ NARROW[civ.VA];
ict: CellType ~ d.CiT[ci];
IF ict.asu#NIL OR ict.asArray#NIL THEN {
step: ROPE ~ UnparseSteppyName[VSn[ct.fullName[i].Lookup[goal: civ, side: left].DVal[anonymous]]];
Work[ict, n, FALSE, p1.Concat[step]];
}
ELSE {cellInstances ← cellInstances + n; [] ← atmCts.AddA[ict]};
RETURN [FALSE]};
[] ← cmpCts.AddA[ct];
IF subcells.Scan[PerSub].found THEN ERROR;
atmWires ← atmWires + n*intros.Intersection[d.isAtomic].Size.EN;
cmpWires ← cmpWires + n*intros.Intersection[d.isComposite].Size.EN}
ELSE IF ct.asArray#NIL THEN {
a: Array ~ ct.asArray;
subn: NATURAL ~ INT[n]*a.size;
ect: CellType ~ ct.EltType;
dr: DumRep ~ a.dumrep;
pubWires: Set ~ dr.apToWire.SetOn[right];
compWires: Set ~ dr.dwParent.Image[dr.wires].CreateHashCopy;
someAtmWires: Set ~ dr.wires.Difference[compWires].CreateHashCopy;
pubParents: Set ~ dr.dwParent.Image[pubWires].CreateHashCopy;
fudge: INT ~ SumFudge[ct, a];
IF NOT root THEN {
[] ← someAtmWires.RemSet[pubWires];
[] ← compWires.RemSet[pubWires]};
IF pubParents.Difference[pubWires].NonEmpty THEN ERROR nyet--need to decide whether exportable or stuck--;
atmWires ← atmWires + n*(someAtmWires.Size.EN + fudge);
cmpWires ← cmpWires + n*compWires.Size.EN;
IF ect.asu#NIL OR ect.asArray#NIL THEN Work[ect, subn, FALSE, p1.Concat["0"]]
ELSE {cellInstances ← cellInstances + subn; [] ← atmCts.AddA[ect]};
ct ← ct}
ELSE ERROR;
n ← n};
IF start=NIL THEN start ← d.root;
IF NOT d.cellTypes.HasMemA[start] THEN ERROR;
status.i ← 0;
IF start.asu=NIL AND start.asArray=NIL THEN {
wires: Set ~ start.CTParts[p];
pa: Set ~ wires.Intersection[d.isAtomic];
pc: Set ~ wires.Intersection[d.isComposite];
RETURN [0, 1, 1, pa.Size.EN, pc.Size.EN]};
Work[start, 1, TRUE, NIL];
cmpCellTypes ← cmpCts.Size.EN;
atmCellTypes ← atmCts.Size.EN;
RETURN};
SumFudge: PROC [ct: CellType, a: Array] RETURNS [INT] ~ {
dr: DumRep ~ a.dumrep;
ect: CellType ~ ct.EltType[];
epsa: Set ~ ect.CTParts[p].Intersection[ct.d.isAtomic];
ecTot: INT ~ epsa.Size.EN * a.size;
ecSum: INT ← 0;
PerDW: PROC [dwv: Sets.Value] RETURNS [BOOL] ~ {
dw: DumbWire ~ NARROW[dwv.VA];
IF dw.children=nilBiRel THEN ecSum ← ecSum + dw.eps.Size.EN;
RETURN [FALSE]};
IF dr.wires.Scan[PerDW].found THEN ERROR;
IF ecSum > ecTot THEN ERROR;
RETURN [ecTot - ecSum]};
ReadBoring: PROC [d: Design, fileName: ROPE] RETURNS [boring: Set--of CellInstance--] ~ {
in: IO.STREAM ~ FS.StreamOpen[fileName];
boring ← Sets.CreateHashSet[d.eSpace];
DO
[] ← in.SkipWhitespace[];
IF in.EndOf[] THEN EXIT;
{cctn: ROPE ~ in.GetTokenRope[Break].token;
cin: ROPE ~ in.GetTokenRope[Break].token;
cisn: SteppyName ~ ParseSteppyName[cin];
ictn: ROPE ~ in.GetTokenRope[Break].token;
eol: ROPE ~ in.GetTokenRope[Break].token;
cct: CellType ~ d.FetchCellType[cctn];
ci: CellInstance ~ cct.FetchSubcell[cisn];
ict: CellType ~ d.FetchCellType[ictn];
IF NOT eol.Equal["\n"] THEN ERROR;
IF ci=NIL THEN ERROR;
IF d.CiT[ci] # ict THEN ERROR;
IF NOT boring.AddA[ci] THEN ERROR;
}ENDLOOP;
in.Close[]};
Break: PROC [char: CHAR] RETURNS [IO.CharClass] --IO.BreakProc-- ~ {
RETURN [SELECT char FROM
'\n => break,
<= ' => sepr,
ENDCASE => other]};
ReadFrontier: PROC [d: Design, fileName: ROPE, i: [0..1]] RETURNS [cs: Set--of CellType--] ~ {
in: IO.STREAM ~ FS.StreamOpen[fileName];
cs ← Sets.CreateHashSet[d.eSpace];
DO
[] ← in.SkipWhitespace[];
IF in.EndOf[] THEN EXIT;
{ctn0: ROPE ~ in.GetTokenRope[Break].token;
ctn1: ROPE ~ in.GetTokenRope[Break].token;
eol: ROPE ~ in.GetTokenRope[Break].token;
ctn: ROPE ~ SELECT i FROM 0 => ctn0, 1 => ctn1, ENDCASE => ERROR;
ct: CellType ~ d.FetchCellType[ctn];
IF NOT eol.Equal["\n"] THEN ERROR;
IF ct=NIL THEN ERROR;
[] ← cs.AddA[ct];
}ENDLOOP;
in.Close[]};
CheckFrontier: PROC [d: Design, f: Set--of CellType--, log: IO.STREAM, start: CellType ← NIL] RETURNS [missed: Set, cellInstances, atmWires, cmpWires: INT ← 0] ~ {
seen: Set--of CellType-- ~ Sets.CreateHashSet[d.eSpace];
Work: PROC [ct: CellType, path: ROPE] ~ {
status.prefix ← path;
IF f.HasMemA[ct] THEN {
IF NOT seen.AddA[ct] THEN RETURN;
{subI, subA, subC: INT ← 0;
[,,subI, subA, subC] ← FlatCount[d, ct];
log.PutF["%g: %g %g %g\n", [rope[d.Describe[ct, d]]], [integer[subI]], [integer[subA]], [integer[subC]]];
cellInstances ← cellInstances + subI;
atmWires ← atmWires + subA;
cmpWires ← cmpWires + subC;
RETURN}};
{p1: ROPE ~ IF path#NIL THEN path.Concat["/"] ELSE "";
IF ct.asu#NIL THEN {
subcells: Set ~ ct.CTParts[i];
PerSub: PROC [civ: Sets.Value] RETURNS [BOOL] ~ {
ci: CellInstance ~ NARROW[civ.VA];
ict: CellType ~ d.CiT[ci];
step: ROPE ~ UnparseSteppyName[VSn[ct.fullName[i].Lookup[goal: civ, side: left].DVal[anonymous]]];
subPath: ROPE ~ p1.Concat[step];
Work[ict, subPath];
RETURN [FALSE]};
IF subcells.Scan[PerSub].found THEN ERROR;
d ← d}
ELSE IF ct.asArray#NIL THEN {
a: Array ~ ct.asArray;
ect: CellType ~ ct.EltType;
Work[ect, p1.Concat["0"]];
d ← d}
ELSE log.PutF["!Uncovered %g: %g\n", [rope[path]], [rope[d.Describe[ct, d]]]];
RETURN}};
IF start=NIL THEN start ← d.root;
Work[start, NIL];
missed ← f.Difference[seen].CreateHashCopy[];
RETURN};
END.