<> <> DIRECTORY AbSets, BiRelBasics, BiRels, IntStuff, IO, LichenArrayPrivate, LichenDataOps, LichenDataStructure, LichenIntBasics, Rope, SetBasics; LichenTranspose: CEDAR PROGRAM IMPORTS AbSets, BiRelBasics, BiRels, IO, LichenArrayPrivate, LichenDataOps, LichenDataStructure, LichenIntBasics, SetBasics = BEGIN OPEN IS:IntStuff, LIB:LichenIntBasics, LIB, LichenArrayPrivate, LichenDataStructure, LichenDataOps, Sets:AbSets; LowerArrayStructure: PROC [outer: CellType] ~ --AAASEP frees us from worrying about interference between parents & kids--{ d: Design ~ outer.d; mid: CellType ~ outer.EltType[]; elts: Set--of CellInstance-- ~ mid.Subcells[]; eltArrays: OneToOne--ci arrayInsts: OneToOne--inner ci oa: Array ~ outer.asArray; outerName: ROPE ~ outer.ACtName[]; CreateArrays: PROC [civ: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ NARROW[civ.VA]; ict: CellType ~ d.CiT[ci]; ciName: SteppyName ~ mid.BestIName[ci]; ictName: ROPE ~ ict.ACtName[]; act: CellType ~ CreateArray[d, ict, oa.size2, oa.basePeriod, nilBiRel, NIL, OneRope[IO.PutFR["%g-array(%g.%g)", [rope[ictName]], [rope[outerName]], [rope[ciName.UnparseSteppyName]] ]]]; aci: CellInstance ~ Instantiate[act, outer, FALSE, [], dullInt2, mid.INames[ci]]; eltArrays.AddNewAA[ci, act]; arrayInsts.AddNewAA[ci, aci]; RETURN [FALSE]}; MakeSelfEdges: PROC [wv: Sets.Value] RETURNS [BOOL] ~ { w: Wire ~ NARROW[wv.VA]; PerCell: PROC [cv: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ WITH cv.VA SELECT FROM x: CellInstance => x, x: CellType => NIL, ENDCASE => ERROR; IF ci=NIL THEN RETURN [FALSE]; {mct: CellType ~ NARROW[eltArrays.ApplyA[ci].MA]; ma: Array ~ mct.asArray; ports: Set ~ w.conns.MappingA[ci, rightToLeft]; lastSelfport: Port _ NIL; PerPort: PROC [pv: Sets.Value] RETURNS [BOOL] ~ { p: Port ~ NARROW[pv.VA]; IF lastSelfport#NIL THEN { sep: StatEdgeSpec ~ [vs: [[lastSelfport, ALL[0]], [p, ALL[0]]], [] _ EnsureStatEdge[d, ma.statrep, sep, TRUE, TRUE, FALSE]}; lastSelfport _ p; RETURN [FALSE]}; IF ports.Scan[PerPort].found THEN ERROR; RETURN [FALSE]}}; IF w.conns.SetOn[right].Scan[PerCell].found THEN ERROR; RETURN [FALSE]}; missedEdges: Set ~ Sets.CreateHashSet[oa.statrep.edgeSpace]; MakeDeltaEdges: PROC [osev: Sets.Value] RETURNS [BOOL] ~ { ose: StatEdge ~ NARROW[osev.VA]; opa: Port ~ SeP[ose, oa, FALSE]; opb: Port ~ SeP[ose, oa, TRUE]; wa: Wire ~ NARROW[mid.asu.exports.ApplyA[opa].MA]; wb: Wire ~ NARROW[mid.asu.exports.ApplyA[opb].MA]; cells: Set ~ wa.conns.SetOn[right].Intersection[ wb.conns.SetOn[right]]; some: BOOL _ FALSE; PerCell: PROC [cv: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ WITH cv.VA SELECT FROM x: CellInstance => x, x: CellType => NIL, ENDCASE => ERROR; IF ci=NIL THEN RETURN [FALSE]; {mct: CellType ~ NARROW[eltArrays.ApplyA[ci].MA]; ma: Array ~ mct.asArray; ipa: Port ~ NARROW[wa.conns.Lookup[goal: cv, order: Sets.alleq].MA]; ipb: Port ~ NARROW[wb.conns.Lookup[goal: cv, order: Sets.alleq].MA]; sep: StatEdgeSpec ~ [vs: [[ipa, ALL[0]], [ipb, ALL[0]]], [] _ EnsureStatEdge[d, ma.statrep, sep, TRUE, TRUE, FALSE]; some _ TRUE; RETURN [FALSE]}}; IF cells.Scan[PerCell].found THEN ERROR; IF NOT some THEN IF NOT missedEdges.AddElt[osev] THEN ERROR; RETURN [FALSE]}; Midway: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { mact: CellType ~ NARROW[pair[right].VA]; FinishedMakingArrayConnections[mact]; RETURN [FALSE]}; MakeSiblingEdges: PROC [wv: Sets.Value] RETURNS [BOOL] ~ { w: Wire ~ NARROW[wv.VA]; lastCI: CellInstance _ NIL; lastEP: Port _ NIL; lastArray: CellType _ NIL; lastACI: CellInstance _ NIL; nt: BOOL _ FALSE; PerCell: PROC [cv: Sets.Value] RETURNS [BOOL] ~ { ci: CellInstance ~ WITH cv.VA SELECT FROM x: CellInstance => x, x: CellType => NIL, ENDCASE => ERROR; IF ci=NIL THEN RETURN [FALSE]; {thisEP: Port ~ NARROW[w.conns.Lookup[goal: cv, order: Sets.alleq].MA]; thisArray: CellType ~ NARROW[eltArrays.Apply[cv].MA]; thisACI: CellInstance ~ NARROW[arrayInsts.Apply[cv].MA]; IF thisEP=NIL OR thisArray=NIL OR thisACI=NIL THEN ERROR; IF lastCI#NIL THEN { FOR aix: NATURAL IN [0 .. oa.size2[X]) DO FOR aiy: NATURAL IN [0 .. oa.size2[Y]) DO lastAP: Port ~ GetArrayPortForPort[lastArray, [aix, aiy], lastEP, TRUE, TRUE, FALSE]; thisAP: Port ~ GetArrayPortForPort[thisArray, [aix, aiy], thisEP, TRUE, TRUE, FALSE]; lastWire: Wire ~ NARROW[lastACI.conns.ApplyA[lastAP].MA]; thisWire: Wire ~ NARROW[thisACI.conns.ApplyA[thisAP].MA]; IF lastWire=NIL OR thisWire=NIL THEN ERROR; IF lastWire # thisWire THEN [] _ MergeNets[d, lastWire, thisWire, TRUE--neither can be exported yet--]; ENDLOOP ENDLOOP; nt _ TRUE}; lastCI _ ci; lastEP _ thisEP; lastArray _ thisArray; lastACI _ thisACI; RETURN [FALSE]}}; IF NOT d.Atomic[w] THEN RETURN [FALSE]; IF w.conns.SetOn[right].Scan[PerCell].found THEN ERROR; IF nt THEN { FOR aix: NATURAL IN [0 .. oa.size2[X]) DO FOR aiy: NATURAL IN [0 .. oa.size2[Y]) DO lastAP: Port ~ GetArrayPortForPort[lastArray, [aix, aiy], lastEP, FALSE, FALSE, FALSE]; lastWire: Wire ~ NARROW[lastACI.conns.ApplyA[lastAP].MA]; ain: SteppyName ~ AIName[oa, [aix, aiy]]; acts: Set ~ ActualNames[FALSE, OneSteppy[ain], mid.WNames[w]]; IF lastWire=NIL THEN ERROR; KnowVertexNames[outer, lastWire, acts, TRUE]; ENDLOOP ENDLOOP; nt _ nt}; RETURN [FALSE]}; MakeCrossEdges: PROC [osev: Sets.Value] RETURNS [BOOL] ~ { ose: StatEdge ~ NARROW[osev.VA]; IF ose.rank # 0 THEN RETURN [FALSE]; {opa: Port ~ SeP[ose, oa, FALSE]; opb: Port ~ SeP[ose, oa, TRUE]; wa: Wire ~ NARROW[mid.asu.exports.ApplyA[opa].MA]; wb: Wire ~ NARROW[mid.asu.exports.ApplyA[opb].MA]; pca: BiRels.Pair ~ wa.conns.Scan[AcceptNonexport].P; pcb: BiRels.Pair ~ wb.conns.Scan[AcceptNonexport].P; epa: Port ~ NARROW[pca[left].VA]; epb: Port ~ NARROW[pcb[left].VA]; ecia: CellInstance ~ NARROW[pca[right].VA]; ecib: CellInstance ~ NARROW[pcb[right].VA]; macta: CellType ~ NARROW[eltArrays.ApplyA[ecia].MA]; mactb: CellType ~ NARROW[eltArrays.ApplyA[ecib].MA]; acia: CellInstance ~ NARROW[arrayInsts.ApplyA[ecia].MA]; acib: CellInstance ~ NARROW[arrayInsts.ApplyA[ecib].MA]; sizeRange: Range2 ~ SizeRange[oa.size2]; rangeB: Range2 ~ Range2Intersection[sizeRange, Range2Off[sizeRange, ose. rangeA: Range2 ~ Range2Off[rangeB, Neg[ose. FOR aix: NATURAL IN [0 .. oa.size2[X]) DO FOR aiy: NATURAL IN [0 .. oa.size2[Y]) DO apa: Port ~ GetArrayPortForPort[macta, [aix, aiy], epa, TRUE, TRUE, FALSE]; apb: Port ~ GetArrayPortForPort[mactb, [aix, aiy], epb, TRUE, TRUE, FALSE]; owa: Wire ~ NARROW[acia.conns.ApplyA[apa].MA]; owb: Wire ~ NARROW[acib.conns.ApplyA[apb].MA]; KnowVertexNames[outer, owa, ActualNames[FALSE, OneSteppy[AIName[oa, [aix, aiy]]], mid.WNames[wa]], TRUE]; KnowVertexNames[outer, owb, ActualNames[FALSE, OneSteppy[AIName[oa, [aix, aiy]]], mid.WNames[wb]], TRUE]; outer _ outer; ENDLOOP ENDLOOP; FOR aix: INTEGER IN [rangeA[X].min .. rangeA[X].maxPlusOne) DO FOR aiy: INTEGER IN [rangeA[Y].min .. rangeA[Y].maxPlusOne) DO apa: Port ~ GetArrayPortForPort[macta, [aix, aiy], epa, FALSE, FALSE, FALSE]; apb: Port ~ GetArrayPortForPort[mactb, [aix, aiy], epb, FALSE, FALSE, FALSE]; owa: Wire ~ NARROW[acia.conns.ApplyA[apa].MA]; owb: Wire ~ NARROW[acib.conns.ApplyA[apb].MA]; IF owa#owb THEN [] _ MergeNets[d, owa, owb, TRUE]; outer _ outer; ENDLOOP ENDLOOP; RETURN [FALSE]}}; <> MakeExport: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { oap: Port ~ NARROW[pair[left].VA]; IF NOT d.Atomic[oap] THEN RETURN [FALSE]; {idw: DumbWire ~ NARROW[pair[right].VA]; minEpCai: BiRels.Pair ~ idw.eps.First[BiRels.rightFwd].P; mp: Port ~ NARROW[minEpCai[left].VA]; ocai: CompositeArrayIndex ~ minEpCai[right].VI; oai: Int2 ~ DecomposeAI[oa, ocai]; iw: Wire ~ NARROW[mid.asu.exports.ApplyA[mp].MA]; pc: BiRels.Pair ~ iw.conns.Scan[AcceptNonexport].P; ep: Port ~ NARROW[pc[left].VA]; eci: CellInstance ~ NARROW[pc[right].VA]; mact: CellType ~ NARROW[eltArrays.ApplyA[eci].MA]; aci: CellInstance ~ NARROW[arrayInsts.ApplyA[eci].MA]; iap: Port ~ GetArrayPortForPort[mact, oai, ep, TRUE, TRUE, FALSE]; ow: Wire ~ NARROW[aci.conns.ApplyA[iap].MA]; KnowVertexNames[outer, ow, ActualNames[FALSE, OneSteppy[AIName[oa, oai]], mid.WNames[iw]], TRUE]; Connect[d, ow, oap, outer]; RETURN [FALSE]}}; Deedoose: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { mact: CellType ~ NARROW[pair[right].VA]; [] _ DeduceStructureForPorts[mact, NIL]; RETURN [FALSE]}; IF oa.buildPhase # statrepFixed THEN ERROR; IF oa.basePeriod # ALL[1] THEN ERROR--sheer laziness (and desire to phinish)--; ForgetArray[outer]; FinishCreatingUnorganized[outer]; IF elts.Scan[CreateArrays].found THEN ERROR; IF mid.CTParts[w].Scan[MakeSelfEdges].found THEN ERROR; IF oa.statrep.edges.Scan[MakeDeltaEdges].found THEN ERROR; IF eltArrays.Scan[Midway].found THEN ERROR; IF mid.CTParts[w].Scan[MakeSiblingEdges].found THEN ERROR; IF missedEdges.Scan[MakeCrossEdges].found THEN ERROR; <> IF oa.dumrep.apToWire.Scan[MakeExport].found THEN ERROR; IF eltArrays.Scan[Deedoose].found THEN ERROR; [] _ DeduceStructureForWires[outer, NIL]; IF mid.Unused[] THEN DeleteCellType[mid, NIL]; RETURN}; AcceptNonexport: PROC [pair: BiRels.Pair] RETURNS [BOOL] ~ { WITH pair[right].VA SELECT FROM x: CellInstance => RETURN [TRUE]; x: CellType => RETURN [FALSE]; ENDCASE => ERROR}; END.