<> <> DIRECTORY AbSets, BiRelBasics, BiRels, IntStuff, LichenArrayPrivate, LichenDataOps, LichenDataStructure, LichenIntBasics, Rope, SetBasics; LichenFlatGroup: CEDAR PROGRAM IMPORTS AbSets, BiRelBasics, BiRels, IntStuff, LichenArrayPrivate, LichenDataOps, LichenDataStructure, LichenIntBasics, Rope, SetBasics EXPORTS LichenDataOps = BEGIN OPEN IS:IntStuff, LIB:LichenIntBasics, LIB, LichenDataStructure, LichenDataOps, Sets:AbSets; ExpandType: PUBLIC PROC [d: Design, ct: CellType] ~ { ExpInst: PROC [civ: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ NARROW[civ.VA]; ExpandInstance[d, ci]; RETURN [FALSE]}; IF ct.asArray#NIL AND ct.asu=NIL THEN UnorganizeArray[ct]; IF d.ciType.ScanMapping[AV[ct], ExpInst, rightToLeft].found THEN ERROR; RETURN}; ExpandInstance: PUBLIC PROC [d: Design, ci: CellInstance] ~ { ict: CellType ~ d.CiT[ci]; cct: CellType ~ d.CiCct[ci]; privates: Set ~ ict.CTParts[w] .Difference[d.ancest.Image[ict.asu.publics]] .CreateHashCopy[]; wireWas: OneToOne ~ CopyPWStructure[ict, cct, w, privates, cct.INames[ci]]; newWires: Set ~ wireWas.SetOn[left]; oldCis: Set ~ ict.CTParts[i]; wireAttached: BiRel ~ ci.conns.Invert.Compose[ict.asu.exports]; ageWire: BiRel ~ wireWas.Union[b: wireAttached, disjoint: TRUE]; ciWas: OneToOne ~ CopyInstStructure[ict, cct, oldCis, cct.INames[ci], ageWire, IF d.ciXfm#nilBiRel THEN VXfm[d.ciXfm.ApplyA[ci].Val] ELSE [], ci.offset]; newCis: Set ~ ciWas.SetOn[left]; DeleteInsts[d, Sets.CreateSingleA[ci, d.eSpace], TRUE]; IF ict.Unused[] THEN DeleteCellType[ict, NIL]; RETURN}; GroupInstancesToNewCT: PROC [d: Design, cis: Set, iName, tName: ROPE] RETURNS [newCT: CellType, newCI: CellInstance] ~ { cct: CellType ~ NARROW[d.cct[i].Image[cis].TheElt.VA]; conndWires: Set ~ d.iwConns.Image[cis].CreateHashCopy[]; conndRoots: Set ~ d.toRoot.Image[conndWires].CreateHashCopy[]; relatedWires: Set ~ d.ancest.Image[conndRoots, rightToLeft].CreateHashCopy[]; otherCis: Set ~ cct.CTParts[i].Difference[cis]; otherConndWires: Set ~ d.iwConns.Image[otherCis] .Union[cct.asu.exports.SetOn[right]] .CreateHashCopy[]; otherRoots: Set ~ d.toRoot.Image[otherConndWires].CreateHashCopy[]; splitRoots: Set ~ conndRoots.Intersection[otherRoots].CreateHashCopy[]; pvtRoots: Set ~ conndRoots.Difference[otherRoots].CreateHashCopy[]; splitWires: Set ~ d.ancest.Image[splitRoots, rightToLeft].CreateHashCopy[]; pvtWires: Set ~ d.ancest.Image[pvtRoots, rightToLeft].CreateHashCopy[]; newCT _ CreateCellType[d, unorganized, fullRange2, OneRope[tName]]; {wireWas: OneToOne ~ CopyPWStructure[cct, newCT, w, relatedWires, nilSet]; ciWas: OneToOne ~ CopyInstStructure[cct, newCT, cis, nilSet, wireWas, [], ALL[0]]; Exportit: PROC [owv: Sets.Value] RETURNS [BOOL] ~ { nw: Wire ~ NARROW[wireWas.InvApply[owv].MA]; p: Port ~ PortForWire[newCT, nw, TRUE]; IF p=NIL THEN ERROR; RETURN [FALSE]}; Connectit: PROC [owv: Sets.Value] RETURNS [BOOL] ~ { ow: Wire ~ NARROW[owv.VA]; nw: Wire ~ NARROW[wireWas.InvApply[owv].MA]; p: Port ~ PortForWire[newCT, nw, FALSE]; IF p=NIL THEN ERROR; Connect[d, ow, p, newCI]; RETURN [FALSE]}; IF splitWires.Scan[Exportit].found THEN ERROR; newCI _ Instantiate[newCT, cct, FALSE, [], ALL[0], OneOSn[iName]]; IF splitWires.Scan[Connectit].found THEN ERROR; DeleteInsts[d, cis, TRUE]; DeleteWires[cct, pvtWires, FALSE]; RETURN}}; SplitUnorganized: PROC [d: Design, take: Set--of CellInstance--] RETURNS [from, to: CellType] ~ { from _ NARROW[d.cct[i].Image[take].TheElt.VA]; IF NOT d.arrayElt.MappingEmpty[AV[from], rightToLeft] THEN ERROR nyet; {takename: SteppyName ~ VSn[from.fullName[i].Image[take].First[].Val]; fix: OneToOne ~ BiRels.CreateRopeCat[Rope.Cat["-", takename.UnparseSteppyName], suffix]; to _ CreateCellType[d, unorganized, emptyRange2, fix.Image[d.CTNames[from]]]; {allcis: Set ~ from.Subcells[]; keep: Set ~ allcis.Difference[take].CreateHashCopy[]; tw: Set ~ d.iwConns.Image[take]; kw: Set ~ d.iwConns.Image[keep]; twRoots: Set ~ d.toRoot.Image[tw].CreateHashCopy[]; kwRoots: Set ~ d.toRoot.Image[kw].CreateHashCopy[]; twForest: Set ~ d.toRoot.Image[twRoots, rightToLeft].CreateHashCopy[]; kwForest: Set ~ d.toRoot.Image[kwRoots, rightToLeft].CreateHashCopy[]; dwForest: Set ~ from.CTParts[w].Difference[kwForest].CreateHashCopy[]; bw: Set ~ tw.Intersection[kw]; bwRoots: Set ~ d.toRoot.Image[bw].CreateHashCopy[]; bwForest: Set ~ d.toRoot.Image[bwRoots, rightToLeft].CreateHashCopy[]; npbwForest: Set ~ bwForest .Difference[from.asu.publics] .CreateHashCopy[]; [] _ FullySfwdlyExportWires[from, npbwForest]; IF NOT npbwForest.Subset[from.asu.publics] THEN ERROR; {tp: Set ~ from.asu.exports.Image[twForest, rightToLeft]; kp: Set ~ from.asu.exports.Image[kwForest, rightToLeft]; tpRoots: Set ~ d.toRoot.Image[tp].CreateHashCopy[]; kpRoots: Set ~ d.toRoot.Image[kp].CreateHashCopy[]; tpForest: Set ~ d.toRoot.Image[tpRoots, rightToLeft].CreateHashCopy[]; kpForest: Set ~ d.toRoot.Image[kpRoots, rightToLeft].CreateHashCopy[]; dpForest: Set ~ from.CTParts[p].Difference[kpForest].CreateHashCopy[]; portWas: OneToOne ~ CopyPWStructure[from, to, p, tpForest, nilSet]; wireWas: OneToOne ~ CopyPWStructure[from, to, w, twForest, nilSet]; ciWas: OneToOne ~ CopyInstStructure[from, to, take, nilSet, wireWas, [], ALL[0]]; FixInst: PROC [ociv: Sets.Value] RETURNS [BOOL] ~ { oci: CellInstance ~ NARROW[ociv.VA]; cct: CellType ~ d.CiCct[oci]; nci: CellInstance ~ Instantiate[to, cct, FALSE, [], oci.offset, cct.INames[oci]]; ConnectPWs[d, portWas.Compose[oci.conns], nci]; RETURN [FALSE]}; ConnectPWs[d, portWas.Compose[from.asu.exports.Compose[wireWas.Invert]], to]; IF d.ciType.ScanMapping[AV[from], FixInst, rightToLeft].found THEN ERROR; DeletePorts[from, dpForest, TRUE, FALSE]; DeleteWires[from, dwForest, TRUE]; DeleteInsts[d, take, TRUE]; RETURN}}}}; CopyPWStructure: PROC [fromCT, toCT: CellType, class: PWClass, olds, cins: Set] RETURNS [was: OneToOne] ~ { d: Design ~ fromCT.d; lab: BOOL ~ d.labelCellTypes.HasMemA[fromCT]; simpleNames: BOOL ~ cins=nilSet; MoveWire: PROC [opwv: Sets.Value] RETURNS [BOOL] ~ { IF was.HasMapping[opwv, rightToLeft] THEN RETURN [FALSE]; {opw: PW ~ NARROW[opwv.VA]; atomic: BOOL ~ d.Atomic[opw]; oNames: Set ~ fromCT.PartNames[class, opw]; fullNames: Set ~ IF simpleNames THEN oNames ELSE IF d.inheritNames THEN ActualNames[lab, cins, oNames] ELSE emptySteppySet; nkids: Seq _ nilBiRel; npw: PW _ NIL; IF NOT atomic THEN { okids: Seq ~ d.SubSeq[opw]; n: NAT ~ okids.Size.EN; nkids _ CreateSeq[len: n, oneToOne: TRUE, dense: TRUE, rightSpace: d.eSpace]; FOR i: NAT IN [0 .. n) DO okid: PW ~ NARROW[okids.ApplyI[i].MA]; IF MoveWire[[okid]] THEN ERROR; nkids.AddNewIA[i, was.InvApplyA[okid].MA]; ENDLOOP; nkids _ nkids}; SELECT class FROM p => npw _ CreatePort[toCT, fullNames, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, nkids]; w => npw _ CreateWire[toCT, fullNames, FALSE, FALSE, FALSE, nkids]; ENDCASE => ERROR; was.AddNewAA[npw, opw]; RETURN [FALSE]}}; was _ BiRels.CreateHashOTO[ALL[d.eSpace]]; IF olds.Scan[MoveWire].found THEN ERROR; RETURN}; CopyInstStructure: PROC [fromCT, toCT: CellType, oldCis, cins: Set, ageWire: BiRel, xf: Transform, ofst: Int2] RETURNS [ciWas: OneToOne] ~ { d: Design ~ fromCT.d; simpleNames: BOOL ~ cins=nilSet; MoveInst: PROC [ociv: Sets.Value] RETURNS [BOOL] ~ { oci: CellInstance ~ NARROW[ociv.VA]; oct: CellType ~ d.CiT[oci]; oNames: Set ~ fromCT.INames[oci]; fullNames: Set ~ IF simpleNames THEN oNames ELSE IF d.inheritNames THEN ActualNames[FALSE, cins, oNames] ELSE emptySteppySet; xfm: Transform _ []; offset: Int2 _ dullInt2; IF d.ciXfm#nilBiRel THEN { t1: Transform ~ VXfm[d.ciXfm.ApplyA[oci].Val]; xfm _ t1.Compose[xf]; offset _ Add[ofst, t1.TransformVector[oci.offset]]}; {nci: CellInstance ~ Instantiate[oct, toCT, FALSE, xfm, offset, fullNames]; MoveConnection: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { p: Port ~ NARROW[pair[left].VA]; wmv: Sets.MaybeValue ~ ageWire.InvApply[pair[right]]; IF wmv.found THEN Connect[d, NARROW[wmv.it.VA], p, nci] ELSE IF d.Atomic[p] THEN ERROR; RETURN [FALSE]}; ciWas.AddNewAA[nci, oci]; IF oci.conns.Scan[MoveConnection].found THEN ERROR; RETURN [FALSE]}}; ciWas _ BiRels.CreateHashOTO[ALL[d.eSpace]]; IF oldCis.Scan[MoveInst].found THEN ERROR; RETURN}; Differentiate: PUBLIC PROC [d: Design, cis: Set] RETURNS [new: CellType] ~ { old: CellType ~ NARROW[d.ciType.Image[cis].TheElt.VA]; portAssoc: OneToOne--old Port portInv: OneToOne--new Port FixInst: PROC [civ: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ NARROW[civ.VA]; FixWire: PROC [wv: Sets.Value] RETURNS [BOOL] ~ { w: Wire ~ NARROW[wv.VA]; oPorts: Set ~ w.conns.Mapping[civ, rightToLeft]; nPorts: Set ~ portAssoc.Image[oPorts].CreateHashCopy[]; IF NOT w.conns.Delete[civ, right] THEN ERROR; [] _ w.conns.AddSet[BiRels.CreateProduct[[nPorts, Sets.CreateSingleton[civ, d.eSpace]]]]; RETURN [FALSE]}; [] _ d.ciType.AddAA[ci, new]; {newConns: Fn ~ portInv.Compose[ci.conns, [FALSE,TRUE]].CreateHashCopy[]; IF ci.conns.SetOn[right].Scan[FixWire].found THEN ERROR; [] _ ci.conns.Erase[]; [] _ ci.conns.AddSet[newConns]; RETURN [FALSE]}}; [new, portInv] _ CopyCellType[old]; portAssoc _ portInv.Invert; IF cis.Scan[FixInst].found THEN ERROR; RETURN}; CopyCellType: PROC [oct: CellType] RETURNS [nct: CellType, portInv: OneToOne] ~ { d: Design ~ oct.d; flavor: CellFlavor ~ SELECT TRUE FROM oct.asTrans # NIL => leaf, oct.asArray # NIL => array, oct.asu # NIL => unorganized, ENDCASE => ERROR; nct _ CreateCellType[d, flavor, oct.bbox, d.CTNames[oct]]; portInv _ CopyPWStructure[oct, nct, p, oct.CTParts[p], nilSet]; IF flavor=unorganized THEN { wireWas: OneToOne ~ CopyPWStructure[oct, nct, p, oct.CTParts[w], nilSet]; ciWas: OneToOne ~ CopyInstStructure[oct, nct, oct.CTParts[w], nilSet, wireWas, [], ALL[0]]; ConnectPWs[d, portInv.Compose[oct.asu.exports.Compose[wireWas.Invert]], nct]; nct _ nct} ELSE IF flavor=array THEN { oa: Array ~ oct.asArray; ect: CellType ~ oct.EltType; na: Array ~ CreateArrayPart[nct, ect, oa.size2, oa.basePeriod, IF oa. CopyOffsets[oa.offsets]]; MoveEdge: PROC [sev: Sets.Value] RETURNS [BOOL] ~ { se: StatEdge ~ NARROW[sev.VA]; sep: StatEdgeSpec ~ se.SeSp[oa.statrep]; [] _ LichenArrayPrivate.AddStatEdge[d, na.statrep, sep]; RETURN [FALSE]}; IF oa.buildPhase # statrepFixed THEN ERROR; [] _ na.statrep.apToPAI.AddSet[portInv.Compose[oa.statrep.apToPAI, [FALSE, TRUE]]]; SetArrayPart[nct, ect, na]; FinishedMakingArrayConnections[nct]; nct _ nct} ELSE { nct.asTrans _ NEW [TransistorPrivate _ oct.asTrans^]; nct _ nct}; oct _ oct}; CopyOffsets: PROC [old: OffsetSeq] RETURNS [new: OffsetSeq] ~ { IF old=NIL THEN RETURN [NIL]; new _ NEW [OffsetSequence[old.length]]; FOR i: NAT IN [0 .. old.length) DO new[i] _ old[i] ENDLOOP; new _ new}; END.