<> <> 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 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. 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}; MergeCellTypes: PUBLIC PROC [d: Design, lost, kept: CellType, assoc: OneToOne] ~ { FixInst: PROC [civ: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ NARROW[civ.VA]; add: Fn--Port 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, 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.