<> <> 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: ROPE _ NIL]; 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 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.