LowerArrayStructure:
PUBLIC
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 é array ct-- ~ BiRels.CreateHashOTO[ALL[d.eSpace]];
arrayInsts: OneToOne--inner ci é array inst-- ~ BiRels.CreateHashOTO[ALL[d.eSpace]];
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];
[] ← d.crossedCellTypes.AddA[act];
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]]], d: 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]]], d: ose.d];
[] ← 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 ai
x:
NATURAL
IN [0 .. oa.size2[X])
DO
FOR ai
y:
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, FALSE--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 ai
x:
NATURAL
IN [0 .. oa.size2[X])
DO
FOR ai
y:
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.d]];
rangeA: Range2 ~ Range2Off[rangeB, Neg[ose.d]];
FOR ai
x:
NATURAL
IN [0 .. oa.size2[X])
DO
FOR ai
y:
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 ai
x:
INTEGER
IN [rangeA[X].min .. rangeA[X].maxPlusOne)
DO
FOR ai
y:
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, FALSE];
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];
{ipai: PortAtIndex ~ VPai[pair[right]];
iw: Wire ~ NARROW[mid.asu.exports.ApplyA[ipai.port].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, ipai.ai, ep, TRUE, TRUE, FALSE];
ow: Wire ~ NARROW[aci.conns.ApplyA[iap].MA];
KnowVertexNames[outer, ow, ActualNames[FALSE, OneSteppy[AIName[oa, ipai.ai]], mid.WNames[iw]], TRUE];
Connect[d, ow, oap, outer];
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.statrep.apToPAI.Scan[MakeExport].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};