LichenWireMunging.Mesa
Last tweaked by Mike Spreitzer on August 3, 1988 3:29:04 pm PDT
DIRECTORY AbSets, AMBridge, AMTypes, BasicTime, BiRelBasics, BiRels, IntStuff, IO, LichenDataOps, LichenDataStructure, LichenIntBasics, PrintTV, Rope, SetBasics;
LichenWireMunging: CEDAR PROGRAM
IMPORTS AbSets, BiRelBasics, BiRels, IntStuff, LichenDataOps, LichenDataStructure, SetBasics
EXPORTS LichenDataOps
=
BEGIN OPEN IS:IntStuff, LIB:LichenIntBasics, LIB, LichenDataStructure, LichenDataOps, Sets:AbSets;
steppyNameFunctions: Sets.Space ~ BiRelBasics.CreateBiRelSpace[ALL[steppyNameSpace]];
FixInterleavingsOfArray: PUBLIC PROC [act: CellType] ~ {
a: Array ~ act.asArray;
d: Design ~ act.d;
ect: CellType ~ act.EltType[];
wire2ap: InvFn --DumbWire ← array Port-- ~ a.dumrep.apToWire.Invert;
CheckEltPort: PROC [epv: Sets.Value] RETURNS [BOOL] ~ {
ep: Port ~ NARROW[epv.VA];
cai2dw: Fn--composite array index b DumbWire-- ~ BiRels.VB[a.dumrep.epToWire.Apply[epv].Val];
cais: Set--of composite array index-- ~ cai2dw.SetOn[left];
IF cais.Size[IS.two].Compare[IS.two]<equal THEN RETURN [FALSE];
{cai0: CompositeArrayIndex ~ cais.First[].MI;
cai1: CompositeArrayIndex ~ cais.Next[IV[cai0]].MI;
cainm1: CompositeArrayIndex ~ cais.Last[].MI;
caid: CompositeArrayIndex ~ cai1 - cai0;
estCais: Set--of int-- ~ Sets.Mods[[cai0, cainm1], caid, cai0];
IF NOT cais.Equal[estCais] THEN RETURN [FALSE];
{n: NATURAL ~ (cainm1 - cai0) / caid + 1;
cai2ap: Fn--cai b array port-- ~ CreateVector[bounds: cais.GetIntBounds, oneToOne: TRUE, rightSpace: d.eSpace];
hads: BiRels.HadSetPair ~ cai2ap.AddSet[ cai2dw.Compose[wire2ap] ];
IF hads # ALL[[same: FALSE, different: FALSE, none: TRUE]] THEN RETURN [FALSE];
IF cai2ap.Size.EN # n THEN RETURN [FALSE];
{cPorts: Set ~ cai2ap.SetOn[right];
pPorts: Set ~ d.parent.Image[cPorts].CreateHashCopy[];
IF pPorts.Size[IS.two].Compare[IS.two] < equal THEN RETURN [FALSE];
IF NOT d.parent.Image[pPorts, rightToLeft].Equal[cPorts] THEN RETURN [FALSE];
{apKids: Seq ~ cai2ap .Shift[IS.IE[-INT[cai0]]] .CreateVectorCopy[];
[] ← RestructurePorts[act, pPorts, apKids];
RETURN [FALSE]}}}}};
IF d.cct[p].ScanMapping[AV[ect], CheckEltPort, rightToLeft].found THEN ERROR;
RETURN};
RestructurePorts: PROC [ct: CellType, ports: Set--of Port--, newKids: Seq--of Port--] RETURNS [new: Port] ~ {
d: Design ~ ct.d;
nPorts: LNAT ~ ports.Size[].EN;
FixWire: PROC [wv: Sets.Value] RETURNS [BOOL] ~ {
w: Wire ~ NARROW[wv.VA];
[] ← w.conns.DeleteSet[ports];
RETURN [FALSE]};
FixInst: PROC [civ: Sets.Value] RETURNS [BOOL] ~ {
ci: CellInstance ~ NARROW[civ.VA];
cct: CellType ~ d.CiCct[ci];
wires: Set--of Wire-- ~ Sets.CreateHashSet[d.eSpace];
someBad: BOOLFALSE;
ProjectPort: PROC [pv: Sets.Value] RETURNS [BOOL] ~ {
wmv: Sets.MaybeValue ~ ci.conns.Apply[pv];
IF NOT wmv.found THEN RETURN [FALSE];
[] ← wires.AddElt[wmv.it];
{w: Wire ~ NARROW[wmv.it.VA];
someBad ← someBad OR NOT d.Top[w];
IF d.Atomic[w] THEN ERROR --atomic wire connected to composite port--;
RETURN [FALSE]}};
IF ports.Scan[ProjectPort].found THEN ERROR;
IF wires.Size[].EN=nPorts AND NOT someBad THEN {
kidWires: Seq ~ newKids.Compose[ci.conns, [TRUE, FALSE]];
[] ← RestructureWires[cct, wires, kidWires];
ct ← ct}
ELSE {
IF wires.Scan[FixWire].found THEN ERROR;
[] ← ci.conns.DeleteSet[ports]};
RETURN [FALSE]};
IF NOT newKids.SetOn[right].Equal[d.parent.Image[ports, rightToLeft]] THEN ERROR;
IF NOT ports.Intersection[d.isntTop].Empty THEN ERROR;
IF NOT ports.Intersection[d.isAtomic].Empty THEN ERROR;
IF NOT ct.CtArrays.Empty THEN ERROR--not implemented case--;
{parentNames: Set ~ FixNames[ct, p, ports, newKids];
DeletePorts[ct, ports, FALSE, FALSE];
new ← CreatePort[ct, parentNames, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, newKids];
IF d.ciType.ScanMapping[AV[ct], FixInst, rightToLeft].found THEN ERROR;
RETURN}};
RestructureWires: PROC [ct: CellType, wires: Set, newKids: Seq] RETURNS [new: Wire] ~ {
d: Design ~ ct.d;
nParents: LNAT ~ wires.Size[].EN;
nKids: LNAT ~ newKids.Size[].EN;
IF NOT newKids.SetOn[right].Equal[d.parent.Image[wires, rightToLeft]] THEN ERROR;
IF NOT wires.Intersection[d.isntTop].Empty THEN ERROR;
IF NOT wires.Intersection[d.isAtomic].Empty THEN ERROR;
IF ct.asArray#NIL THEN ERROR;
IF ct.asu=NIL THEN ERROR;
{ports: Set--of Wire-- ~ ct.asu.exports.Image[wires, rightToLeft].CreateHashCopy[];
parentNames: Set ~ FixNames[ct, w, wires, newKids];
DeleteWires[ct, wires, TRUE];
new ← CreateWire[ct, parentNames, TRUE, TRUE, TRUE, newKids];
IF ports.Size[].EN=nParents AND ports.Intersection[d.isntTop].Empty THEN {
rawKids: BiRel ~ newKids.Compose[ct.asu.exports.Invert];
kidPorts: Seq ~ CreateSeq[len: rawKids.Size.EN, oneToOne: TRUE, rightSpace: d.eSpace];
had: BiRels.HadSetPair ~ kidPorts.AddSet[rawKids];
IF had=ALL[[same: FALSE, different: FALSE, none: TRUE]] AND kidPorts.Size.EN = nKids THEN {
[] ← RestructurePorts[ct, ports, kidPorts];
ct ← ct;
}
ELSE new ← new;
ct ← ct}
ELSE new ← new;
RETURN}};
FixNames: PROC [ct: CellType, class: PWClass, olds: Set--of PW--, newKids: Seq] RETURNS [parentNames: Set--of SteppyName--] ~ {
n: NATURAL ~ newKids.Size.EN;
p2r: Fn--pattern b OTO(old name é new)-- ~ BiRels.CreateHashFn[spaces: [steppyNameSpace, steppyNameFunctions], invable: FALSE];
p2n: Fn--pattern b parent name-- ~ BiRels.CreateHashFn[ALL[steppyNameSpace], FALSE];
pats: Set--of SteppyNamePattern-- ~ p2r.SetOn[left];
k0: PW ~ newKids.ApplyI[0].MA;
k1: PW ~ newKids.ApplyI[1].MA;
ns0: Set ~ ct.PartNames[class, k0];
ns1: Set ~ ct.PartNames[class, k1];
Start0: PROC [v0: Sets.Value] RETURNS [BOOL] ~ {
n0: SteppyName ~ VSn[v0];
len: NATURAL ~ n0.grade.nonsubs+n0.grade.subs;
IF n0.grade.nonsubs < 1 OR n0.grade.subs < 1 OR len < 3 THEN RETURN [FALSE];
{tail0: NameStepList ~ n0.SNthTail[len-1].steps;
last0: REF INT ~ WITH tail0.first SELECT FROM
x: REF INT => x, ENDCASE => NIL;
Start1: PROC [v1: Sets.Value] RETURNS [BOOL] ~ {
n1: SteppyName ~ VSn[v1];
IF n1.grade # n0.grade THEN RETURN [FALSE];
{tail1: NameStepList ~ n1.SNthTail[len-1].steps;
last1: REF INT ~ WITH tail1.first SELECT FROM
x: REF INT => x, ENDCASE => NIL;
IF last1=NIL THEN RETURN [FALSE];
{sameLast: BOOL ~ last0^ = last1^;
d0: NameStepList ← n0.steps;
d1: NameStepList ← n1.steps;
WHILE d0 # tail0 AND nameStepSpace.SEqual[AV[d0.first], AV[d1.first]] DO
d0 ← d0.rest; d1 ← d1.rest; ENDLOOP;
IF d0#tail0 THEN {
IF NOT NameStepListEqual[d0.rest, d1.rest, tail0, tail1] THEN RETURN [FALSE];
ConsiderPattern[CopyTill[n0.steps, d0], CopyTill[d0.rest, tail0]];
}
ELSE IF NOT sameLast THEN {ct ← ct;
FOR l0: NameStepList ← n0.steps, l0.rest WHILE l0 # tail0 DO
ConsiderPattern[CopyTill[n0.steps, l0], CopyTill[l0.rest, tail0]];
ENDLOOP;
ct ← ct}
ELSE ct ← ct;
RETURN [FALSE]}}};
IF last0=NIL THEN RETURN [FALSE];
IF ns1.Scan[Start1].found THEN ERROR;
RETURN [FALSE]}};
ConsiderPattern: PROC [pre, post: TList] ~ {
base: SteppyName ~ LSn[CopyTill[pre.head, NIL].Cat[CopyTill[post.head, NIL]].head];
pat: SteppyNamePattern ~ LSn[Cat[Append[pre, anyROPE], Append[post, anyInt]].head];
r: OneToOne--old name é new-- ~ BiRels.CreateHashOTO[ALL[steppyNameSpace]];
pms: Set ~ matching.Mapping[SnV[pat]];
FOR i: NATURAL IN [0 .. n) DO
ki: PW ~ newKids.ApplyI[i].MA;
matchingNames: Set ~ pms.Intersection[ct.PartNames[class, ki]];
old: SteppyName ~ VSn[matchingNames.TheElt[!SetBasics.Error => IF msg=Sets.notASingleton THEN GOTO Bad]];
new: SteppyName ~ base.SNAppend[NewInt[i]];
had: BiRels.HadPair ~ r.AddPair[[SnV[old], SnV[new]]];
IF had # ALL[none] THEN GOTO Bad;
ENDLOOP;
{had: BiRels.Had ~ p2r.AddPair[[SnV[pat], r.BV[]], BiRels.addIfNew] [leftToRight];
IF had = different THEN ERROR--if it's the same pattern, it's got to have the same r--;
IF p2n.AddPair[[SnV[pat], SnV[base]]][leftToRight] = different THEN ERROR;
};RETURN;
EXITS Bad => ct ← ct};
RemoveInferiors: PROC [pv: Sets.Value] RETURNS [BOOL] ~ {
IF pats.HasMember[pv] THEN {
losers: Set ~ difoverlap.Mapping[pv].Intersection[pats].CreateHashCopy[];
[] ← p2r.DeleteSet[losers];
[] ← p2n.DeleteSet[losers]};
RETURN [FALSE]};
IF ns0.Scan[Start0].found THEN ERROR;
IF pats.Size.EN > 1 THEN nontrivs ← nontrivs + 1;
IF pats.Scan[RemoveInferiors, patorder].found THEN ERROR;
IF pats.Empty THEN {SIGNAL Hard; nhards ← nhards + 1}
ELSE FOR i: NAT IN [0 .. n) DO
ki: PW ~ newKids.ApplyI[i].MA;
ri: REF INT ~ NewInt[i];
PerRepl: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ {
pat: SteppyName ~ VSn[pair[left]];
r: OneToOne--old name é new-- ~ BiRels.VB[pair[right]];
parentName: SteppyName ~ VSn[p2n.Apply[pair[left]].Val];
new: SteppyName ~ SNAppend[parentName, ri];
old: SteppyName ~ VSn[r.Apply[SnV[new], rightToLeft].Val];
ReplaceDescendantsName[ct, ki, old, new];
RETURN [FALSE]};
IF p2r.Scan[PerRepl].found THEN ERROR;
ENDLOOP;
RETURN [p2n.SetOn[right]]};
sighard: BOOLTRUE;
nhards, nontrivs: INT ← 0;
Hard: SIGNAL ~ CODE;
patorder: Sets.Order ~ [ComparePats, TRUE, FALSE, NIL];
ComparePats: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [SetBasics.PartialComparison] ~ {
l1: NameStepList ← VSn[v1].steps;
l2: NameStepList ← VSn[v2].steps;
WHILE l1#NIL AND l2#NIL DO
e1: BOOL ~ l1.first=anyROPE;
e2: BOOL ~ l2.first=anyROPE;
IF e1#e2 THEN RETURN [IF e2 THEN less ELSE greater];
IF e1 THEN RETURN [equal];
l1 ← l1.rest;
l2 ← l2.rest;
ENDLOOP;
ERROR};
END.