<> <> DIRECTORY LichenCollections, LichenDataOps, LichenDataStructure, LichenIntFunctions, LichenPairCollections, LichenTransforms, List; LichenFlattenning: CEDAR PROGRAM IMPORTS LichenCollections, LichenDataOps, LichenDataStructure, LichenIntFunctions, LichenPairCollections, List EXPORTS LichenTransforms = BEGIN OPEN LichenDataOps, LichenDataStructure, Colls:LichenCollections, PairColls:LichenPairCollections, IntFns:LichenIntFunctions; ExpandVertex: PUBLIC PROC [child: CellInstance] RETURNS [roleToSib: Seq--role ct: CellType ~ child.type; parent: CellType ~ child.containingCT; u: Unorganized ~ ct.asUnorganized; roles: INT ~ u.containedInstances.Size[]; promote: VarFunction--part of ct SetPromotion: PROC [inner, outer: Wire] ~ { IF inner=NIL OR outer=NIL THEN ERROR; IF NOT promote.Store[[inner, outer]] THEN ERROR; inner _ inner.FirstChildWire[]; outer _ outer.FirstChildWire[]; WHILE inner#NIL AND outer#NIL DO SetPromotion[inner, outer]; inner _ inner.NextChildWire[]; outer _ outer.NextChildWire[]; ENDLOOP; IF inner#NIL OR outer#NIL THEN ERROR; }; NotePorting: PROC [p: Port, w: Wire] ~ { SetPromotion[p.wire, w]; }; MoveCell: PROC [ra: REF ANY] ~ { ci: CellInstance ~ NARROW[ra]; sib: CellInstance ~ Instantiate[ci.type, parent, CrossNames[child, ci]]; GetPromotion: PROC [vi, uvo: Vertex, port: Port] RETURNS [vo: Vertex] ~ { IF (vo _ NARROW[promote.Apply[vi].DVal])#NIL THEN RETURN; WITH vi SELECT FROM wi: Wire => { uwo: Wire ~ WITH uvo SELECT FROM x: Wire => x, ENDCASE => NIL; wo: Wire ~ vo _ CreateWire[parent, uwo, IF uwo#NIL THEN vi.VertexNames.Copy.data ELSE CrossNames[child, vi]]; IF NOT promote.Store[[wi, wo]] THEN ERROR; WITH uvo SELECT FROM x: Intermediary => AddEdge[[x, wo], port]; ENDCASE => NULL; FOR cwi: Wire _ wi.FirstChildWire, cwi.NextChildWire WHILE cwi # NIL DO [] _ GetPromotion[cwi, wo, NIL] ENDLOOP; }; ii: Intermediary => { io: Intermediary ~ vo _ CreateIntermediary[uvo, wireward, parent, port, vi.VertexNames.Copy.data]; PromoteIM: PROC [q: Port, wi: Vertex] ~ {[] _ GetPromotion[wi, io, q]}; IF NOT promote.Store[[ii, io]] THEN ERROR; EnumerateImmediateConnections[ii, PromoteIM, [FALSE, TRUE]]; }; cii: CellInstance => ERROR; ENDCASE => ERROR; IF vo=NIL THEN ERROR; }; PromoteEdge: PROC [p: Port, v: Vertex] ~ { w: Vertex ~ GetPromotion[v, sib, p]; AddEdge[[sib, w], p]; }; roleToSib.Append[sib]; EnumerateImmediateConnections[ci, PromoteEdge]; }; roleToSib _ CreateSeq[oneToOne: TRUE]; EnumerateTopConnections[child, NotePorting]; u.containedInstances.Enumerate[MoveCell]; DeleteVertex[child]; roleToSib _ roleToSib.Freeze; }; CrossNames: PROC [outer, inner: Vertex] RETURNS [ListData] ~ { crossed: Set--of SteppyName-- ~ [listClass, CreateSteppyNames[]]; Crossit: PROC [v1: REF ANY] ~ { outerName: SteppyName ~ NARROW[v1]; Finish: PROC [v2: REF ANY] ~ { innerName: SteppyName ~ NARROW[v2]; name: SteppyName ~ List.Append[outerName, innerName]; new: BOOL ~ crossed.AddElt[name]; RETURN}; inner.VertexNames.Enumerate[Finish]; RETURN}; outer.VertexNames.Enumerate[Crossit]; RETURN [crossed.data]}; Flatten: PUBLIC PROC [root: CellType, expand: ConstFilter--of CellInstance--] ~ { action: BOOL _ TRUE; MaybeExpand: PROC [ra: REF ANY] ~ { ci: CellInstance ~ NARROW[ra]; IF expand.HasMember[ci] THEN { action _ TRUE; [] _ ExpandVertex[ci]; }; }; u: Unorganized ~ root.asUnorganized; IF u=NIL THEN ERROR; WHILE action DO action _ FALSE; u.containedInstances.Enumerate[MaybeExpand]; ENDLOOP; root _ root; }; END.