DIRECTORY Asserting, LichenArrayStuff, LichenCollections, LichenDataOps, LichenDataStructure, LichenIntFunctions, LichenNavigation, LichenPairCollections, LichenTransforms, LichenTransformsPrivate, RefTab, Rope; LichenSplitMerge: CEDAR PROGRAM IMPORTS Asserting, LichenArrayStuff, LichenCollections, LichenDataOps, LichenDataStructure, LichenIntFunctions, LichenNavigation, LichenPairCollections, LichenTransformsPrivate, RefTab, Rope EXPORTS LichenTransforms = BEGIN OPEN LichenArrayStuff, LichenNavigation, LichenDataStructure, LichenTransforms, LichenDataOps, LichenTransformsPrivate, Colls:LichenCollections, PairColls:LichenPairCollections, IntFns:LichenIntFunctions; PortAns: TYPE ~ REF PortAnsPrivate; PortAnsPrivate: TYPE ~ RECORD [ from, to: Port, doFrom: PortAction _ leave, doTo: PortAction[dontAdd..addPort] _ dontAdd ]; SplitType: PUBLIC PROC [design: Design, fizz: ConstSet--of CellInstance--] RETURNS [from, to: CellType, pairs: ConstOneToOne--instance of from or ancestor f instance of to or ancestor--] ~ { cs: Seq--role f fizzee-- ~ IntFns.CreateFromCollection[fizz]; analysis: Analysis ~ NEW [AnalysisPrivate _ [ roles: fizz.Size[], subjTypes: cs.Compose[right: instanceType, rightRestricts: FALSE].CreateSimpleCopy[oneToOne: TRUE].Freeze, wag: NEW [WireAnsweringPrivate _ [ oldSubjConnectionss: CreateRefSeq[fizz.Size[]], anses: PairColls.CreateHashFn[] ]], doomedPorts: Colls.CreateHashSet[] ]]; {OPEN analysis; connectionsV: VarFunction--port of to _ port of from-- ~ PairColls.CreateHashFn[invable: TRUE]; pairsV: VarOneToOne ~ PairColls.CreateHashOTO[]; nameParts: LOLORA _ NIL; toName, subTail: ROPE; IF roles=0 THEN Error["Null fission"]; from _ NIL; {i: INT _ 0; PerElt: PROC [ra: REF ANY] ~ {v: CellInstance ~ NARROW[ra]; IF v.type=NIL OR v.containingCT=NIL THEN ERROR; IF from=NIL THEN from _ v.containingCT ELSE IF from#v.containingCT THEN Error["Fission of vertices not all having same parent"]; nameParts _ CONS[Listify[v.VertexNames], nameParts]; IF v.type # subjTypes.Apply[i].val THEN ERROR; i _ i + 1; }; fizz.Enumerate[PerElt]; IF i # cs.Size THEN ERROR; }; IF NOT from.designs.HasMember[design] THEN ERROR; subTail _ RopeCrossCat[nameParts]; toName _ RopeCrossCat[LIST[Select[nameReln, 1, from.otherPublic], LIST[subTail]]]; subTail _ Rope.Concat["-", subTail]; to _ CreateCellType[design: design, cellTypeName: toName, class: NIL, internals: TRUE]; IF Survey[from, NIL, cs, analysis, TRUE] THEN ERROR; {MoveWire: PROC [pair: PairColls.Pair] ~ { wire: Wire ~ NARROW[pair[left]]; wa: WireAns ~ NARROW[pair[right]]; IF NOT wa.analyzed THEN ERROR; IF wa.counterpart # NIL THEN ERROR; wa.counterpart _ CreateWire[containingCT: to, copy: wire, names: wire.VertexNames.Copy.data]; SELECT wa.doFrom FROM addPort => { wa.fromPort _ AddPort[[parent: from.port, wire: wire]]; AddEdge[[from.asUnorganized.mirror, wire], wa.fromPort]}; leave, dontAdd, dePort => NULL; ENDCASE => ERROR; SELECT wa.doTo FROM addPort => { wa.toPort _ AddPort[[parent: to.port, wire: wa.counterpart]]; IF wa.fromPort=NIL THEN ERROR; IF NOT connectionsV.Store[[wa.toPort, wa.fromPort]] THEN ERROR; AddEdge[[to.asUnorganized.mirror, wa.counterpart], wa.toPort]}; dontAdd => NULL; ENDCASE => ERROR; }; wag.anses.Enumerate[MoveWire]; }; FOR role: NATURAL IN [0 .. roles) DO fci: CellInstance ~ NARROW[cs.Apply[role].val]; tci: CellInstance ~ Instantiate[fci.type, to, fci.other]; MoveConnection: PROC [subjPort: Port, fwire: Wire] ~ { wa: WireAns = GetRPAns[wag, role, subjPort, fwire, FALSE]; IF NOT wa.analyzed THEN ERROR; AddEdges[[tci, wa.counterpart], subjPort]; }; EnumerateTopConnections[fci, MoveConnection]; ENDLOOP; {connections: ConstFunction ~ connectionsV.Freeze; doomedPortsC: ConstSet ~ doomedPorts.Freeze; FixArrays[design, from, to, connections, doomedPortsC, portToInternalWire, subTail, pairsV]; FixInstances[from, to, connections, doomedPortsC, portToInternalWire, pairsV]; FOR i: INT IN [0 .. cs.Size) DO DeleteVertex[NARROW[cs.Apply[i].val]]; ENDLOOP; {KillWireAndPort: PROC [pair: PairColls.Pair] ~ { wire: Wire ~ NARROW[pair[left]]; wa: WireAns ~ NARROW[pair[right]]; IF NOT wa.analyzed THEN ERROR; IF wa.counterpart=NIL THEN ERROR; SELECT wa.doFrom FROM addPort => NULL; leave, dontAdd => NULL; dePort => RemovePort[wa.fromPort]; ENDCASE => ERROR; IF NOT (wa.sawElse OR wa.sawBords) THEN DeleteVertex[wire]; design _ design; }; wag.anses.Enumerate[KillWireAndPort]; }; pairs _ pairsV.Freeze; }}}; FixArrays: PROC [ design: Design, fromAncestorCT, toAncestorCT: CellType, eltConnections: ConstFunction--port of toAncestorCT _ port of fromAncestorCT--, doomedFromPorts: ConstSet--of port of fromAncestorCT--, eltTPToWire: UWFunction--port of toAncestorCT _ prototypical wire--, subTail: ROPE--to append to name of from array--, pairs: VarOneToOne--instance of from or ancestor f instance of to or ancestor-- ] ~ { SplitArray: PROC [fromArrayCT: CellType] ~ { fa: Array ~ fromArrayCT.asArray; faName: ROPE ~ NARROW[Asserting.FnVal[nameReln, fromArrayCT.otherPublic]]; taName: ROPE ~ faName.Cat[subTail]; toArrayCT: CellType ~ CreateArray[design, taName, NIL, toAncestorCT, fa.size, fa.jointsPeriod, GetBorders[fa], NIL, NIL]; ta: Array ~ toArrayCT.asArray; toNewGroup: VarFunction--group of fa _ group of ta-- ~ PairColls.CreateHashFn[]; toNewTie: VarFunction--tie of ta _ tie of fa-- ~ PairColls.CreateHashFn[]; arrayConnectionsV: VarFunction--port of toArrayCT _ port of fromArrayCT-- ~ PairColls.CreateHashFn[invable: TRUE]; arrayTPToWireV: VarFunction--port of ta _ wire-- ~ PairColls.CreateHashFn[]; doomedArrayPortsV: VarSet--of port of fa-- ~ Colls.CreateHashSet[]; AddConnection: PROC [fai: ArrayIndex, fg: Group, tai: ArrayIndex, tg: Group] ~ { IF fg=NIL OR tg=NIL THEN ERROR; {fp: Port ~ GetArrayPortForGroup[fromArrayCT, fa, fai, fg, TRUE]; tp: Port ~ GetArrayPortForGroup[toArrayCT, ta, tai, tg, TRUE]; w: Wire ~ NARROW[eltTPToWire.Apply[tg.ports.first].Val]; IF fp=NIL OR tp=NIL THEN ERROR; IF w=NIL THEN ERROR; SELECT arrayConnectionsV.Apply[tp].DVal FROM fp => NULL; NIL => IF NOT arrayConnectionsV.Store[[tp, fp]] THEN ERROR; ENDCASE => ERROR; [] _ arrayTPToWireV.Store[[tp, w]]; }}; IF IsIncompleteArray[fromArrayCT] THEN ERROR; IF ta.groupingParmses # fa.groupingParmses THEN ERROR; {UnroleOldPort: PROC [ra: REF ANY] ~ {UnrolePort[fa, NARROW[ra]]}; doomedFromPorts.Enumerate[UnroleOldPort]; }; FOR gi: NATURAL IN [0 .. fa.groupingses.length) DO fgs: Groupings ~ NARROW[fa.groupingses[gi]]; tgs: Groupings ~ NARROW[ta.groupingses[gi]]; MoveGroup: PROC [ra: REF ANY] ~ { fg: Group ~ NARROW[ra]; tg: Group ~ MakeGroup[ta, fg.gi2, tgs]; IF NOT toNewGroup.Store[[fg, tg]] THEN ERROR; FOR pl: PortList _ fg.ports, pl.rest WHILE pl # NIL DO fp: Port ~ NARROW[pl.first]; EnGroup: PROC [ra: REF ANY] ~ { tp: Port ~ NARROW[ra]; AddPortToGroup[ta, gi, tp, tg, FALSE]; }; eltConnections.EnumerateMapping[fp, EnGroup, rightToLeft]; IF doomedFromPorts.HasMember[fp] THEN RemovePortFromGroup[fa, gi, fp, fg]; ENDLOOP; ra _ ra; }; fgs.groups.Enumerate[MoveGroup]; ENDLOOP; {MoveTie: PROC [d: Dim, phase: Nat2, jgi: NATURAL, jgi2: Nat2, j: Joint, tie: Tie] ~ { fj: Joint ~ j; ftie: Tie ~ tie; IF ftie.groups[low]#NIL AND ftie.groups[high]#NIL THEN { tj: Joint ~ GetArrayJoint[ta, d, phase]; ttie: Tie ~ NEW [TiePrivate _ [groups: [ low: NARROW[toNewGroup.Apply[ftie.groups[low]].Val], high: NARROW[toNewGroup.Apply[ftie.groups[high]].Val]]]]; IF ttie.groups[low]=NIL OR ttie.groups[high]=NIL THEN ERROR; AddTie[tj, jgi, ttie]; IF NOT toNewTie.Store[[ftie, ttie]] THEN ERROR; }; }; EnumerateTies[fa, MoveTie]; }; FlushArrayWires[fa, doomedArrayPortsV]; {ConnectGroup: PROC [pair: PairColls.Pair] ~ { fg: Group ~ NARROW[pair[left]]; tg: Group ~ NARROW[pair[right]]; IF tg.gi2#fg.gi2 THEN ERROR; IF tg.ports#NIL AND (fg.ports#NIL OR fa.toWire.Fetch[fg].val#NIL) THEN { air: Range2 ~ Gi2ToAir[fa, fg.gi2].air; FOR f: INT IN [air[Foo].min .. air[Foo].maxPlusOne) DO FOR b: INT IN [air[Bar].min .. air[Bar].maxPlusOne) DO ai: ArrayIndex ~ [f, b]; IF fg.ports#NIL OR GetArrayPortForGroup[fromArrayCT, fa, ai, fg, FALSE]#NIL THEN AddConnection[ai, fg, ai, tg]; ENDLOOP ENDLOOP; }; }; toNewGroup.Enumerate[ConnectGroup]; }; {ConnectTie: PROC [d: Dim, phase: Nat2, jgi: NATURAL, jgi2: Nat2, j: Joint, tie: Tie] ~ { ftie: Tie ~ tie; ttie: Tie ~ NARROW[toNewTie.Apply[ftie].DVal]; IF ttie#NIL AND ((ttie.groups[low].ports=NIL) # (ttie.groups[high].ports=NIL)) AND ((ttie.groups[low].ports=NIL) # (ftie.groups[low].ports=NIL)) AND ((ttie.groups[high].ports=NIL) # (ftie.groups[high].ports=NIL)) THEN { o: Dim ~ OtherDim[d]; toHigh: BOOL ~ ttie.groups[low]=NIL; FOR perp: NATURAL IN [0 .. fa.size[o]) DO FOR para: NATURAL IN [0 .. fa.size[d]-1) DO lai: ArrayIndex ~ ConsInt2[d, para, perp]; hai: ArrayIndex ~ Int2Tweak[lai, d, 1]; IF toHigh THEN AddConnection[lai, ftie.groups[low], hai, ttie.groups[high]] ELSE AddConnection[lai, ftie.groups[high], hai, ttie.groups[low]]; ENDLOOP ENDLOOP; }; }; EnumerateTies[fa, ConnectTie]; }; TrimEmptyGroups[fa]; TrimEmptyGroups[ta]; {arrayConnections: ConstFunction ~ arrayConnectionsV.Freeze; doomedArrayPorts: ConstSet ~ doomedArrayPortsV.Freeze; arrayTPToWire: ConstFunction ~ arrayTPToWireV.Freeze; KillDoomedArrayPort: PROC [ra: REF ANY] ~ { p: Port--of fromArrayCT-- ~ NARROW[ra]; RemovePort[p]; }; FixArrays[design, fromArrayCT, toArrayCT, arrayConnections, doomedArrayPorts, arrayTPToWire, subTail, pairs]; FixInstances[fromArrayCT, toArrayCT, arrayConnections, doomedArrayPorts, arrayTPToWire, pairs]; doomedArrayPorts.Enumerate[KillDoomedArrayPort]; }; }; fromAncestorCT.EnumerateArrays[SplitArray]; }; FixInstances: PROC [ fromAncestorCT, toAncestorCT: CellType, connections: ConstFunction--port of toAncestorCT _ port of fromAncestorCT--, doomedFromPorts: ConstSet--of port of fromAncestorCT--, tpToWire: UWFunction--port of toAncestorCT _ prototypical wire--, pairs: VarOneToOne--instance of from or ancestor f instance of to or ancestor-- ] ~ { FixInstance: PROC [fci: CellInstance] ~ { parentCT: CellType ~ fci.containingCT; tci: CellInstance ~ Instantiate[toAncestorCT, parentCT]; ConnectChildren: PROC [parent: Port, do: BOOL] RETURNS [done: BOOL] ~ { done _ FALSE; FOR tp: Port _ FirstChildPort[parent], NextChildPort[tp] WHILE tp # NIL DO IF connections.MappingSize[tp, leftToRight, 1]#0 THEN done _ TRUE; ENDLOOP; IF done OR do THEN { FOR tp: Port _ FirstChildPort[parent], NextChildPort[tp] WHILE tp # NIL DO seen: BOOL _ FALSE; PerFrom: PROC [ra: REF ANY] ~ { fp: Port--of fa-- ~ NARROW[ra]; w: Wire ~ FindTransitiveConnection[fci, fp]; IF seen THEN ERROR ELSE seen _ TRUE; IF w=NIL THEN ERROR; AddEdges[[tci, w], tp]; }; connections.EnumerateMapping[tp, PerFrom]; IF seen THEN NULL ELSE IF NOT ConnectChildren[tp, FALSE] THEN { w: Wire ~ CreateWire[containingCT: parentCT, copy: NARROW[tpToWire.Apply[tp].DVal]]; AddEdges[[tci, w], tp]; }; ENDLOOP; }; }; [] _ ConnectChildren[toAncestorCT.port, TRUE]; UnlinkPorts[fci, doomedFromPorts]; IF pairs.AddPair[[fci, tci], PairColls.addIfNew]#[new, new] THEN ERROR; }; EnumerateInstances[fromAncestorCT, FixInstance, FALSE]; }; Listify: PROC [set: Set] RETURNS [list: LORA] ~ { AddElt: PROC [val: REF ANY] ~ { steppy: SteppyName ~ NARROW[val]; list _ CONS[UnparseSteppyName[steppy], list]; RETURN}; list _ NIL; set.Enumerate[AddElt]; RETURN}; Select: PROC [reln: Asserting.Term, position: NATURAL, from: Assertions] RETURNS [terms: Asserting.Terms] ~ { Filter: PROC [assertion: Asserting.Assertion] ~ { these: Asserting.Terms _ Asserting.TermsOf[assertion]; THROUGH [1 .. position) DO these _ these.rest ENDLOOP; terms _ CONS[these.first, terms]; }; Asserting.EnumerateAssertionsAbout[reln, from, Filter]; }; RopeCrossCat: PROC [lolora: LOLORA] RETURNS [ans: ROPE] ~ { ans _ NIL; FOR lolora _ lolora, lolora.rest WHILE lolora # NIL DO lora: LORA _ NARROW[lolora.first]; subAns: ROPE _ NIL; n: NATURAL _ 0; FOR lora _ lora, lora.rest WHILE lora # NIL DO n _ n + 1; SELECT n FROM 1 => NULL; 2 => subAns _ Rope.Cat["{", subAns, "|"]; ENDCASE => subAns _ subAns.Concat["|"]; subAns _ subAns.Concat[NARROW[lora.first]]; ENDLOOP; IF n > 1 THEN subAns _ subAns.Concat["}"]; IF ans # NIL THEN ans _ ans.Concat["-"]; ans _ ans.Concat[subAns]; ENDLOOP; ans _ ans; }; END. \LichenSplitMerge.Mesa Last tweaked by Mike Spreitzer on August 3, 1987 3:18:19 pm PDT ʘ™Icodešœ?™?—J˜KšÏk œÊ˜ÓK˜šÑbnxœœ˜Kšœ·˜¾Kšœ˜—K˜Kš œœtÏnœŸ œŸœ˜ÒK˜Kšœ œœ˜#šœœœ˜K˜Kšœ˜Kšœ,˜,K˜—K˜šŸ œœœ Ïcœœ* Ðcm œ˜¾Kšœ ¡  œ%˜=šœœ˜-Kšœ˜Kšœ;œœ ˜jšœœ˜"Kšœ/˜/Kšœ˜Kšœ˜—K˜"Kšœ˜—Kšœœ ˜Kšœ  ¡ œ#œ˜_Kšœ0˜0Kšœ œœ˜Kšœœ˜Kšœ œ˜&Kšœœ˜ Kšœœ˜ š Ÿœœœœœ˜;Kš œœœœœœ˜/Kš œœœœœœ9˜€Kšœ œ$˜4Kšœ!œœ˜.K˜ K˜—Kšœ˜Kšœ œœ˜K˜Kšœœ œœ˜1Kšœ"˜"Kšœœ(œ ˜RK˜$KšœAœ œ˜WKš œœœœœ˜4šœŸœœ˜*Kšœ œ ˜ Kšœœ˜"Kšœœ œœ˜Kšœœœœ˜#Kšœ]˜]šœ ˜šœ ˜ Kšœ7˜7Kšœ9˜9—Kšœœ˜Kšœœ˜—šœ ˜šœ ˜ Kšœ=˜=Kšœ œœœ˜Kšœœ.œœ˜?Kšœ?˜?—Kšœ œ˜Kšœœ˜—K˜—Kšœ˜K˜šœœœ˜$Kšœœ˜/Kšœ9˜9šŸœœ"˜6Kšœ3œ˜:Kšœœ œœ˜Kšœ*˜*K˜—K˜-Kšœ˜—Kšœ2˜2Kšœ,˜,Kšœ\˜\KšœN˜Nšœœœ˜Kšœ œ˜&Kšœ˜—šœŸœœ˜1Kšœ œ ˜ Kšœœ˜"Kšœœ œœ˜Kšœœœœ˜!šœ ˜Kšœ œ˜Kšœœ˜Kšœ"˜"Kšœœ˜—Kšœœ œœ˜;K˜K˜—Kšœ%˜%K˜Kšœ˜K˜—K˜šŸ œ˜šœ˜K˜Kšœ'˜'Kšœ ¡ œ˜OKšœ œ˜7Kšœ ¡ œ˜DKšœ  #œ˜1Kšœ ¡ ˜O—Kšœ˜šŸ œœ˜,K˜ Kšœœœ5˜JKšœœ˜#Kšœ2œ:œœ˜yKšœ˜Kšœ ¡ œ˜PKšœ  ¡  œ˜JKšœ ¡ œ#œ˜rKšœ  ¡ œ˜LKšœ œ˜CšŸ œœ=˜PKš œœœœœœ˜Kšœ;œ˜AKšœ8œ˜>Kšœ œ(˜8Kš œœœœœœ˜Kšœœœœ˜šœ"˜,Kšœœ˜ Kš œœœ#œœ˜;Kšœœ˜—Kšœ#˜#K˜—Kšœ œœ˜-Kšœ)œœ˜6Kš œŸ œœœœœ˜BKšœ)˜)K˜šœœœ˜2Kšœœ˜,Kšœœ˜,šŸ œœœœ˜!Kšœ œ˜Kšœ'˜'Kšœœœœ˜-šœ"œœ˜6Kšœ œ ˜šŸœœœœ˜Kšœ œ˜Kšœœ˜&K˜—Kšœ:˜:Kšœœ%˜JKšœ˜—K˜K˜—Kšœ ˜ Kšœ˜—šœŸœœœ%˜VK˜K˜š œœœœœ˜8Kšœ(˜(šœ œ˜(Kšœœ)˜4Kšœœ-˜9—Kš œœœœœœ˜œ>˜ŽKšœœ˜—K˜—K˜—Kšœ˜K˜K˜K˜Kšœ<˜