<> <> DIRECTORY AbSets, BiRels, FS, IntStuff, IO, LichenDataStructure, LichenIntBasics, LichenPrinting, Rope, SetBasics, StructuredStreams, TiogaAccess, UnparserBuffer; LichenPrintingImpl: CEDAR PROGRAM IMPORTS AbSets, BiRels, FS, IntStuff, IO, LichenDataStructure, Rope, SetBasics, StructuredStreams, TiogaAccess, UnparserBuffer EXPORTS LichenPrinting = BEGIN OPEN IB:LichenIntBasics, IB, LichenDataStructure, LichenPrinting, Ints:IntStuff, Sets:AbSets, SS:StructuredStreams, UB:UnparserBuffer; printStep: INT _ 2; printWidth: INT _ 76; sortTops: BOOL _ TRUE; 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]; RETURN}; PrintRope: PROC [to: IO.STREAM, united: BOOL, rope: ROPE] = { SS.Bp[to, IF united THEN united ELSE lookLeft, printStep]; SS.Begin[to]; to.PutRope[rope !UNWIND => SS.End[to]]; SS.End[to]; RETURN}; PrintDesignOnFile: PUBLIC PROC [d: 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[d: d, subject: d, nameGen: nameGen], ".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, d, nameGen, pacify, Filter]; IF tioga THEN TiogaAccess.WriteFile[taw, realFileName] ELSE IO.Close[fs]; ss.Close[]; RETURN}; PrintDesign: PUBLIC PROC [to: IO.STREAM, d: Design, nameGen: NameGenerator _ NIL, pacify: IO.STREAM _ NIL] = { PrintDesignSubset[to, d, nameGen, pacify, NIL]; RETURN}; PrintDesignSubset: PUBLIC PROC [to: IO.STREAM, d: 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[d, ct, d, nameGen]]]]; PrintCellType[to, ct, nameGen]; IF pacify#NIL THEN pacify.PutRope[" .\n"]; RETURN}; IF Filter=NIL OR Filter[ct] THEN PrintObject[to, TRUE, Inner]; RETURN}; IF pacify#NIL AND Filter=NIL THEN pacify.PutF["Total: %g\n", [integer[d.cellTypes.Size.EN]]]; IF NOT SS.IsAnSS[to] THEN to _ SS.Create[UB.NewInittedHandle[[output: [stream[to]], margin: printWidth]]]; to.PutF["%g: Design {", [rope[Describe[d: d, subject: d, nameGen: nameGen]]]]; d.cellTypes.EnumA[CTPrint]; to.PutF["}"]; RETURN}; PrintNameAndAliases: PROC [to: IO.STREAM, names: Set--of SteppyName--, nonrelnames: Set _ nilSet] ~ { first, second: BOOL _ TRUE; prefix: ROPE _ NIL; PerName: PROC [val: Sets.Value] ~ { name: SteppyName ~ VSn[val]; IF first THEN first _ FALSE ELSE { IF second THEN {to.PutRope["(a.k.a."]; second _ FALSE} ELSE to.PutRope[","]; SS.Bp[to, width, printStep, " "]; }; to.PutRope[prefix]; to.PutRope[UnparseSteppyName[name]]; RETURN}; names.Enumerate[PerName]; IF nonrelnames#nilSet THEN { prefix _ "/"; nonrelnames.Enumerate[PerName]}; IF NOT second THEN to.PutRope[")"]; RETURN}; PrintCellType: PUBLIC PROC [to: IO.STREAM, ct: CellType, nameGen: NameGenerator _ NIL] = { PortPrint: PROC = { tops: Set ~ ct.CTParts[p].Intersection[ct.d.isTop]; sep: ROPE _ NIL; PrintAPort: PROC [pv: Sets.Value] RETURNS [BOOL] ~ { p: Port ~ NARROW[pv.VA]; PPrint: PROC ~ {PrintPW[to, ct, p, p, NIL, nameGen]}; to.PutRope[sep]; PrintObject[to, FALSE, PPrint]; sep _ ", "; RETURN [FALSE]}; to.PutRope["ports: ["]; IF tops.Scan[PrintAPort, IF sortTops THEN ct.fullName[p].MapOrder[leftToRight, steppyNameSpace.SpaceOrder] ELSE Sets.alleq].found THEN ERROR; to.PutRope["]"]; RETURN}; IWPrint: PROC = { tops: Set ~ ct.CTParts[w].Intersection[ct.d.isTop]; sep: ROPE _ NIL; PrintAWire: PROC [wv: Sets.Value] RETURNS [BOOL] ~ { w: Wire ~ NARROW[wv.VA]; WPrint: PROC ~ {PrintPW[to, ct, w, w, NIL, nameGen]}; to.PutRope[sep]; PrintObject[to, FALSE, WPrint]; sep _ ", "; RETURN [FALSE]}; to.PutRope["internal wires: ["]; IF tops.Scan[PrintAWire, IF sortTops THEN ct.fullName[w].MapOrder[leftToRight, steppyNameSpace.SpaceOrder] ELSE Sets.alleq].found THEN ERROR; to.PutRope["]"]; RETURN}; CIPrint: PROC = { to.PutF["connection sites: "]; PrintCells[to, ct, ct.TypeSites, nameGen]; RETURN}; 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.d, ct, ct.d, nameGen]]; to.PutRope[": CellType["]; PrintObject[to, TRUE, PortPrint]; IF ct.asu # 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["]"]; }; PrintPW: PROC [to: IO.STREAM, ct: CellType, class: PWClass, pw: PW, parent: PW _ NIL, nameGen: NameGenerator _ NIL] ~ { [] _ ct.d.Describe[pw, IF parent#NIL THEN parent ELSE ct, nameGen]; {fullNames: Set ~ ct.fullName[class].MappingA[pw]; IF parent#NIL THEN { relNames: Set ~ RelativeNames[ct, class, parent, pw]; reldNames: Set ~ SNsCat[ct.fullName[class].MappingA[parent], relNames]; nonRelNames: Set ~ fullNames.Difference[reldNames]; PrintNameAndAliases[to, relNames, nonRelNames]; to _ to} ELSE PrintNameAndAliases[to, fullNames]; IF ct.d.Atomic[pw] THEN RETURN; {shape: LOI ~ Shape[ct, class, pw]; IF shape#NIL THEN { IF shape.rest=NIL THEN ERROR; FOR dims: LOI _ shape, dims.rest WHILE dims.rest#NIL DO to.PutF["*%g", [integer[dims.first]]]; ENDLOOP; RETURN}; {kids: Seq ~ BiRels.DeRef[ct.d.sub.ApplyA[pw].MA]; first: BOOL _ TRUE; to.PutRope["["]; FOR i: INT IN [0 .. kids.Size.EN) DO kid: PW ~ kids.ApplyI[i].MA; PWPrint: PROC ~ {PrintPW[to, ct, class, kid, pw, nameGen]}; IF first THEN first _ FALSE ELSE to.PutRope[", "]; PrintObject[to, FALSE, PWPrint]; ENDLOOP; to.PutRope["]"]; RETURN}}}}; listOne: LOI ~ LIST[1]; Shape: PROC [ct: CellType, class: PWClass, pw: PW] RETURNS [LOI] ~ { IF ct.d.Atomic[pw] THEN RETURN [listOne]; {kids: Seq ~ BiRels.DeRef[ct.d.sub.ApplyA[pw].MA]; width: LNAT ~ kids.Size.EN; subShape: LOI _ NIL; FOR i: INT IN [0 .. width) DO kid: PW ~ kids.ApplyI[i].MA; thissub: LOI; AcceptIndex: PROC [sn: SteppyName] RETURNS [BOOL] ~ { IF sn.grade.nonsubs#0 OR sn.grade.subs#1 THEN RETURN [FALSE]; IF NARROW[sn.steps.first, REF INT]^ # i THEN RETURN [FALSE]; RETURN [TRUE]}; IF NOT ct.ScanRelativeNames[class, pw, kid, AcceptIndex].found THEN RETURN [NIL]; thissub _ Shape[ct, class, kid]; IF thissub=NIL THEN RETURN [NIL]; IF subShape=NIL THEN subShape _ thissub ELSE IF NOT LoiEqual[subShape, thissub] THEN RETURN [NIL]; ENDLOOP; RETURN [CONS[width, subShape]]}}; LoiEqual: PROC [l1, l2: LOI] RETURNS [BOOL] ~ { WHILE l1#l2 DO IF l1=NIL OR l2=NIL OR l1.first#l2.first THEN RETURN [FALSE]; l1 _ l1.rest; l2 _ l2.rest; ENDLOOP; RETURN [TRUE]}; PrintCells: PUBLIC PROC [to: IO.STREAM, cct: CellType, set: Set--OF Cell--, nameGen: NameGenerator _ NIL] = { first: BOOL _ TRUE; PrintIt: PROC [cell: Cell] = { IPrint: PROC = {PrintCell[to, cct, cell, nameGen]}; IF first THEN first _ FALSE ELSE to.PutRope[", "]; PrintObject[to, TRUE, IPrint]; }; to.PutRope["["]; set.EnumA[PrintIt]; to.PutRope["]"]; }; PrintCell: PUBLIC PROC [to: IO.STREAM, cct: CellType, cell: Cell, nameGen: NameGenerator _ NIL] = { conns: Fn--Port PrintForPorts: PROC [pct: CellType, ports: Set--of Port--, rel: REF ANY, sort: BOOL] = { first: BOOL _ TRUE; PrintForPort: PROC [val: Sets.Value] RETURNS [BOOL] ~ { p: Port ~ NARROW[val.VA]; CPrint: PROC ~ { w: Wire ~ NARROW[conns.ApplyA[p].MDA]; to.PutRope[cct.d.Describe[p, rel, nameGen]]; to.PutRope[": "]; IF w#NIL THEN {to.PutRope[cct.d.Describe[w, cct, nameGen]]; RETURN}; {pkids: Seq--of Port-- ~ BiRels.DeRef[cct.d.sub.ApplyA[p].MDA]; IF pkids=nilBiRel THEN {to.PutRope["??"]; RETURN}; {wkids: Seq--of Wire-- ~ pkids.Compose[conns]; nwkids: NATURAL ~ wkids.Size.EN; npkids: NATURAL ~ pkids.Size.EN; IF nwkids#npkids THEN GOTO NotEasy; {ws: Set--of Wire-- ~ wkids.SetOn[right]; IF ws.Size=Ints.one THEN {to.PutF["%g*%g", [rope[cct.d.Describe[ws.TheElt.VA, cct, nameGen]]], [integer[pkids.Size.EN]]]; RETURN}; {wparents: Set--of Wire-- ~ cct.d.parent.Image[ws]; IF wparents.Size#Ints.one THEN GOTO NotEasy; {wparent: Wire ~ NARROW[wparents.TheElt.VA]; allwkids: Seq--of Wire-- ~ BiRels.DeRef[cct.d.sub.ApplyA[wparent].MA]; mi: Sets.MaybeValue ~ allwkids.Index[wkids]; IF NOT mi.found THEN GOTO NotEasy; {base: NATURAL ~ mi.it.VI; to.PutRope[cct.d.Describe[wparent, cct, nameGen]]; IF base#0 OR allwkids.Size.EN#npkids THEN to.PutF["[%g..%g]", [integer[base]], [integer[base+npkids-1]] ]; RETURN}}}}; EXITS NotEasy => NULL}; PrintForPorts[pct, pkids.SetOn[right], p, FALSE]; RETURN}}; IF first THEN first _ FALSE ELSE to.PutRope[", "]; PrintObject[to, FALSE, CPrint]; RETURN [FALSE]}; to.PutRope["["]; IF ports.Scan[PrintForPort, IF sort AND sortTops THEN pct.fullName[p].MapOrder[leftToRight, steppyNameSpace.SpaceOrder] ELSE Sets.alleq].found THEN ERROR; to.PutRope["]"]; RETURN}; WITH cell SELECT FROM ct: CellType => { IF ct # cct THEN ERROR; conns _ ct.asu.exports; to.PutRope["exports"]; PrintForPorts[ct, ct.TopParts[p], ct, TRUE]; RETURN}; ci: CellInstance => { ict: CellType ~ cct.d.CiT[ci]; conns _ ci.conns; [] _ cct.d.Describe[ci, cct, nameGen]; PrintNameAndAliases[to, cct.INames[ci]]; to.PutF[": %g", [rope[cct.d.Describe[ict, cct.d, nameGen]]] ]; PrintForPorts[ict, ict.TopParts[p], ict, TRUE]; RETURN}; ENDCASE => ERROR; }; printStatRep: BOOL _ TRUE; printDumbRep: BOOL _ FALSE; PrintArray: PUBLIC PROC [to: IO.STREAM, act: CellType, nameGen: NameGenerator _ NIL] = { a: Array = act.asArray; ect: CellType ~ act.EltType[]; BasePrint: PROC = { to.PutF["base period = [%g, %g]", [integer[a.basePeriod[X]]], [integer[a.basePeriod[Y]]]]}; StatPrint: PROC = { to.PutRope["static graph = ["]; PrintStatRep[to, act, nameGen]; to.PutRope["]"]; }; to.PutF["{%g BY %g OF %g, ", [integer[a.size2[X]]], [integer[a.size2[Y]]], [rope[act.d.Describe[ect, act.d, 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, act: CellType, nameGen: NameGenerator] ~ { a: Array = act.asArray; ect: CellType ~ act.EltType[]; firstEdge: BOOL _ TRUE; EnsureNamed: PROC [part: Part] ~ { [] _ act.d.Describe[part, ect, nameGen]; RETURN}; PrintEdge: PROC [val: Sets.Value] ~ { IF firstEdge THEN firstEdge _ FALSE ELSE to.PutRope[", "]; PrintRope[to, TRUE, a.statrep.edgeSpace.SFormat[val]]; RETURN}; ect.EnumCTParts[p, TRUE, TRUE, EnsureNamed]; a.statrep.edges.Enumerate[PrintEdge, Sets.fwd]; RETURN}; 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[X]=1 OR ct.asArray.size2[Y]=1)]}; Is2D: PROC [ct: CellType] RETURNS [BOOL] ~ {RETURN [ct.asArray#NIL AND ct.asArray.size2[X]#1 AND ct.asArray.size2[Y]#1]}; PrintArrays: PROC [to: IO.STREAM, d: Design, nameGen: NameGenerator _ NIL, pacify: IO.STREAM _ NIL] = { PrintDesignSubset[to, d, nameGen, pacify, IsArray]; }; END.