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šœœ
˜Kšœœ˜ Kšœœœ˜šœ
œœœœœœ˜HKšœ'˜'šœœœ'œœœœ'˜mK˜Kšœ
œœ/œœœ˜oKšœœ˜—K˜—K˜—Kšœ#˜#K˜šœŸ
œœœ%˜YK˜Kšœœ˜.šœ˜Kšœœœ˜BKšœœœ˜AKšœœœ˜CKšœ˜K˜Kšœœœ˜$šœœœœœœœ˜UKšœ*˜*Kšœ'˜'Kšœœ>œ>˜ŽKšœœ˜—K˜—K˜—Kšœ˜K˜K˜K˜Kšœ<˜<Kšœ6˜6K˜5šŸœœœœ˜+Kšœ œœ˜'Kšœ˜K˜—Kšœm˜mKšœ_˜_Kšœ0˜0K˜K˜—K˜+K˜—K˜�šŸœ˜šœ˜Kšœ'˜'Kšœ ¡ œ˜LKšœ œ˜7Kšœ ¡ œ˜AKšœ ¡ ˜O—Kšœ˜šŸœœ˜)K˜&Kšœ8˜8š
Ÿœœœœœ˜GKšœœ˜
šœ6œœ˜JKšœ/œœ˜BKšœ˜—šœœœ˜šœ6œœ˜JKšœœœ˜šŸœœœœ˜Kšœ 	œœ˜Kšœ,˜,Kš
œœœœœ˜$Kšœœœœ˜K˜K˜—Kšœ*˜*Kšœœ˜š
œœœœœ˜-Kšœ3œ˜TK˜K˜—Kšœ˜—K˜—K˜—Kšœ(œ˜.Kšœ"˜"Kšœ:œœ˜GK˜—Kšœ0œ˜7K˜—K˜�šŸœœœœ˜1šŸœœœœ˜Kšœœ˜!Kšœœ"˜-Kšœ˜—Kšœœ˜Kšœ˜Kšœ˜—K˜�šŸœœ"œœ˜mšŸœœ%˜1Kšœ6˜6Kšœœœ˜6Kšœœ˜!K˜—Kšœ7˜7K˜—K˜�š
Ÿœœ
œœœ˜;Kšœœ˜
šœœ
œ˜6Kšœœœ˜"Kšœœœ˜Kšœœ˜šœœœ˜.K˜
šœ˜
Kšœœ˜
K˜)Kšœ ˜'—Kšœœ˜+Kšœ˜—Kšœœ˜*Kšœœœ˜(K˜Kšœ˜—K˜
K˜—K˜�Kšœ˜—�…—����/ ��>
��