LichenNewArrayImpl1.Mesa
Last tweaked by Mike Spreitzer on February 2, 1988 12:40:11 pm PST
DIRECTORY AbSets, Basics, BiRels, Convert, LichenArrayStuff, LichenDataOps, LichenDataStructure, LRUCache, Rope, SetBasics;
LichenNewArrayImpl1: CEDAR PROGRAM
IMPORTS AbSets, BiRels, Convert, LichenDataOps, LichenDataStructure, LRUCache, Rope, SetBasics
EXPORTS LichenArrayStuff, LichenDataStructure
=
BEGIN OPEN LichenDataOps, LichenDataStructure, LichenArrayStuff, Sets:AbSets;
Array: TYPE ~ LichenDataStructure.Array;
CreateArrayRep: PUBLIC PROC [eltType: CellType, size2, basePeriod: Size2] RETURNS [Array] ~ {
statrep: StatRep ~ CreateStatRep[];
a: Array = NEW [ArrayPrivate ← [
eltType: eltType,
prevArray: NIL,
nextArray: NIL,
size2: size2,
size: size2[Foo]*size2[Bar],
basePeriod: basePeriod,
dumrep: NIL,
statrep: statrep
]];
RETURN [a]};
CreateStatRep: PUBLIC PROC RETURNS [sr: StatRep] ~ {
sr ← NEW [StatRepPrivate ← [
edges: Sets.CreateHashSet[statEdges],
portEdge: [
FALSE: BiRels.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]],
TRUE: BiRels.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]]],
apToPAI: BiRels.CreateHashFn[spaces: [SetBasics.refs, portsAtIndices], invable: FALSE]
]];
RETURN};
flushSelves: BOOLTRUE;
MakeArrayNewConnection: PUBLIC PROC [act: CellType, rangeA: Range2, delta: Int2, epA, epB: Port] ~ {
a: Array ~ act.asArray;
fullRangeA: Range2 ~ Range2Intersection[SizeRange[a.size2], Range2Off[SizeRange[a.size2], Int2Neg[delta]]];
rangeB: Range2 ~ Range2Off[rangeA, delta];
IF a.buildPhase#buildingStatrep THEN ERROR;
IF ABS[delta[Foo]]>1 OR ABS[delta[Bar]]>1 THEN ERROR;
IF epA=epB AND delta=[0, 0] THEN --this self-connection is always implicitly present, let's not make it explicit-- IF flushSelves THEN RETURN;
IF rangeA # fullRangeA THEN ERROR;
FOR ff: NAT IN [0 .. a.basePeriod[Foo]) DO FOR fb: NAT IN [0 .. a.basePeriod[Bar]) DO
fA: Nat2 ~ [ff, fb];
fB: Nat2 ~ Nat2AddMod[fA, delta, a.basePeriod];
svA: StatVertex ~ NEW [StatVertexPrivate ← [epA, fA]];
svB: StatVertex ~ NEW [StatVertexPrivate ← [epB, fB]];
IF FindStatEdge[a.statrep, [vs: [svA, svB], d: delta]]=NIL THEN [] ← AddStatEdge[a.statrep, [vs: [FALSE: svA, TRUE: svB], d: delta]];
act ← act;
ENDLOOP ENDLOOP;
RETURN};
MakeStatEdge: PUBLIC PROC [sep: StatEdgePrivate] RETURNS [StatEdge] ~ {
rev: BOOL ~ SELECT sep.d[Foo] FROM
<0 => TRUE,
=0 => sep.d[Bar]<0,
>0 => FALSE,
ENDCASE => ERROR;
IF rev THEN sep ← [
vs: [FALSE: sep.vs[TRUE], TRUE: sep.vs[FALSE]],
d: Int2Neg[sep.d]
];
RETURN [NEW [StatEdgePrivate ← sep]]};
AddStatEdge: PUBLIC PROC [sr: StatRep, sep: StatEdgePrivate] RETURNS [se: StatEdge] ~ {
se ← MakeStatEdge[sep];
IF sr.edges.HasMemA[se] THEN ERROR;
sr.portEdge[FALSE].AddNewAA[se.vs[FALSE].port, se];
sr.portEdge[TRUE].AddNewAA[se.vs[TRUE].port, se];
IF NOT sr.edges.AddA[se] THEN ERROR;
RETURN};
RemStatEdge: PUBLIC PROC [sr: StatRep, se: StatEdge] ~ {
IF NOT sr.edges.RemA[se] THEN ERROR;
IF sr.portEdge[FALSE].RemAA[se.vs[FALSE].port, se].had[rightToLeft]#same THEN ERROR;
IF sr.portEdge[TRUE].RemAA[se.vs[TRUE].port, se].had[rightToLeft]#same THEN ERROR;
RETURN};
StatEdgeRedundant: PROC [a: Array, sep: StatEdgePrivate, avoid: StatEdge ← NIL] RETURNS [redundant: BOOL] ~ {
seen: Set--of PortAtIndex-- ~ Sets.CreateHashSet[portsAtIndices];
frontier: Set--of PortAtIndex-- ~ Sets.CreateHashSet[portsAtIndices];
c1: Int2 ~ WidenNat2[sep.vs[FALSE].phase];
c2: Int2 ~ Int2Add[c1, sep.d];
bounds: Range2 ~ Int2sRange[c1, c2];
IF sep.vs[TRUE].phase # Nat2AddMod[sep.vs[FALSE].phase, sep.d, a.basePeriod] THEN ERROR;
IF NOT frontier.AddA[NEW [PortAtIndexPrivate ← [sep.vs[FALSE].port, c1]]] THEN ERROR;
WHILE NOT frontier.Empty[] DO
pai: PortAtIndex ~ NARROW[frontier.Pop.MA];
IF NOT seen.AddA[pai] THEN LOOP;
IF pai.port = sep.vs[TRUE].port AND pai.ai = c2 THEN RETURN [TRUE];
{sv: StatVertex ~ NEW [StatVertexPrivate ← [pai.port, Int2Mod[pai.ai, a.basePeriod]]];
TestEdge: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL] ~ {
d: Int2 ~ IF ob THEN se.d ELSE Int2Neg[se.d];
oai: ArrayIndex ~ Int2Add[pai.ai, d];
IF se#avoid AND Int2InRange[oai, bounds] THEN [] ← frontier.AddA[NEW [PortAtIndexPrivate ← [se.vs[ob].port, oai]]];
RETURN [FALSE]};
[] ← ScanStatEdgesFrom[a.statrep, sv, TestEdge];
}ENDLOOP;
RETURN [FALSE]};
FindStatEdge: PUBLIC PROC [sr: StatRep, sep: StatEdgePrivate] RETURNS [fse: StatEdge] ~ {
TestEdge: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL] ~ {
RETURN [statVerts.SEqual[AV[se.vs[ob]], AV[sep.vs[TRUE]]] AND sep.d = (IF ob THEN se.d ELSE Int2Neg[se.d])]};
fse ← ScanStatEdgesFrom[sr, sep.vs[FALSE], TestEdge].se;
RETURN};
FinishedMakingArrayConnections: PUBLIC PROC [act: CellType] ~ {
a: Array ~ act.asArray;
dumrep: DumRep ~ NEW [DumRepPrivate ← [
topWires: Sets.CreateHashSet[],
epToTopWire: BiRels.CreateHashFn[invable: FALSE],
apToWire: BiRels.CreateHashFn[invable: TRUE]
]];
PerStatEdge: PROC [ra: REF ANY] ~ {
DumbifyStatEdge[a, NARROW[ra]];
RETURN};
PerPort: PROC [rap, rpai: REF ANY] ~ {
ap: Port ~ NARROW[rap];
pai: PortAtIndex ~ NARROW[rpai];
dw: DumbWire ~ GetDumbWireForPort[a, pai.port, pai.ai, TRUE];
IF dw=NIL THEN ERROR;
dumrep.apToWire.AddNewAA[ap, dw];
RETURN};
IF a.buildPhase#buildingStatrep THEN ERROR;
a.buildPhase ← statrepFixed;
a.dumrep ← dumrep;
a.statrep.edges.EnumA[PerStatEdge];
a.statrep.apToPAI.EnumAA[PerPort];
RETURN};
SetStatRep: PUBLIC PROC [act: CellType, statrep: StatRep, reset: BOOL] ~ {
a: Array ~ act.asArray;
IF a.buildPhase # (IF reset THEN statrepFixed ELSE buildingStatrep) THEN ERROR;
a.buildPhase ← buildingStatrep;
a.statrep ← statrep;
FinishedMakingArrayConnections[act];
RETURN};
DumbifyStatEdge: PROC [a: Array, se: StatEdge] ~ {
epA: Port ~ se.vs[FALSE].port;
epB: Port ~ se.vs[TRUE].port;
fullRangeA: Range2 ~ Range2Intersection[SizeRange[a.size2], Range2Off[SizeRange[a.size2], Int2Neg[se.d]]];
iRangeA: Range2 ~ Range2Div[fullRangeA, a.basePeriod, se.vs[FALSE].phase];
dwsA: RefSeq--cai b TopDumbWire-- ~ GetDumbWires[a, epA, TRUE];
dwsB: RefSeq--cai b TopDumbWire-- ~ GetDumbWires[a, epB, TRUE];
FOR if: INT IN [iRangeA[Foo].min .. iRangeA[Foo].maxPlusOne) DO FOR ib: INT IN [iRangeA[Bar].min .. iRangeA[Bar].maxPlusOne) DO
aiA: Int2 ~ [
if*a.basePeriod[Foo]+se.vs[FALSE].phase[Foo],
ib*a.basePeriod[Bar]+se.vs[FALSE].phase[Bar]];
aiB: ArrayIndex ~ Int2Add[se.d, aiA];
caiA: CompositeArrayIndex ~ ComposeAI[a, aiA];
caiB: CompositeArrayIndex ~ ComposeAI[a, aiB];
dwA: TopDumbWire ~ NARROW[dwsA[caiA]];
dwB: TopDumbWire ~ NARROW[dwsB[caiB]];
IF dwA=dwB THEN {IF dwA=NIL THEN {
dw: TopDumbWire ~ CreateDumbTop[a];
AddDumbElt[a, dw, epA, aiA];
AddDumbElt[a, dw, epB, aiB]}}
ELSE IF dwA=NIL THEN AddDumbElt[a, dwB, epA, aiA]
ELSE IF dwB=NIL THEN AddDumbElt[a, dwA, epB, aiB]
ELSE JoinDumbWires[a, dwA, dwB];
a ← a;
ENDLOOP ENDLOOP;
RETURN};
CreateDumbTop: PROC [a: Array] RETURNS [tdw: TopDumbWire] ~ {
tdw ← NEW [DumbWirePrivate[top] ← [
children: BiRels.CreateHashFn[invable: FALSE],
variant: top[eps: BiRels.CreateHashFn[invable: FALSE]]
]];
IF NOT a.dumrep.topWires.AddA[tdw] THEN ERROR;
RETURN};
AddDumbElt: PROC [a: Array, dw: TopDumbWire, ep: Port, ai: ArrayIndex] ~ {
cai: CompositeArrayIndex ~ ComposeAI[a, ai];
dws: RefSeq--CompositeArrayIndex b TopDumbWire-- ~ GetDumbWires[a, ep, TRUE];
mems: BoolSeq--CompositeArrayIndex b member--NARROW[dw.eps.ApplyA[ep].MDA];
IF mems=NIL THEN dw.eps.AddNewAA[ep, mems ← CreateBoolSeq[a.size, FALSE]];
dws[cai] ← dw;
mems[cai] ← TRUE;
RETURN};
JoinDumbWires: PROC [a: Array, dwA, dwB: TopDumbWire] ~ {
MoveElt: PROC [pair: BiRels.Pair] ~ {
ep: Port ~ NARROW[pair[left].VA];
dws: RefSeq--CompositeArrayIndex b DumbWire-- ~ NARROW[a.dumrep.epToTopWire.ApplyA[ep].MA];
memsB: BoolSeq ~ NARROW[pair[right].VA];
memsA: BoolSeq ~ NARROW[dwA.eps.ApplyA[ep].MDA];
IF memsA=NIL THEN {
dwA.eps.AddNewAA[ep, memsB];
FOR cai: CompositeArrayIndex IN [0 .. a.size) DO
IF memsB[cai] THEN dws[cai] ← dwA;
ENDLOOP;
}
ELSE {
FOR cai: CompositeArrayIndex IN [0 .. a.size) DO
IF memsB[cai] THEN {
memsA[cai] ← TRUE;
dws[cai] ← dwA};
ENDLOOP;
};
RETURN};
MoveExport: PROC [ra: Sets.Value] ~ {
ap: Port ~ NARROW[ra.VA];
[] ← a.dumrep.apToWire.AddAA[ap, dwA];
RETURN};
IF NOT a.dumrep.topWires.RemA[dwB] THEN ERROR;
dwB.eps.Enumerate[MoveElt];
a.dumrep.apToWire.MappingA[dwB, rightToLeft].Enumerate[MoveExport];
RETURN};
GetDumbWires: PROC [a: Array, ep: Port, mayAdd: BOOL] RETURNS [dws: RefSeq--cai b TopDumbWire--] ~ {
dws ← NARROW[a.dumrep.epToTopWire.ApplyA[ep].MDA];
IF dws=NIL AND mayAdd THEN a.dumrep.epToTopWire.AddNewAA[ep, dws ← CreateRefSeq[a.size]];
RETURN};
GetDumbWire: PUBLIC PROC [a: Array, ep: Port, ai: ArrayIndex] RETURNS [dw: DumbWire] ~ {
cai: CompositeArrayIndex ~ ComposeAI[a, ai];
Work: PROC [ep: Port] RETURNS [dw: DumbWire] ~ {
dws: RefSeq--cai b TopDumbWire-- ~ GetDumbWires[a, ep, FALSE];
IF dws#NIL THEN dw ← NARROW[dws[cai]];
IF dw#NIL THEN RETURN;
IF ep.parent # a.eltType.port THEN {
pdw: DumbWire ~ Work[NARROW[ep.parent]];
IF pdw#NIL THEN RETURN [GetDumbChild[pdw, ep]];
};
RETURN};
IF a.buildPhase#statrepFixed THEN ERROR;
RETURN Work[ep]};
GetDumbChild: PROC [pdw: DumbWire, port: Port] RETURNS [cdw: ChildDumbWire] ~ {
cdw ← NARROW[pdw.children.ApplyA[port].MDA];
IF cdw#NIL THEN RETURN;
pdw.children.AddNewAA[port, cdw ← NEW [DumbWirePrivate[child] ← [
children: BiRels.CreateHashFn[invable: FALSE],
variant: child[pdw, port] ]] ];
RETURN};
GetDumbWireForPort: PROC [a: Array, ep: Port, ai: ArrayIndex, mayAdd: BOOL] RETURNS [dw: DumbWire] ~ {
dw ← GetDumbWire[a, ep, ai];
IF dw#NIL OR NOT mayAdd THEN RETURN;
AddDumbSubtree[a, ai, ep];
dw ← GetDumbWire[a, ep, ai];
RETURN};
AddDumbSubtree: PROC [a: Array, index: ArrayIndex, ep: Port] ~ {
Check: PROC [ep, done: Port] RETURNS [ok: BOOLTRUE] ~ {
ok ← GetDumbWire[a, ep, index] = NIL;
FOR cep: Port ← ep.FirstChildPort, cep.NextChildPort WHILE ok AND cep#NIL DO
ok ← cep=done OR Check[cep, NIL];
ENDLOOP;
RETURN};
IF NOT Check[ep, NIL] THEN RETURN;
{WorkUp: PROC [ep: Port] ~ {
WITH ep.parent SELECT FROM
parent: Port => IF parent#a.eltType.port THEN {
pdw: DumbWire ~ GetDumbWire[a, parent, index];
IF pdw#NIL THEN {WorkDown[pdw, parent]; RETURN};
IF Check[parent, ep] THEN {WorkUp[parent]; RETURN};
};
ENDCASE => NULL;
{tdw: TopDumbWire ~ CreateDumbTop[a];
AddDumbElt[a, tdw, ep, index];
WorkDown[tdw, ep];
RETURN}};
WorkDown: PROC [dw: DumbWire, ep: Port] ~ {
FOR cep: Port ← ep.FirstChildPort, cep.NextChildPort WHILE cep#NIL DO
WorkDown[GetDumbChild[dw, cep], cep];
ENDLOOP;
RETURN};
WorkUp[ep];
RETURN}};
ArrayEltPortsConnected: PUBLIC PROC [a: Array, ai1, ai2: ArrayIndex, ep1, ep2: Port] RETURNS [BOOL] ~ {
dw1: DumbWire ~ GetDumbWire[a, ep1, ai1];
dw2: DumbWire ~ GetDumbWire[a, ep2, ai2];
IF a.buildPhase#statrepFixed THEN ERROR;
RETURN [dw1=dw2 AND dw1#NIL]};
EnumerateConnectedEltPorts: PUBLIC PROC [a: Array, ep: Port, Consume: PROC [Port], mayDuplicate: BOOL] ~ {
seenPorts: Set--of elt Port--;
PerWire: PROC [dw: DumbWire] ~ {
[] ← ScanPortsInDumbWire[a, dw, PassPort];
RETURN};
PassPort: PROC [ep: Port] RETURNS [BOOL] ~ {
IF (mayDuplicate OR seenPorts.AddA[ep]) THEN Consume[ep];
RETURN [FALSE]};
IF NOT mayDuplicate THEN seenPorts ← Sets.CreateHashSet[];
IF a.buildPhase#statrepFixed THEN ERROR;
EnumerateDumbWiresForPort[a, ep, PerWire];
RETURN};
EnumerateDumbWiresForPort: PUBLIC PROC [a: Array, ep: Port, Consume: PROC [DumbWire]] ~ {
seenWires: Set--of TopDumbWire-- ~ Sets.CreateHashSet[];
Work: PROC [port: Port, Consume: PROC [DumbWire]] ~ {
dws: RefSeq--CompositeArrayIndex b TopDumbWire-- ~ NARROW[a.dumrep.epToTopWire.ApplyA[port].MDA];
IF dws#NIL THEN {
FOR cai: CompositeArrayIndex IN [0 .. a.size) DO
dw: TopDumbWire ~ NARROW[dws[cai]];
IF seenWires.AddA[dw] THEN Consume[dw];
ENDLOOP;
};
WITH port.parent SELECT FROM
parent: Port => {
Pass: PROC [parent: DumbWire] ~ {
child: ChildDumbWire ~ GetDumbChild[parent, port];
Consume[child];
RETURN};
Work[parent, Pass];
};
x: CellType => NULL;
ENDCASE => ERROR;
RETURN};
IF a.buildPhase#statrepFixed THEN ERROR;
Work[ep, Consume];
RETURN};
ScanPortsInDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, Test: PROC [Port] RETURNS [BOOL]] RETURNS [found: BOOL, ep: Port] ~ {
ScanWire: PROC [dw: DumbWire, Test: PROC [Port] RETURNS [BOOL]] RETURNS [found: BOOL, ep: Port] ~ {
WITH dw SELECT FROM
tdw: TopDumbWire => {
TestPort: PROC [pair: BiRels.Pair] RETURNS [pass: BOOLFALSE] ~ {
port: Port ~ NARROW[pair[left].VA];
IF (pass ← Test[port]) THEN ep ← port;
RETURN};
found ← tdw.eps.Scan[TestPort].found;
RETURN};
cdw: ChildDumbWire => {
index: NATURAL ~ cdw.port.PortIndex;
TestPort: PROC [parent: Port] RETURNS [pass: BOOLFALSE] ~ {
child: Port ~ parent.SubPort[index];
IF (pass ← Test[child]) THEN ep ← child;
RETURN};
found ← ScanWire[cdw.parent, TestPort].found;
RETURN};
ENDCASE => ERROR;
};
RETURN ScanWire[dw, Test]};
GetInstForPortInDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, ep: Port] RETURNS [ArrayIndex] ~ {
WITH dw SELECT FROM
tdw: TopDumbWire => {
mems: BoolSeq--CompositeArrayIndex b member-- ~ NARROW[tdw.eps.ApplyA[ep].MA];
FOR cai: NATURAL IN [0 .. a.size) DO
IF mems[cai] THEN RETURN DecomposeAI[a, cai];
ENDLOOP;
RETURN [ALL[-1]]};
cdw: ChildDumbWire => RETURN GetInstForPortInDumbWire[a, cdw.parent, NARROW[ep.parent]];
ENDCASE => ERROR;
};
ScanPortsAtIndicesForDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, Test: PROC [port: Port, ai: ArrayIndex] RETURNS [BOOL]] RETURNS [found: BOOL, pai: PortAtIndexPrivate] ~ {
WITH dw SELECT FROM
tdw: TopDumbWire => {
PerPort: PROC [pair: BiRels.Pair] RETURNS [pass: BOOL] ~ {
ep: Port ~ NARROW[pair[left].VA];
mems: BoolSeq--CompositeArrayIndex b member-- ~ NARROW[pair[right].VA];
FOR f: INT IN [0 .. a.size2[Foo]) DO FOR b: INT IN [0 .. a.size2[Bar]) DO
cai: CompositeArrayIndex ~ ComposeAI[a, [f, b]];
IF mems[cai] THEN IF (pass ← Test[ep, [f, b]])
THEN {pai ← [ep, [f, b]]; RETURN};
ENDLOOP ENDLOOP;
RETURN [FALSE]};
found ← tdw.eps.Scan[PerPort].found;
RETURN};
cdw: ChildDumbWire => {
index: NATURAL ~ cdw.port.PortIndex;
Pass: PROC [port: Port, ai: ArrayIndex] RETURNS [pass: BOOL] ~ {
child: Port ~ port.SubPort[index];
IF (pass ← Test[child, ai]) THEN pai ← [child, ai];
RETURN};
found ← ScanPortsAtIndicesForDumbWire[a, cdw.parent, Pass].found;
RETURN};
ENDCASE => ERROR;
};
ScanStatVertices: PUBLIC PROC [a: Array, Test: PROC [StatVertex] RETURNS [BOOL]] RETURNS [found: BOOLFALSE, sv: StatVertex ← NIL] ~ {
seen: Set--of StatVertex-- ~ Sets.CreateHashSet[statVerts];
PerEdge: PROC [ra: Sets.Value] ~ {
se: StatEdge ~ NARROW[ra.VA];
IF seen.AddA[se.vs[FALSE]] AND Test[se.vs[FALSE]] THEN {found ← TRUE; sv ← se.vs[FALSE]; RETURN};
IF seen.AddA[se.vs[TRUE]] AND Test[se.vs[TRUE]] THEN {found ← TRUE; sv ← se.vs[TRUE]};
RETURN};
a.statrep.edges.Enumerate[PerEdge];
RETURN};
ScanStatEdgesFrom: PUBLIC PROC [sr: StatRep, from: StatVertex, Test: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL]] RETURNS [found: BOOLFALSE, se: StatEdge ← NIL, ob: BOOLFALSE] ~ {
FOR ob IN BOOL DO
sb: BOOL ~ NOT ob;
TestEdge: PROC [ra: Sets.Value] RETURNS [pass: BOOL] ~ {
se: StatEdge ~ NARROW[ra.VA];
pass ← se.vs[sb].phase = from.phase AND Test[se, ob];
RETURN};
mp: BiRels.MaybePair ~ sr.portEdge[sb].ScanMapping[AV[from.port], TestEdge];
IF mp.found THEN RETURN [TRUE, NARROW[mp.it[right].VA], ob];
ENDLOOP;
RETURN};
GetArrayPortForPort: PUBLIC PROC [act: CellType, index: ArrayIndex, ep: Port, mayAdd: BOOL] RETURNS [arrayPort: Port] ~ {
a: Array ~ act.asArray;
IF a.buildPhase#statrepFixed THEN ERROR;
{dw: DumbWire ~ GetDumbWireForPort[a, ep, index, mayAdd];
IF dw=NIL THEN {IF mayAdd THEN ERROR--trying to export a composite wire that doesn't really exist-- ELSE RETURN [NIL]};
{aPort: Port ~ NARROW[a.dumrep.apToWire.ScanHalfRestriction[set: Sets.CreateSingleton[AV[dw], SetBasics.refs], Test: BiRels.AcceptAny, side: right].KeepHalf[left].MDA];
IF aPort#NIL THEN RETURN [aPort];
IF NOT mayAdd THEN RETURN [NIL];
arrayPort ← FullyAddPort[[parent: act.port, names: CreateSteppyNames[IF act.inheritNames THEN LIST[SNCat[NameIndex[a, index], SteppyDescribe[ep, a.eltType.port]]] ELSE NIL]]].port;
a.statrep.apToPAI.AddNewAA[arrayPort, NEW[PortAtIndexPrivate ← [ep, index]]];
a.dumrep.apToWire.AddNewAA[arrayPort, dw];
RETURN}}};
NoteNewEltPort: PUBLIC PROC [a: Array, ep: Port] ~ {
RETURN};
IsIncompleteArray: PUBLIC PROC [act: CellType] RETURNS [BOOL]
~ {RETURN [FALSE]};
ComposeAI: PROC [a: Array, ai: ArrayIndex] RETURNS [CompositeArrayIndex]
~ INLINE {RETURN [a.size2[Bar]*ai[Foo]+ai[Bar]]};
DecomposeAI: PROC [a: Array, cai: CompositeArrayIndex] RETURNS [ArrayIndex] ~ {
f: NATURAL ~ cai/a.size2[Bar];
RETURN [[f, cai - f*a.size2[Bar]]]};
NameIndex: PUBLIC PROC [a: Array, index: ArrayIndex] RETURNS [SteppyName] = {
RETURN LSn[SELECT 1 FROM
a.size2[Foo] => LIST[NewInt[index[Bar]]],
a.size2[Bar] => LIST[NewInt[index[Foo]]],
ENDCASE => LIST[NewInt[index[Foo]], NewInt[index[Bar]]]];
};
FmtIndex: PUBLIC PROC [a: Array, index: ArrayIndex] RETURNS [asRope: ROPE] = {
asRope ← SELECT TRUE FROM
a.size2[Foo]=1 => Subscript[NIL, index[Bar]],
a.size2[Bar]=1 => Subscript[NIL, index[Foo]],
ENDCASE => Subscript2[NIL, index];
};
sublen: NATURAL ~ 64;
subs: ARRAY [0 .. sublen) OF ROPEALL[NIL];
Subscript: PUBLIC PROC [base: ROPE, index: INT] RETURNS [sub: ROPE] ~ {
sub ← IF index < sublen THEN sub ← subs[index] ELSE sub ← Convert.RopeFromInt[index].Concat["/"];
IF base.Length#0 THEN sub ← base.Cat["/", sub];
RETURN};
sub2len: NATURAL ← 2050;
sub2Ps: LRUCache.Handle ← LRUCache.Create[sub2len, HashAI, EqualAI];
sub2Rs: RefSeq ← CreateRefSeq[sub2len];
s2probes, s2misses: CARD ← 0;
HashAI: PROC [ra: REF ANY] RETURNS [CARDINAL] --LRUCache.HashProc-- ~ {
rai: REF ArrayIndex ~ NARROW[ra];
lnF: Basics.LongNumber ~ [li[rai[Foo]]];
lnB: Basics.LongNumber ~ [li[rai[Bar]]];
ln: Basics.LongNumber ~ [lc[lnF.lo + lnF.hi*3 + lnB.lo*5 + lnB.hi*7]];
RETURN [ln.lo+ln.hi];
};
EqualAI: PROC [r1, r2: REF ANY] RETURNS [BOOL] --LRUCache.EqualProc-- ~ {
rai1: REF ArrayIndex ~ NARROW[r1];
rai2: REF ArrayIndex ~ NARROW[r2];
RETURN [rai1^ = rai2^]};
Subscript2: PUBLIC PROC [base: ROPE, index: ArrayIndex] RETURNS [sub: ROPE] ~ {
rai: REF ArrayIndex ~ NEW [ArrayIndex ← index];
p: NATURAL;
news: BOOL;
[p, news, ] ← sub2Ps.Include[rai];
s2probes ← s2probes+1;
IF news THEN {
sub2Rs[p] ← Rope.Cat[Convert.RopeFromInt[index[Foo]], "/", Convert.RopeFromInt[index[Bar]], "/"];
s2misses ← s2misses+1;
};
sub ← NARROW[sub2Rs[p]];
IF base.Length#0 THEN sub ← base.Cat["/", sub];
RETURN};
statEdges: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate ← [
Contains: StatEdgesContains,
Equal: StatEdgesEqual,
Hash: HashStatEdge,
Compare: CompareStatEdges,
name: "stat edges"
]];
StatEdgesContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ {
RETURN [WITH v.ra SELECT FROM
x: StatEdge => TRUE,
ENDCASE => FALSE]};
StatEdgesEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ {
RETURN [CompareStatEdges[data, v1, v2]=equal]};
HashStatEdge: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ {
se: StatEdge ~ NARROW[v.ra];
RETURN [statVerts.SHash[AV[se.vs[FALSE]]]*17 + statVerts.SHash[AV[se.vs[TRUE]]] + SetBasics.HashIntI[se.d[Foo]]*137 + SetBasics.HashIntI[se.d[Bar]]*33]};
CompareStatEdges: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ {
se1: StatEdge ~ NARROW[v1.ra];
se2: StatEdge ~ NARROW[v2.ra];
IF (c ← statVerts.SCompare[AV[se1.vs[FALSE]], AV[se2.vs[FALSE]]]) = equal THEN
IF (c ← statVerts.SCompare[AV[se1.vs[TRUE]], AV[se2.vs[TRUE]]]) = equal THEN
IF (c ← SetBasics.CompareIntI[se1.d[Foo], se2.d[Foo]]) = equal THEN
c ← SetBasics.CompareIntI[se1.d[Bar], se2.d[Bar]];
RETURN};
statVerts: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate ← [
Contains: StatVertsContains,
Equal: StatVertsEqual,
Hash: HashStatVert,
Compare: CompareStatVerts,
name: "stat verts"
]];
StatVertsContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ {
RETURN [WITH v.ra SELECT FROM
x: StatVertex => TRUE,
ENDCASE => FALSE]};
StatVertsEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ {
RETURN [CompareStatVerts[data, v1, v2]=equal]};
HashStatVert: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ {
sv: StatVertex ~ NARROW[v.VA];
RETURN [SetBasics.HashRefI[sv.port] + SetBasics.HashIntI[sv.phase[Foo]]*137 + SetBasics.HashIntI[sv.phase[Bar]]]};
CompareStatVerts: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ {
sv1: StatVertex ~ NARROW[v1.VA];
sv2: StatVertex ~ NARROW[v2.VA];
IF (c ← SetBasics.CompareRefI[sv1.port, sv2.port]) = equal THEN IF (c ← SetBasics.CompareIntI[sv1.phase[Foo], sv2.phase[Foo]]) = equal THEN c ← SetBasics.CompareIntI[sv1.phase[Bar], sv2.phase[Bar]];
RETURN};
portsAtIndices: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate ← [
Contains: PortsAtIndicesContains,
Equal: PortsAtIndicesEqual,
Hash: PortsAtIndicesHash,
Compare: PortsAtIndicesCompare,
name: "ports at indices"
]];
PortsAtIndicesContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ {
RETURN [WITH v.ra SELECT FROM
x: PortAtIndex => TRUE,
ENDCASE => FALSE]};
PortsAtIndicesEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ {
RETURN [PortsAtIndicesCompare[data, v1, v2]=equal]};
PortsAtIndicesHash: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ {
pai: PortAtIndex ~ NARROW[v.VA];
RETURN [SetBasics.HashRefI[pai.port] + SetBasics.HashIntI[pai.ai[Foo]]*137 + SetBasics.HashIntI[pai.ai[Bar]]]};
PortsAtIndicesCompare: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ {
pai1: PortAtIndex ~ NARROW[v1.VA];
pai2: PortAtIndex ~ NARROW[v2.VA];
IF (c ← SetBasics.CompareRefI[pai1.port, pai2.port]) = equal THEN IF (c ← SetBasics.CompareIntI[pai1.ai[Foo], pai2.ai[Foo]]) = equal THEN c ← SetBasics.CompareIntI[pai1.ai[Bar], pai2.ai[Bar]];
RETURN};
Range2Div: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = {
rr ← [
Foo: [
min: CeilDiv[r[Foo].min-f[Foo], t[Foo]],
maxPlusOne: FloorDiv[r[Foo].maxPlusOne-1-f[Foo], t[Foo]] + 1],
Bar: [
min: CeilDiv[r[Bar].min-f[Bar], t[Bar]],
maxPlusOne: FloorDiv[r[Bar].maxPlusOne-1-f[Bar], t[Bar]] + 1]];
};
Range1Div: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = {
rr ← [
min: CeilDiv[r.min-f, t],
maxPlusOne: FloorDiv[r.maxPlusOne-1-f, t] + 1];
};
Range2MulA: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = {
rr ← [
Foo: [
min: r[Foo].min*t[Foo] + f[Foo],
maxPlusOne: (r[Foo].maxPlusOne-1)*t[Foo] + 1 + f[Foo]],
Bar: [
min: r[Bar].min*t[Bar] + f[Bar],
maxPlusOne: (r[Bar].maxPlusOne-1)*t[Bar] + 1 + f[Bar]]];
};
Range2MulB: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = {
rr ← [
Foo: [
min: r[Foo].min*t[Foo] + f[Foo],
maxPlusOne: r[Foo].maxPlusOne*t[Foo] + f[Foo]],
Bar: [
min: r[Bar].min*t[Bar] + f[Bar],
maxPlusOne: r[Bar].maxPlusOne*t[Bar] + f[Bar]]];
};
Range1MulB: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = {
rr ← [
min: r.min*t + f,
maxPlusOne: r.maxPlusOne*t + f];
};
Start: PROC ~ {
FOR index: NATURAL IN [0 .. sublen) DO
subs[index] ← Convert.RopeFromInt[index].Concat["/"];
ENDLOOP;
RETURN};
Start[];
END.