CoreTracingImpl.Mesa
Mike Spreitzer March 10, 1987 1:38:12 pm PST
DIRECTORY Core, CoreClasses, CoreOps, CoreProperties, CoreTracing, IO, PartialOrders, RefTab;
CoreTracingImpl: CEDAR PROGRAM
IMPORTS CoreClasses, CoreOps, CoreProperties, CoreTracing, IO, PartialOrders, RefTab
EXPORTS CoreTracing
= BEGIN OPEN Core, CoreClasses, CO: CoreOps, CP: CoreProperties, CoreTracing, PO: PartialOrders;
RefInt: TYPE = REF INT;
CellTypeList: TYPE ~ LIST OF CellType;
Reg: PROC [a: ATOM] RETURNS [ATOM]
~ {RETURN [CP.RegisterUnprintableProperty[a]]};
containerProp: ATOM ~ Reg[$CoreTraceToContainingCellType];
instancesProp: ATOM ~ Reg[$CoreTraceCellTypeToInstances];
connectionsProp: ATOM ~ Reg[$CoreTraceWireToConnections];
seqProp: ATOM ~ Reg[$CoreTraceIsRootWireSequence];
seqsProp: ATOM ~ Reg[$CoreTraceCellTypeToSequencesOfIt];
upWireProp: ATOM ~ Reg[$CoreTraceWireUpward];
publicIndexProp: ATOM ~ Reg[$CoreTraceWireToPublicIndex];
simplestProp: ATOM ~ Reg[$CoreTraceCellTypeToSimplest];
noPath: PUBLIC Path ~ LIST[noIndex];
ConsOuter: PUBLIC PROC [i: Index, p: Path] RETURNS [Path]
~ {RETURN [IF p=NIL THEN LIST[i] ELSE CONS[p.first, ConsOuter[i, p.rest]]]};
Outsplit: PUBLIC PROC [p: Path] RETURNS [first: Index, rest: Path]
~ {IF p.rest = NIL THEN RETURN [p.first, NIL] ELSE {
[first, rest] ← Outsplit[p.rest];
RETURN [first, CONS[p.first, rest]]}};
PathCat: PUBLIC PROC [inner, outer: Path] RETURNS [Path] ~ {
RETURN [
IF inner=NIL THEN outer
ELSE IF outer=NIL THEN inner
ELSE IF inner.rest=NIL THEN CONS[inner.first, outer]
ELSE CONS[inner.first, PathCat[inner.rest, outer]]]};
SubWire: PUBLIC PROC [w: Wire, p: Path] RETURNS [Wire] ~ {
RETURN [
IF p=NIL THEN w
ELSE IF p.rest=NIL THEN w[p.first]
ELSE SubWire[w, p.rest][p.first]
]};
Simplify: PUBLIC PROC [anyCellType: CellType] RETURNS [cellType: CellType, recordCellType: RecordCellType] = {
cellType ← NARROW[CP.GetCellTypeProp[anyCellType, simplestProp]];
IF cellType = NIL THEN {
FOR cellType ← anyCellType, CO.Recast[cellType] UNTIL cellType.class.recast = NIL DO NULL ENDLOOP;
CP.PutCellTypeProp[anyCellType, simplestProp, cellType];
};
WITH cellType.data SELECT FROM
x: RecordCellType => recordCellType ← x;
ENDCASE => recordCellType ← NIL;
};
EnumeratorForSingleton: PUBLIC PROC [s: REF ANY] RETURNS [e: Enumerator] = {
e ← NEW [EnumeratorPrivate ← [EnumerateSingleton, s]];
};
EnumerateSingleton: PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
Consumer[data];
};
EnumeratorForHashTable: PUBLIC PROC [ht: RefTab.Ref, key, value: BOOL] RETURNS [e: Enumerator] = {
hte: HashTableEnumeration = NEW [HashTableEnumerationPrivate ← [ht, key, value]];
e ← NEW [EnumeratorPrivate ← [EnumerateHashTable, hte]];
};
HashTableEnumeration: TYPE = REF HashTableEnumerationPrivate;
HashTableEnumerationPrivate: TYPE = RECORD [
ht: RefTab.Ref, key, value: BOOL];
EnumerateHashTable: PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
hte: HashTableEnumeration = NARROW[data];
PerPair: PROC [key, val: REF ANY] RETURNS [quit: BOOLEANFALSE] --RefTab.EachPairAction-- = {
IF hte.key THEN Consumer[key];
IF hte.value THEN Consumer[val];
};
[] ← hte.ht.Pairs[PerPair];
};
EnumeratorForPartialOrder: PUBLIC PROC [po: PartialOrder, direction: PO.Direction] RETURNS [e: Enumerator] = {
poe: PartialOrderEnumeration = NEW [PartialOrderEnumerationPrivate ← [po, direction]];
e ← NEW [EnumeratorPrivate ← [EnumeratePartialOrder, poe]];
};
PartialOrderEnumeration: TYPE = REF PartialOrderEnumerationPrivate;
PartialOrderEnumerationPrivate: TYPE = RECORD [
po: PO.PartialOrder, direction: PO.Direction];
EnumeratePartialOrder: PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
poe: PartialOrderEnumeration = NARROW[data];
PerElt: PROC [rank: INT, elt: PO.Element, v: PO.Vertex] --PartialOrder.Consumer-- = {
Consumer[elt];
};
[] ← poe.po.Enumerate[poe.direction, NIL, PerElt];
};
EnumeratorForReachable: PUBLIC PROC [e0: Enumerator] RETURNS [e: Enumerator] = {
e ← NEW [EnumeratorPrivate ← [EnumerateReachable, e0]];
};
EnumerateReachable: PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
e0: Enumerator = NARROW[data];
seen: RefTab.Ref = RefTab.Create[];
SeeAny: PROC [ra: REF ANY] = {SeeCellType[NARROW[ra]]};
SeeCellType: PROC [ct: CellType] = {
quaRecord: RecordCellType = Simplify[ct].recordCellType;
IF NOT seen.Insert[ct, $T] THEN RETURN;
Consumer[ct];
IF quaRecord # NIL THEN {
FOR i: INT IN [0 .. quaRecord.size) DO SeeCellType[quaRecord[i].type] ENDLOOP;
};
};
e0.Enumerate[e0.data, SeeAny];
};
Count: PUBLIC PROC [e: Enumerator, limit: INTINT.LAST] RETURNS [i: INT] = {
PerElt: PROC [REF ANY] = {IF (i ← i + 1) >= limit THEN Enuf};
i ← 0;
e.Enumerate[e.data, PerElt !Enuf => CONTINUE];
};
Enuf: ERROR = CODE;
GetOne: PUBLIC PROC [e: Enumerator] RETURNS [elt: REF ANY] = {
PerElt: PROC [x: REF ANY] = {elt ← x; Enuf};
elt ← NIL;
e.Enumerate[e.data, PerElt !Enuf => CONTINUE];
};
Prepare: PUBLIC PROC [e: Enumerator--of all CellTypes--] = {
Clear: PROC [ra: REF ANY] = {
urCellType: CellType = NARROW[ra];
cellType: CellType;
recordCellType: RecordCellType;
[cellType, recordCellType] ← Simplify[urCellType];
CP.PutCellTypeProp[urCellType, instancesProp, NIL];
CP.PutCellTypeProp[urCellType, seqsProp, NIL];
IF recordCellType = NIL THEN RETURN;
ClearCellType[urCellType, cellType, recordCellType];
};
Note: PROC [ra: REF ANY] = {
urCellType: CellType = NARROW[ra];
cellType: CellType;
recordCellType: RecordCellType;
public: Wire ← urCellType.public;
[cellType, recordCellType] ← Simplify[urCellType];
NoteCellType[urCellType, cellType, recordCellType, TRUE];
};
e.Enumerate[e.data, Clear];
e.Enumerate[e.data, Note];
};
ClearCellType: PROC [urCellType, cellType: CellType, recordCellType: RecordCellType] = {
internal: Wire;
CP.PutWireProp[urCellType.public, seqProp, NIL];
IF recordCellType = NIL THEN RETURN;
internal ← recordCellType.internal;
CP.PutWireProp[internal, seqProp, NIL];
RemoveLocalConnections[internal];
};
NoteCellType: PROC [urCellType, cellType: CellType, recordCellType: RecordCellType, instanceStuffToo: BOOL] = {
public: Wire ~ urCellType.public;
AddLocalConnection[public, NIL, NIL];
IF urCellType.class = sequenceCellClass THEN {
seq: SequenceCellType ~ NARROW[urCellType.data];
seqs: CellTypeList ← NARROW[CP.GetCellTypeProp[seq.base, seqsProp]];
seqs ← CONS[urCellType, seqs];
CP.PutCellTypeProp[seq.base, seqsProp, seqs];
};
IF recordCellType = NIL THEN RETURN;
{internal: Wire ~ recordCellType.internal;
FOR i: INT IN [0 .. recordCellType.size) DO
ci: CellInstance = recordCellType[i];
actual: Wire = ci.actual;
IF instanceStuffToo THEN {
instances: InstanceList ← NARROW[CP.GetCellTypeProp[ci.type, instancesProp]];
instances ← CONS[ci, instances];
CP.PutCellTypeProp[ci.type, instancesProp, instances];
CP.PutCellInstanceProp[ci, containerProp, urCellType];
};
AddLocalConnection[actual, ci, NIL];
ENDLOOP;
SetUpLink[internal, NIL, urCellType, noIndex];
instanceStuffToo ← instanceStuffToo;
}};
AddLocalConnection: PROC [wire: Wire, ci: CellInstance, path: Path] ~ {
IF path = NIL THEN {
CP.PutWireProp[wire, seqProp, $TRUE];
}
ELSE {
connections: LocalConnectionList ← NARROW[CP.GetWireProp[wire, connectionsProp]];
IF ci = NIL THEN CP.PutWireProp[wire, publicIndexProp, path];
connections ← CONS[
NEW [LocalConnectionPrivate ← [NIL, ci, path]],
connections];
CP.PutWireProp[wire, connectionsProp, connections];
};
FOR i: Index IN [0 .. wire.size) DO
AddLocalConnection[wire[i], ci, ConsInner[i, path]];
ENDLOOP;
};
RemoveLocalConnections: PROC [wire: Wire] ~ {
CP.PutWireProp[wire, connectionsProp, NIL];
CP.PutWireProp[wire, publicIndexProp, NIL];
FOR i: Index IN [0 .. wire.size) DO
RemoveLocalConnections[wire[i]];
ENDLOOP;
};
SetUpLink: PROC [wire, parent: Wire, container: CellType, index: Index] ~ {
IF parent = NIL THEN {
CP.PutWireProp[wire, seqProp, $TRUE];
}
ELSE {
wul: WireUpLink ~ NEW [WireUpLinkPrivate ← [parent, index]];
CP.PutWireProp[wire, upWireProp, wul];
CP.PutWireProp[wire, containerProp, container];
};
FOR i: Index IN [0 .. wire.size) DO
SetUpLink[wire[i], wire, container, i];
ENDLOOP;
};
Repair: PUBLIC PROC [urCellType: CellType] = {
cellType: CellType;
recordCellType: RecordCellType;
[cellType, recordCellType] ← Simplify[urCellType];
ClearCellType[urCellType, cellType, recordCellType];
NoteCellType[urCellType, cellType, recordCellType, FALSE];
};
WireContainer: PUBLIC PROC [w: Wire] RETURNS [ct: CellType] = {
ct ← NARROW[CP.GetWireProp[w, containerProp]];
};
UpWire: PUBLIC PROC [w: --internal--Wire] RETURNS [parent: Wire, index: Index] ~ {
wul: WireUpLink ~ NARROW[CP.GetWireProp[w, upWireProp]];
RETURN [wul.parent, wul.index];
};
InstanceContainer: PUBLIC PROC [ci: CellInstance] RETURNS [ct: CellType] = {
ct ← NARROW[CP.GetCellInstanceProp[ci, containerProp]];
};
WirePublicity: PUBLIC PROC [w: Wire] RETURNS [public: BOOL, publicPath: Path] = {
x: Path ~ NARROW[CP.GetWireProp[w, publicIndexProp]];
IF x # NIL THEN RETURN [TRUE, x];
CheckWireSeq[w];
RETURN [FALSE, noPath];
};
IsInternal: PUBLIC PROC [w: Wire] RETURNS [internal: BOOL] = {
internal ← CP.GetWireProp[w, containerProp] # NIL;
};
IsWireSeq: PUBLIC PROC [ref: REF WireRec] RETURNS [BOOL] ~ {
WITH CP.GetWireProp[ref, upWireProp] SELECT FROM
wul: WireUpLink => RETURN [FALSE];
ENDCASE => SELECT CP.GetWireProp[ref, seqProp] FROM
$TRUE => RETURN [TRUE];
ENDCASE => ERROR;
};
CheckWireSeq: PUBLIC PROC [ref: REF WireRec, shouldBeSeq: BOOLFALSE] ~ {
IF IsWireSeq[ref] # shouldBeSeq THEN ERROR;
};
Atomic: PUBLIC PROC [cellType: CellType] RETURNS [atomic: BOOL] = {
atomic ← Simplify[cellType].recordCellType = NIL;
};
EnumeratorForLocalConnections: PUBLIC PROC [wire: Wire] RETURNS [e: Enumerator] = {
IF NOT IsInternal[wire] THEN ERROR;
e ← NEW [EnumeratorPrivate ← [EnumerateLocalConnections, wire]];
};
EnumerateLocalConnections: PUBLIC PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
ImmediateEnumerate: PROC [w: Wire, subscript: Path, prefix: LIST OF Index] ~ {
connections: LocalConnectionList ← NARROW[CP.GetWireProp[w, connectionsProp]];
FOR connections ← connections, connections.rest WHILE connections # NIL DO
lc: LocalConnection ← connections.first;
IF prefix#NIL OR subscript#NIL THEN {
lc ← NEW [LocalConnectionPrivate ← lc^];
FOR pl: LIST OF Index ← prefix, pl.rest WHILE pl # NIL DO
lc.publicPath ← CONS[pl.first, lc.publicPath];
ENDLOOP;
lc.subscript ← PathCat[subscript, lc.subscript];
};
Consumer[lc];
ENDLOOP;
};
DoChildren: PROC [w: Wire, subscript: Path] ~ {
FOR i: Index IN [0 .. w.size) DO
ss: Path ~ ConsInner[i, subscript];
ImmediateEnumerate[w[i], ss, NIL];
DoChildren[w[i], ss];
ENDLOOP;
};
w: Wire ← NARROW[data];
prefix: LIST OF Index ← NIL;
IF NOT IsInternal[w] THEN ERROR;
--do w and up--DO
ImmediateEnumerate[w, NIL, prefix];
{parent: Wire;
index: Index;
[parent, index] ← UpWire[w];
IF IsWireSeq[parent] THEN EXIT;
prefix ← CONS[index, prefix];
}ENDLOOP;
DoChildren[NARROW[data], NIL];
data ← data};
EnumeratorForSequences: PUBLIC PROC [cellType: CellType] RETURNS [Enumerator] ~ {
RETURN [NEW [EnumeratorPrivate ← [EnumerateSequences, cellType]]];
};
EnumerateSequences: PUBLIC PROC [data: REF ANY, Consumer: PROC [REF ANY]] ~ {
cellType: CellType ~ NARROW[data];
FOR seqs: CellTypeList ← NARROW[CP.GetCellTypeProp[cellType, seqsProp]], seqs.rest WHILE seqs # NIL DO
Consumer[seqs.first];
ENDLOOP;
data ← data;
};
EnumeratorForInstances: PUBLIC PROC [cellType: CellType] RETURNS [e: Enumerator] = {
e ← NEW [EnumeratorPrivate ← [EnumerateInstances, cellType]];
};
EnumerateInstances: PUBLIC PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
cellType: CellType = NARROW[data];
instances: InstanceList ← NARROW[CP.GetCellTypeProp[cellType, instancesProp]];
FOR instances ← instances, instances.rest WHILE instances # NIL DO
Consumer[instances.first];
ENDLOOP;
data ← data};
EnumeratorForGlobalInstances: PUBLIC PROC [cellType: CellType] RETURNS [e: Enumerator] = {
e ← NEW [EnumeratorPrivate ← [EnumerateGlobalInstances, cellType]];
};
EnumerateGlobalInstances: PUBLIC PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
cellType: CellType = NARROW[data];
Work: PROC [ct: CellType, tail: InstanceList] = {
instances: InstanceList ← NARROW[CP.GetCellTypeProp[cellType, instancesProp]];
SELECT TRUE FROM
instances = NIL => {--a root
Consumer[tail];
};
instances # NIL => {
FOR instances ← instances, instances.rest WHILE instances # NIL DO
ci: CellInstance = instances.first;
IF ci.type # ct THEN ERROR;
Work[InstanceContainer[ci], CONS[ci, tail]];
ENDLOOP;
};
ENDCASE => ERROR;
data ← data};
Work[cellType, NIL];
data ← data};
EnumeratorForWiresOfNode: PUBLIC PROC [wire: Wire] RETURNS [e: Enumerator] = {
IF NOT IsInternal[wire] THEN ERROR;
e ← NEW [EnumeratorPrivate ← [EnumerateWiresOfNode, wire]];
};
EnumerateWiresOfNode: PUBLIC PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
w: Wire = NARROW[data];
seen: RefTab.Ref = RefTab.Create[];
See: PROC [wire: Wire] = {
IF NOT seen.Insert[wire, $T] THEN RETURN;
IF NOT IsInternal[wire] THEN ERROR;
Consumer[wire];
-- look upward-- {
publicPath: Path = WirePublicity[wire].publicPath;
SeeUpper: PROC [ra: REF ANY] = {
uci: CellInstance = NARROW[ra];
See[SubWire[uci.actual, publicPath]]
};
IF publicPath # noPath THEN EnumerateInstances[WireContainer[wire], SeeUpper];
};
-- look downard -- {
SeeDown: PROC [ra: REF ANY] = {
lc: LocalConnection = NARROW[ra];
IF NOT Atomic[lc.ci.type] THEN See[SubWire[lc.ci.type.public, lc.publicPath]];
};
EnumerateLocalConnections[wire, SeeDown];
};
};
See[w];
seen.Erase[];
data ← data};
EnumeratorForLeafConnections: PUBLIC PROC [wire: Wire] RETURNS [e: Enumerator] = {
IF NOT IsInternal[wire] THEN ERROR;
e ← NEW [EnumeratorPrivate ← [EnumerateLeafConnections, wire]];
};
EnumerateLeafConnections: PUBLIC PROC [data: REF ANY, Consumer: PROC [REF ANY]] = {
w: Wire = NARROW[data];
PerWire: PROC [ra: REF ANY] = {
wire: Wire = NARROW[ra];
PerLocalConnection: PROC [ra: REF ANY] = {
lc: LocalConnection = NARROW[ra];
IF Atomic[lc.ci.type] THEN Consumer[lc];
};
EnumerateLocalConnections[wire, PerLocalConnection];
};
EnumerateWiresOfNode[w, PerWire];
data ← data};
PrintTable: PUBLIC PROC [to: IO.STREAM, table: RefTab.Ref] ~ {
sep: ROPENIL;
PrintPair: PROC [key, val: REF ANY] RETURNS [quit: BOOLFALSE] --RefTab.EachPairAction-- ~ {
name: ROPE ~ NARROW[key];
to.PutRope[sep];
to.PutRope[name];
sep ← ", ";
};
IF table.Pairs[PrintPair] THEN ERROR;
};
END.