LichenDataImpl3.Mesa
Last tweaked by Mike Spreitzer on April 13, 1989 5:03:17 pm PDT
DIRECTORY AbSets, AMBridge, AMTypes, BasicTime, BiRels, IntStuff, IO, LichenDataOps, LichenDataStructure, LichenIntBasics, PrintTV, Rope, SetBasics;
LichenDataImpl3: CEDAR PROGRAM
IMPORTS AbSets, BiRels, IntStuff, LichenDataOps, LichenDataStructure, LichenIntBasics, SetBasics
EXPORTS LichenDataOps
=
BEGIN OPEN LIB:LichenIntBasics, LIB, LichenDataStructure, LichenDataOps, Sets:AbSets;
ForgetUnorganized: PUBLIC PROC [ct: CellType] ~ {
IF ct.asArray=NIL THEN ERROR;
IF ct.asu=NIL THEN RETURN;
{wires: Set ~ ct.CTParts[w];
insts: Set ~ ct.CTParts[i];
SmashVertex: PROC [vv: Sets.Value] RETURNS [BOOL] ~ {
WITH vv.VA SELECT FROM
w: Wire => w.conns ← nilBiRel;
ci: CellInstance => ci.conns ← nilBiRel;
ENDCASE => ERROR;
RETURN [FALSE]};
IF wires.Scan[SmashVertex].found THEN ERROR;
IF insts.Scan[SmashVertex].found THEN ERROR;
[] ← ct.d.sub.DeleteSet[wires];
[] ← ct.d.sub.DeleteSet[insts];
[] ← ct.d.parent.DeleteSet[wires];
[] ← ct.d.ciType.DeleteSet[insts];
IF ct.d.physd THEN [] ← ct.d.ciXfm.DeleteSet[insts];
[] ← ct.d.cct[w].DeleteA[ct, right];
[] ← ct.d.cct[i].DeleteA[ct, right];
ct.asu.exports ← nilBiRel;
ct.asu ← NIL;
ct.fullName[w] ← ct.fullName[i] ← nilBiRel;
RETURN}};
ForgetArray: PUBLIC PROC [act: CellType] ~ {
IF NOT act.d.arrayElt.DeleteA[act] THEN ERROR;
act.asArray ← NIL;
RETURN};
OffsetsFromList: PUBLIC PROC [list: OffsetPatList] RETURNS [seq: OffsetSeq] ~ {
len: NATURAL ← 0;
FOR l: OffsetPatList ← list, l.rest WHILE l # NIL DO len ← len + 1 ENDLOOP;
seq ← NEW [OffsetSequence[len]];
FOR i: NATURAL IN [0 .. len) DO
seq[i] ← list.first;
list ← list.rest;
ENDLOOP;
IF list#NIL THEN ERROR};
CTIncludesPoint: PUBLIC PROC [ct: CellType, pt: Int2] ~ {
IF NOT ct.d.physd THEN ERROR;
ct.bbox ← Range2Mbb[ct.bbox, [[pt[X], pt[X]+1], [pt[Y], pt[Y]+1]]];
RETURN};
DesignScaleIs: PUBLIC PROC [d: Design, scale: REAL] ~ {
IF d.scale=0.0 THEN d.scale ← scale ELSE IF d.scale#scale THEN ERROR;
RETURN};
MergeWireSet: PUBLIC PROC [d: Design, wires: Set, callerWillTakeCareOfPorts: BOOL] RETURNS [kept: Wire, lost: Set] ~ {
PerWire: PROC [wv: Sets.Value] RETURNS [BOOL] ~ {
w: Wire ~ NARROW[wv.VA];
IF kept=NIL THEN kept ← w ELSE kept ← MergeNets[d, kept, w, callerWillTakeCareOfPorts].merged;
IF kept=NIL THEN ERROR;
RETURN [FALSE]};
kept ← NIL;
IF wires.Scan[PerWire].found THEN ERROR;
lost ← wires.Difference[Sets.CreateSingleA[kept, d.eSpace]];
RETURN};
MergeNets: PUBLIC PROC [d: Design, w1, w2: Wire, callerWillTakeCareOfPorts: BOOL] RETURNS [merged, deleted: Wire] ~ {
ct: CellType ~ d.WCct[w1];
Work: PROC [merged, deleted: Wire] ~ {
atomic: BOOL ~ d.Atomic[merged];
SwitchConn: PROC [cell: REF ANY] ~ {
WITH cell SELECT FROM
ci: CellInstance => ci.conns.SubstituteA[deleted, merged, right];
cct: CellType => IF ct # cct THEN ERROR;
ENDCASE => ERROR};
IF merged=deleted THEN ERROR;
IF atomic # d.Atomic[deleted] THEN ERROR;
IF (NOT callerWillTakeCareOfPorts) AND (ct.asu.publics.HasMemA[merged] OR ct.asu.publics.HasMemA[deleted]) THEN ERROR;
KnowPartNames[ct, w, merged, ct.WNames[deleted], TRUE];
IF NOT d.cct[w].DeleteA[deleted] THEN ERROR;
ct.asu.exports.SubstituteA[deleted, merged, right];
deleted.conns.SetOn[right].EnumA[SwitchConn];
[] ← merged.conns.AddSet[deleted.conns];
IF NOT atomic THEN {
mSub: Seq ~ d.SubSeq[merged];
dSub: Seq ~ d.SubSeq[deleted];
n: NAT ~ mSub.Size.EN;
IF n # dSub.Size.EN THEN ERROR;
FOR i: NAT IN [0 .. n) DO
mKid: Wire ~ NARROW[mSub.ApplyI[i].MA];
dKid: Wire ~ NARROW[dSub.ApplyI[i].MA];
Work[mKid, dKid];
d ← d; ENDLOOP;
IF NOT d.sub.DeleteA[deleted] THEN ERROR;
IF NOT d.parent.DeleteA[deleted, right] THEN ERROR;
d ← d};
[] ← ct.fullName[w].DeleteA[deleted, left];
RETURN};
IF ct # d.WCct[w2] THEN ERROR;
IF d.isntTop.HasMemA[w1] OR d.isntTop.HasMemA[w2] THEN ERROR;
merged ← w1;
deleted ← w2;
Work[merged, deleted];
RETURN};
MergePorts: PUBLIC PROC [ct: CellType, ports: Set] RETURNS [kept: Port, lost: Set] ~ {
d: Design ~ ct.d;
Work: PROC [kept: Port, lost, all: Set] ~ {
atomic: BOOL ~ d.Atomic[kept];
ReplaceLoser: PROC [lv: Sets.Value] RETURNS [BOOL] ~ {
loser: Port ~ NARROW[lv.VA];
IF atomic # d.Atomic[loser] THEN ERROR;
KnowPartNames[ct, p, kept, ct.PNames[loser], TRUE];
[] ← ct.fullName[p].DeleteA[loser, left];
RETURN [FALSE]};
FixInst: PROC [civ: Sets.Value] RETURNS [BOOL] ~ {
ci: CellInstance ~ NARROW[civ.VA];
w: Wire ~ NARROW[ci.conns.Image[all].TheElt.VA];
[] ← w.conns.DeleteSet[lost];
IF (NOT ci.conns.DeleteSet[lost].had.all) AND atomic THEN ERROR;
RETURN [FALSE]};
NoteEltPortMerge[ct, kept, lost];
IF ct.CtInsts[].Scan[FixInst].found THEN ERROR;
IF lost.Scan[ReplaceLoser].found THEN ERROR;
IF NOT atomic THEN {
kSubs: Seq ~ d.SubSeq[kept];
n: NAT ~ kSubs.Size.EN;
FOR i: NAT IN [0 .. n) DO
kKid: Port ~ NARROW[kSubs.ApplyI[i].MA];
lKids: Set ~ Sets.CreateHashSet[d.eSpace];
aKids: Set ~ lKids.Union[b: Sets.CreateSingleA[kKid, d.eSpace], disjoint: TRUE];
AddLostKid: PROC [lv: Sets.Value] RETURNS [BOOL] ~ {
loser: Port ~ NARROW[lv.VA];
lSubs: Seq ~ d.SubSeq[loser];
lKid: Port ~ NARROW[lSubs.ApplyI[i].MA];
IF lKid = kKid THEN ERROR;
IF NOT lKids.AddA[lKid] THEN ERROR;
RETURN [FALSE]};
IF lost.Scan[AddLostKid].found THEN ERROR;
Work[kKid, lKids, aKids];
ENDLOOP;
[] ← d.sub.DeleteSet[lost];
[] ← d.parent.DeleteSet[lost, right];
ct ← ct};
IF NOT d.cct[p].DeleteSet[lost].had.all THEN ERROR;
IF ct.asu#NIL THEN {
w: Wire ~ NARROW[ct.asu.exports.Image[all].TheElt.VA];
IF (NOT w.conns.DeleteSet[lost].had.all) AND atomic THEN ERROR;
IF (NOT ct.asu.exports.DeleteSet[lost].had.all) AND atomic THEN ERROR};
IF ct.asArray#NIL THEN {
a: Array ~ ct.asArray;
dw: DumbWire ~ NARROW[a.dumrep.apToWire.Image[all].TheElt.VA];
IF a.buildPhase # statrepFixed THEN ERROR;
IF (NOT a.statrep.apToPAI.DeleteSet[lost].had.all) AND atomic THEN ERROR;
IF (NOT a.dumrep.apToWire.DeleteSet[lost].had.all) AND atomic THEN ERROR};
RETURN};
IF NOT ports.Subset[d.isTop] THEN ERROR;
kept ← NARROW[ports.AnElt.MA];
lost ← ports.Difference[Sets.CreateSingleA[kept, d.eSpace]];
IF lost.Empty THEN RETURN;
Work[kept, lost, ports];
RETURN};
ReplaceDescendantsName: PUBLIC PROC [ct: CellType, subroot: PW, old, new: SteppyName] ~ {
ReplaceDescendantsNameX[ct, subroot, old, OneSteppy[new]];
RETURN};
ReplaceDescendantsNames: PUBLIC PROC [ct: CellType, subroot: PW, oldNew: BiRel--old SteppyName new--] ~ {
PerOld: PROC [ov: Sets.Value] RETURNS [BOOL] ~ {
new: Set--of SteppyName-- ~ oldNew.Mapping[ov];
ReplaceDescendantsNameX[ct, subroot, VSn[ov], new];
RETURN [FALSE]};
IF oldNew.SetOn[left].Scan[PerOld].found THEN ERROR;
RETURN};
ReplaceDescendantsNameX: PROC [ct: CellType, subroot: PW, old: SteppyName, new: Set] ~ {
d: Design ~ ct.d; --&msg["\n\t", old.steps, " -> ", new.steps]
class: PWClass ~ ClassOfPart[subroot];
RenameDescendant: PROC [desv: Sets.Value] ~ {
PerName: PROC [onv: Sets.Value] ~ {
on: SteppyName ~ VSn[onv];
ms: MaybeSteppyName ~ SteppyIsPrefix[old, on];
PerNew: PROC [val: Sets.Value] RETURNS [BOOL] ~ {
nn: SteppyName ~ SNCat[VSn[val], ms.it];
ForgetPartName[ct, class, desv.VA, on];
KnowPartName[ct, class, desv.VA, nn, FALSE];
subroot ← subroot;
RETURN [FALSE]};
IF NOT ms.found THEN ct ← ct
ELSE IF new.Scan[PerNew].found THEN ERROR
ELSE ct ← ct;
RETURN};
ct.fullName[class].EnumerateMapping[desv, PerName, leftToRight];
RETURN--&msg["\n\t\t", AbSets.FormatSet[LichenDataImpl1B.ENames[d, desv.ra]]]--};
d.ancest.EnumerateMapping[AV[subroot], RenameDescendant, rightToLeft];
RETURN};
DropPhysical: PUBLIC PROC [d: Design] ~ {
CTDrop: PROC [ctv: Sets.Value] RETURNS [BOOL] ~ {
ct: CellType ~ NARROW[ctv.VA];
SubcellDrop: PROC [civ: Sets.Value] RETURNS [BOOL] ~ {
ci: CellInstance ~ NARROW[civ.VA];
ci.offset ← dullInt2;
RETURN [FALSE]};
ct.bbox ← fullRange2;
IF ct.asu#NIL THEN IF ct.Subcells[].Scan[SubcellDrop].found THEN ERROR;
IF ct.asArray#NIL THEN {
a: Array ~ ct.asArray;
a.fXfm ← nilBiRel;
a.offsets ← NIL};
RETURN [FALSE]};
IF NOT d.physd THEN RETURN;
d.physd ← FALSE;
d.ciXfm ← nilBiRel;
d.scale ← 0.0;
IF d.cellTypes.Scan[CTDrop].found THEN ERROR;
RETURN};
UndistinguishCellTypes: PUBLIC PROC [d: Design, lost, kept: CellType, assoc: OneToOne] ~ {
FixInst: PROC [civ: Sets.Value] RETURNS [BOOL] ~ {
ci: CellInstance ~ NARROW[civ.VA];
add: Fn--Port b Wire-- ~ BiRels.CreateHashTable[ALL[d.eSpace]];
FixConnection: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ {
pl: Sets.Value ~ pair[left];
pk: Sets.Value ~ assoc.Apply[pl].Val;
w: Wire ~ NARROW[pair[right].VA];
add.AddNewPair[[pk, pair[right]]];
IF NOT ci.conns.RemPair[pair].had[leftToRight]=same THEN ERROR;
[] ← w.conns.RemPair[[pl, civ]];
[] ← w.conns.AddPair[[pk, civ]];
RETURN [FALSE]};
IF ci.conns.Scan[FixConnection].found THEN ERROR;
[] ← ci.conns.AddSet[add];
RETURN [FALSE]};
paiAssoc: OneToOne ~ BiRels.FnFromProc[PaiApply, ALL[SetBasics.reps], assoc.Refify, TRUE, TRUE];
FixArray: PROC [actv: Sets.Value] RETURNS [BOOL] ~ {
act: CellType ~ NARROW[actv.VA];
a: Array ~ act.asArray;
sr: StatRep ~ a.statrep;
dr: DumRep ~ a.dumrep;
FixDW: PROC [dwv: Sets.Value] RETURNS [BOOL] ~ {
dw: DumbWire ~ NARROW[dwv.VA];
dw.eps.SubstituteSet[assoc, left];
RETURN [FALSE]};
FOR b: BOOL IN BOOL DO
sr.portEdge[b].SubstituteSet[assoc, left];
sr.svEdge[b].SubstituteSet[paiAssoc, left];
ENDLOOP;
sr.apToPAI.SubstituteSet[paiAssoc, left];
dr.epToWire.SubstituteSet[assoc, left];
IF dr.wires.Scan[FixDW].found THEN ERROR;
RETURN [FALSE]};
IF lost.CtInsts[].Scan[FixInst].found THEN ERROR;
IF lost.CtArrays[].Scan[FixArray].found THEN ERROR;
d.ctName.Substitute[AV[lost], AV[kept], left];
d.ciType.Substitute[AV[lost], AV[kept], right];
d.arrayElt.Substitute[AV[lost], AV[kept], right];
IF d.crossedCellTypes.HasMemA[lost] THEN [] ← d.crossedCellTypes.AddA[kept];
DeleteCellType[lost, FALSE, NIL];
RETURN--caller has to worry about whether this constitutes crossing--};
PaiApply: PROC [data: REF ANY, v: Sets.Value] RETURNS [mv: Sets.MaybeValue] ~ {
assoc: OneToOne ~ BiRels.DeRef[data];
given: PortAtIndex ~ VPai[v];
mv ← assoc.ApplyA[given.port];
IF NOT mv.found THEN RETURN;
mv ← [TRUE, PaiV[[NARROW[mv.it.VA], given.ai]]];
RETURN};
END.