LichenChildishTransforms.Mesa
Last Edited by: Spreitzer, July 15, 1985 7:34:50 pm PDT
DIRECTORY Basics, DFUtilities, FS, IO, LichenDataStructure, LichenOps, LichenTransforms, LichenTransformsPrivate, RedBlackTree, RedBlackTreeExtras, RefTab, Rope, ViewerIO;
LichenChildishTransforms: CEDAR PROGRAM
IMPORTS IO, LichenOps, LichenTransformsPrivate, RedBlackTree, RedBlackTreeExtras, RefTab, Rope
EXPORTS LichenTransforms =
BEGIN OPEN LichenDataStructure, LichenTransforms, LichenOps, LichenTransformsPrivate;
KeepPort: NAT = LAST[NAT] - 1;
LowerChildren: PUBLIC PROC [design: Design, childTypeA: REF ANY, gcNamesl: NamesList, sibber: Mapper--child => siblings--, newPortNamer: NewPortNamer] RETURNS [gcs: VertexS, children: VertexList] =
BEGIN
gcNamess: NamesS ← ToNamesS[gcNamesl];
childType: CellType ← ToType[design, childTypeA];
gcTypes: CellTypeS ← NIL;
first: BOOLTRUE;
grandChildAnsss: GrandChildAnsSS;
dif: BOOLFALSE;
oldPorts: PortS ← childType.ports;
childAnses: ChildAnses ← NEW [ChildAnsesRep[oldPorts.length]];
losses, gains, remains, newChildPortIndex: NAT ← 0;
oldGCConnectionss: VertexSS--gcPortIndex--;
oldNetToConnections: RefTab.Ref;
Survey: PROC [child: Vertex, sibs: VertexS] = {
IF first THEN {
connectionCount: INT ← 0;
grandChildAnsss ← NEW [GrandChildAnsSSeq[sibs.length]];
oldGCConnectionss ← NEW [VertexSSeq[sibs.length]];
gcTypes ← NEW [CellTypeSeq[sibs.length]];
FOR i: NAT IN [0 .. sibs.length) DO
gcTypes[i] ← sibs[i].type;
connectionCount ← connectionCount + gcTypes[i].ports.length;
ENDLOOP;
oldNetToConnections ← RefTab.Create[connectionCount];
};
IF sibs.length # gcTypes.length THEN {
Warn[[], "Different number of siblings (%g, rather than %g) at %g", IO.card[sibs.length], IO.card[gcTypes.length], IO.refAny[GlobalVertexName[child]]];
dif ← TRUE}
ELSE FOR i: NAT IN [0 .. sibs.length) DO
IF sibs[i].type # gcTypes[i] THEN {
Warn[[], "%g is a %g, not a %g", IO.refAny[GlobalVertexName[sibs[i]]], IO.refAny[PickAName[sibs[i].type.names]], IO.refAny[PickAName[gcTypes[i].names]]];
dif ← TRUE}
ELSE IF sibs[i] = child THEN {
Warn[[], "Child %g sibbed to itself", IO.refAny[GlobalVertexName[child]]];
dif ← TRUE}
ELSE {
gcPortIndex: NAT ← 0;
IF first THEN {
oldGCConnectionss[i] ← NEW [VertexSeq[gcTypes[i].ports.length]];
grandChildAnsss[i] ← NEW [GrandChildAnsSeq[gcTypes[i].ports.length]];
FOR gcpi: NAT IN [0 .. grandChildAnsss[i].length) DO
grandChildAnsss[i][gcpi] ← [sawSelves: NEW [BoolSeq[sibs.length]]];
ENDLOOP};
FOR e: Edge ← sibs[i].firstEdge, e.sides[cell].next WHILE e # NIL DO
sawBord, sawBords, sawElse: BOOLFALSE;
sawSelves: BoolS ← NEW [BoolSeq[sibs.length]];
net: Vertex ← e.sides[net].v;
FOR i: NAT IN [0 .. sibs.length) DO sawSelves[i] ← FALSE ENDLOOP;
IF e.sides[cell].v # sibs[i] THEN ERROR;
FOR f: Edge ← net.firstEdge, f.sides[net].next WHILE f # NIL DO
IF f.sides[net].v # net THEN ERROR;
IF f.sides[cell].v = child THEN {
sawBords ← sawBord;
sawBord ← TRUE;
grandChildAnsss[i][gcPortIndex].oldChildPortIndex ← f.portIndex;
}
ELSE {sawSomeSelf: BOOLFALSE;
FOR j: NAT IN [0 .. sibs.length) DO
IF f.sides[cell].v = sibs[j] THEN sawSomeSelf ← sawSelves[j] ← TRUE;
ENDLOOP;
IF NOT sawSomeSelf THEN sawElse ← TRUE
ELSE IF first THEN {
selfEdges: EdgeList ← NARROW[oldNetToConnections.Fetch[net].val];
selfEdges ← CONS[f, selfEdges];
[] ← oldNetToConnections.Store[net, selfEdges];
};
};
ENDLOOP;
IF NOT sawSelves[i] THEN ERROR;
IF first THEN {
grandChildAnsss[i][gcPortIndex].sawBord ← sawBord;
grandChildAnsss[i][gcPortIndex].sawBords ← sawBords;
grandChildAnsss[i][gcPortIndex].sawElse ← sawElse;
grandChildAnsss[i][gcPortIndex].sawSelves ← sawSelves;
IF sawBord AND NOT (sawElse OR sawBords) THEN {
losses ← NoteLoss[netMapper, net, losses];
childAnses[grandChildAnsss[i][gcPortIndex].oldChildPortIndex].newPortIndex ← NullPortIndex;
};
IF sawElse AND NOT sawBord THEN gains ← NoteGain[netMapper, net, gains];
oldGCConnectionss[i][gcPortIndex] ← net;
}
ELSE {
Dif: PROC = {Warn[[], "%g & %g are connected differently than the first pair", IO.refAny[GlobalVertexName[child]], IO.refAny[GlobalVertexName[sibs[i]]]]; dif ← TRUE};
IF grandChildAnsss[i][gcPortIndex].sawBord # sawBord THEN Dif[];
IF grandChildAnsss[i][gcPortIndex].sawBords # sawBords THEN Dif[];
IF grandChildAnsss[i][gcPortIndex].sawElse # sawElse THEN Dif[];
FOR j: NAT IN [0 .. sibs.length) DO
IF grandChildAnsss[i][gcPortIndex].sawSelves[j] # sawSelves[j] THEN Dif[];
ENDLOOP};
gcPortIndex ← gcPortIndex + 1;
ENDLOOP;
};
ENDLOOP;
first ← FALSE;
};
newPorts: PortS;
newPortIndex: NAT ← 0;
inside: VertexS--oldChildIndex--NEW [VertexSeq[oldPorts.length]];
insideEdge: Edge;
parentTypes: RefTab.Ref ← RefTab.Create[];
netMapper: RefTab.Ref ← RefTab.Create[];
portNameNotes: SymbolTable ← RedBlackTree.Create[GetNameEntryKey, CompareNameEntries];
portClassNotes: SymbolTable ← RedBlackTree.Create[GetNameEntryKey, CompareNameEntries];
children ← NIL;
IF KeepPort = NullPortIndex THEN ERROR;
FOR e: Edge ← childType.mirror.firstEdge, e.sides[cell].next WHILE e # NIL DO
IF e.sides[cell].v # childType.mirror THEN ERROR;
inside[e.portIndex] ← e.sides[net].v;
ENDLOOP;
FOR ocpi: NAT IN [0 .. oldPorts.length) DO
childAnses[ocpi] ← [newPortIndex: KeepPort];
ENDLOOP;
FOR child: Vertex ← childType.firstInstance, child.nextInstance WHILE child # NIL DO
sibsAsAny: REF ANY;
IF IsMirror[child] THEN ERROR; --AM2
sibsAsAny ← sibber.map[sibber.data, child];
IF sibsAsAny = NIL
THEN {Warn[[], "No siblings given for %g", IO.rope[GlobalVertexName[child]]]; dif ← TRUE}
ELSE WITH sibsAsAny SELECT FROM
vs: VertexS => Survey[child, vs];
ENDCASE => {Warn[[], "Siblings for %g should be a CompareTransforms.VertexS, not %g", IO.rope[GlobalVertexName[child]], IO.refAny[sibsAsAny]]; dif ← TRUE};
ENDLOOP;
IF first OR dif THEN RETURN [NIL, NIL];
NoteChange[childType];
gcs ← NEW [VertexSeq[gcTypes.length]];
FOR i: NAT IN [0 .. gcs.length) DO
gcs[i] ← NEW [VertexRep ← [names: gcNamess[i], type: gcTypes[i], parent: childType, class: cell]];
AddVertex[gcs[i]]; LinkInstance[gcs[i]];
ENDLOOP;
remains ← oldPorts.length - losses;
newPorts ← NEW [PortSeq[remains + gains]];
insideEdge ← childType.mirror.firstEdge;
FOR oldPortIndex: NAT IN [0 .. oldPorts.length) DO
nextInsideEdge: Edge ← insideEdge.sides[cell].next;
IF insideEdge.sides[cell].v # childType.mirror THEN ERROR;
IF insideEdge.portIndex # oldPortIndex THEN ERROR;
SELECT childAnses[oldPortIndex].newPortIndex FROM
KeepPort => {
newPorts[newChildPortIndex] ← oldPorts[oldPortIndex];
childAnses[oldPortIndex].newPortIndex ← newChildPortIndex;
insideEdge.portIndex ← newChildPortIndex;
newChildPortIndex ← newChildPortIndex + 1};
NullPortIndex => RemoveEdge[insideEdge];
ENDCASE => ERROR;
insideEdge ← nextInsideEdge;
ENDLOOP;
IF insideEdge # NIL THEN ERROR;
IF newChildPortIndex # remains THEN ERROR;
FOR i: NAT IN [0 .. gcs.length) DO
FOR gcIndex: NAT IN [0 .. gcTypes[i].ports.length) DO
AddPort: PROC RETURNS [insideNet: Vertex] = {
outsideNet: Vertex ← oldGCConnectionss[i][gcIndex];
insideAsAny: REF ANY ← netMapper.Fetch[outsideNet].val;
IF insideAsAny = NIL THEN ERROR;
IF ISTYPE[insideAsAny, Vertex] THEN RETURN [NARROW[insideAsAny]];
IF insideAsAny # $AddPort THEN ERROR;
insideNet ← NEW [VertexRep ← [names: outsideNet.names, parent: childType, class: net]];
AddVertex[insideNet];
newPorts[newChildPortIndex] ← [netNames: LIST[PickAName[insideNet.names]]];
[newPorts[newChildPortIndex].names, newPorts[newChildPortIndex].equivClass] ← newPortNamer.NameNewPort[newPortNamer.data, TRUE, childType, newPorts, newChildPortIndex, outsideNet, NARROW[oldNetToConnections.Fetch[outsideNet].val]];
NoteNaming[portNameNotes, portClassNotes, newPorts, newChildPortIndex, outsideNet, NARROW[oldNetToConnections.Fetch[outsideNet].val]];
grandChildAnsss[i][gcIndex].newChildPortIndex ← newChildPortIndex;
AddEdge[childType.mirror, insideNet];
newChildPortIndex ← newChildPortIndex + 1;
[] ← netMapper.Store[outsideNet, insideNet];
};
MakeDummy: PROC RETURNS [insideNet: Vertex] = {
insideNet ← NARROW[netMapper.Fetch[oldGCConnectionss[i][gcIndex]].val];
IF insideNet # NIL THEN RETURN;
insideNet ← NEW [VertexRep ← [names: oldGCConnectionss[i][gcIndex].names, parent: childType, class: net]];
AddVertex[insideNet];
IF NOT netMapper.Store[oldGCConnectionss[i][gcIndex], insideNet] THEN ERROR;
};
AddEdge[gcs[i], IF grandChildAnsss[i][gcIndex].sawBord THEN inside[grandChildAnsss[i][gcIndex].oldChildPortIndex] ELSE IF grandChildAnsss[i][gcIndex].sawElse THEN AddPort[] ELSE MakeDummy[]];
ENDLOOP;
ENDLOOP;
IF newChildPortIndex # newPorts.length THEN ERROR;
FixNames[childType, newPorts, remains, newPortNamer, portNameNotes, portClassNotes];
childType.ports ← newPorts;
CheckType[childType, check, ignore, TRUE];
FOR child: Vertex ← childType.firstInstance, child.nextInstance WHILE child # NIL DO
sibs: VertexS;
IF IsMirror[child] THEN ERROR; --AM2
children ← CONS[child, children];
sibs ← NARROW[sibber.map[sibber.data, child]];
IF sibs.length # gcs.length THEN ERROR --caller blew it--;
FOR i: NAT IN [0 .. sibs.length) DO
IF sibs[i].parent # child.parent THEN ERROR --caller blew it--;
WHILE sibs[i].firstEdge # NIL DO
e: Edge ← sibs[i].firstEdge;
net: Vertex ← e.sides[net].v;
gcPortIndex: NAT ← e.portIndex;
IF grandChildAnsss[i][gcPortIndex].sawElse AND NOT grandChildAnsss[i][gcPortIndex].sawBord THEN {
any: REF ANY ← netMapper.Fetch[oldGCConnectionss[i][gcPortIndex]].val;
IF any # child THEN {
AddEdge[child, net];
[] ← netMapper.Store[oldGCConnectionss[i][gcPortIndex], child]};
};
IF NOT (grandChildAnsss[i][gcPortIndex].sawElse OR grandChildAnsss[i][gcPortIndex].sawBords) THEN DeleteVertex[net] ELSE RemoveEdge[e];
ENDLOOP;
DeleteVertex[sibs[i]];
ENDLOOP;
NoteChange[child.parent];
IF losses>0 THEN RenumberOutsideEdges[child];
[] ← parentTypes.Store[child.parent, chig];
ENDLOOP;
[] ← parentTypes.Pairs[CheckPerType];
END;
chig: LORALIST[$check, $ignore];
ChildAnses: TYPE = REF ChildAnsesRep;
ChildAnsesRep: TYPE = RECORD [SEQUENCE--oldChildIndex-- length: NAT OF ChildAns];
ChildAns: TYPE = RECORD [newPortIndex: NAT];
GrandChildAnsSS: TYPE = REF GrandChildAnsSSeq;
GrandChildAnsSSeq: TYPE = RECORD [
SEQUENCE length: CARDINAL OF GrandChildAnsS];
GrandChildAnsS: TYPE = REF GrandChildAnsSeq;
GrandChildAnsSeq: TYPE = RECORD [
SEQUENCE--gcPortIndex-- length: PortIndex OF GrandChildAns];
GrandChildAns: TYPE = RECORD [
sawSelves: BoolS,
oldChildPortIndex, newChildPortIndex: PortIndex ← NullPortIndex,
sawBord, sawBords, sawElse: BOOLFALSE];
RaiseGrandchildren: PUBLIC PROC [design: Design, gcsA: REF ANY, newPortNamer: NewPortNamer] RETURNS [newChildrens: VertexSList] =
BEGIN
gcs: VertexS ← ToVertexS[design, gcsA];
childType: CellType ← gcs[0].parent;
oldPorts: PortS ← childType.ports;
newPorts: PortS;
inside: VertexS--oldChildIndex--NEW [VertexSeq[oldPorts.length]];
oldGCConnectionss: VertexSS--gcPortIndex--NEW [VertexSSeq[gcs.length]];
losses, gains, remains, gcPortIndex, newChildPortIndex: NAT ← 0;
childAnses: ChildAnses ← NEW [ChildAnsesRep[oldPorts.length]];
grandChildAnsss: GrandChildAnsSS ← NEW [GrandChildAnsSSeq[gcs.length]];
parentTypes: RefTab.Ref ← RefTab.Create[];
netMapper: RefTab.Ref ← RefTab.Create[];
oldNetToConnections: RefTab.Ref;
portNameNotes: SymbolTable ← RedBlackTree.Create[GetNameEntryKey, CompareNameEntries];
portClassNotes: SymbolTable ← RedBlackTree.Create[GetNameEntryKey, CompareNameEntries];
newChildrens ← NIL;
FOR p: NAT IN [0 .. inside.length) DO inside[p] ← NIL ENDLOOP;
Estimate number of connected nets:
{connectionCount: INT ← 0;
FOR i: NAT IN [0 .. gcs.length) DO
connectionCount ← connectionCount + gcs[i].type.ports.length;
ENDLOOP;
oldNetToConnections ← RefTab.Create[connectionCount];
};
FOR i: NAT IN [0 .. gcs.length) DO
oldGCConnectionss[i] ← NEW [VertexSeq[gcs[i].type.ports.length]];
grandChildAnsss[i] ← NEW [GrandChildAnsSeq[gcs[i].type.ports.length]];
FOR p: NAT IN [0 .. grandChildAnsss[i].length) DO grandChildAnsss[i][p] ← [] ENDLOOP;
IF gcs[i].parent = gcs[i].type THEN ERROR;
IF gcs[i].parent # childType THEN ERROR;
gcPortIndex ← 0;
FOR e: Edge ← gcs[i].firstEdge, e.sides[cell].next WHILE e # NIL DO
sawBord, sawBords, sawElse: BOOLFALSE;
sawSelves: BoolS ← NEW [BoolSeq[gcs.length]];
net: Vertex ← e.sides[net].v;
IF e.sides[cell].v # gcs[i] THEN ERROR;
oldGCConnectionss[i][gcPortIndex] ← net;
FOR f: Edge ← net.firstEdge, f.sides[net].next WHILE f # NIL DO
IF f.sides[net].v # net THEN ERROR;
IF IsMirror[f.sides[cell].v] THEN {
sawBords ← sawBord;
sawBord ← TRUE;
grandChildAnsss[i][gcPortIndex].oldChildPortIndex ← f.portIndex;
IF (inside[f.portIndex] # NIL) AND (inside[f.portIndex] # net) THEN ERROR ELSE inside[f.portIndex] ← net}
ELSE {sawSomeSelves: BOOLFALSE;
FOR j: NAT IN [0 .. gcs.length) DO
IF f.sides[cell].v = gcs[j] THEN sawSomeSelves ← sawSelves[j] ← TRUE;
ENDLOOP;
IF NOT sawSomeSelves THEN sawElse ← TRUE
ELSE {
selfEdges: EdgeList ← NARROW[oldNetToConnections.Fetch[net].val];
selfEdges ← CONS[f, selfEdges];
[] ← oldNetToConnections.Store[net, selfEdges];
};
};
ENDLOOP;
IF NOT sawSelves[i] THEN ERROR;
grandChildAnsss[i][gcPortIndex].sawBord ← sawBord;
grandChildAnsss[i][gcPortIndex].sawBords ← sawBords;
grandChildAnsss[i][gcPortIndex].sawElse ← sawElse;
grandChildAnsss[i][gcPortIndex].sawSelves ← sawSelves;
IF (net.suspect ← (sawBord AND NOT (sawElse OR sawBords))) THEN losses ← NoteLoss[netMapper, net, losses];
IF sawElse AND NOT sawBord THEN gains ← NoteGain[netMapper, net, gains];
gcPortIndex ← gcPortIndex + 1;
ENDLOOP;
IF gcPortIndex # gcs[i].type.ports.length THEN ERROR;
ENDLOOP;
remains ← oldPorts.length - losses;
newPorts ← NEW [PortSeq[remains + gains]];
newChildPortIndex ← 0;
FOR cpi: NAT IN [0 .. oldPorts.length) DO
keep: BOOLTRUE;
IF inside[cpi] # NIL THEN {
keep ← NOT inside[cpi].suspect;
inside[cpi].suspect ← FALSE};
childAnses[cpi].newPortIndex ← IF keep THEN newChildPortIndex ELSE NullPortIndex;
IF keep THEN {
newPorts[newChildPortIndex] ← oldPorts[cpi];
newChildPortIndex ← newChildPortIndex + 1};
ENDLOOP;
IF newChildPortIndex # remains THEN ERROR;
FOR i: NAT IN [0 .. gcs.length) DO
FOR e: Edge ← gcs[i].firstEdge, e.sides[cell].next WHILE e # NIL DO
net: Vertex ← e.sides[net].v;
gcPortIndex: NAT ← e.portIndex;
IF e.sides[cell].v # gcs[i] THEN ERROR;
IF grandChildAnsss[i][gcPortIndex].sawElse AND NOT grandChildAnsss[i][gcPortIndex].sawBord THEN {
IF oldGCConnectionss[i][gcPortIndex] # net THEN ERROR;
SELECT netMapper.Fetch[net].val FROM
$AddPorted => NULL;
$AddPort => {
newPorts[newChildPortIndex] ← [netNames: LIST[PickAName[net.names]]];
[newPorts[newChildPortIndex].names, newPorts[newChildPortIndex].equivClass] ← newPortNamer.NameNewPort[newPortNamer.data, TRUE, childType, newPorts, newChildPortIndex, net, NARROW[oldNetToConnections.Fetch[net].val]];
NoteNaming[portNameNotes, portClassNotes, newPorts, newChildPortIndex, net, NARROW[oldNetToConnections.Fetch[net].val]];
grandChildAnsss[i][gcPortIndex].newChildPortIndex ← newChildPortIndex;
AddEdge[childType.mirror, net];
newChildPortIndex ← newChildPortIndex + 1;
[] ← netMapper.Store[net, $AddPorted]};
ENDCASE => ERROR;
};
ENDLOOP;
ENDLOOP;
IF newChildPortIndex # newPorts.length THEN ERROR;
FixNames[childType, newPorts, remains, newPortNamer, portNameNotes, portClassNotes];
NoteChange[childType];
childType.ports ← newPorts;
FOR i: NAT IN [0 .. gcs.length) DO
WHILE gcs[i].firstEdge # NIL DO
e: Edge ← gcs[i].firstEdge;
net: Vertex ← e.sides[net].v;
gcPortIndex: NAT ← e.portIndex;
IF NOT (grandChildAnsss[i][gcPortIndex].sawElse OR grandChildAnsss[i][gcPortIndex].sawBords) THEN DeleteVertex[net] ELSE RemoveEdge[e];
ENDLOOP;
DeleteVertex[gcs[i]];
ENDLOOP;
IF losses>0 THEN RenumberInsideEdges[childType];
CheckType[childType, check, ignore, TRUE];
FOR child: Vertex ← childType.firstInstance, child.nextInstance WHILE child # NIL DO
sibs: VertexS ← NEW [VertexSeq[gcs.length]];
oldNets: VertexS--oldChildIndex--NEW [VertexSeq[oldPorts.length]];
newNets: VertexS--Gain--NEW [VertexSeq[gains]];
oldChildIndex, newChildIndex: NAT ← 0;
nextChildEdge: Edge ← badEdge;
IF IsMirror[child] THEN ERROR; --AM2
FOR i: NAT IN [0 .. sibs.length) DO
sibs[i] ← NEW [VertexRep ← [names: JoinNames[child.names, gcs[i].names], type: gcs[i].type, parent: child.parent, class: cell]];
AddVertex[sibs[i]];
LinkInstance[sibs[i]];
ENDLOOP;
FOR ce: Edge ← child.firstEdge, nextChildEdge WHILE ce # NIL DO
nextChildEdge ← ce.sides[cell].next;
oldNets[oldChildIndex] ← ce.sides[net].v;
IF ce.portIndex # oldChildIndex THEN ERROR;
IF (childAnses[oldChildIndex].newPortIndex # NullPortIndex)
THEN {
IF newChildIndex # childAnses[oldChildIndex].newPortIndex THEN ERROR;
newChildIndex ← (ce.portIndex ← newChildIndex) + 1}
ELSE RemoveEdge[ce];
oldChildIndex ← oldChildIndex + 1;
ENDLOOP;
IF newChildIndex # oldPorts.length - losses THEN ERROR;
FOR newChildIndex IN [newChildIndex .. newPorts.length) DO
innerNet: Vertex ← NARROW[Lookup[child.type.parts, newPorts[newChildIndex].netNames.first]];
outerNet: Vertex ← NEW [VertexRep ← [names: JoinNames[child.names, innerNet.names], parent: child.parent, class: net]];
AddVertex[outerNet];
AddEdge[child, outerNet];
newNets[newChildIndex - remains] ← outerNet;
ENDLOOP;
FOR i: NAT IN [0 .. gcs.length) DO
FOR ci: NAT IN [0 .. gcs[i].type.ports.length) DO
MakeDummyNet: PROC [iNet: Vertex] RETURNS [oNet: Vertex] = {
oNet ← NARROW[netMapper.Fetch[iNet].val];
IF oNet = NIL OR oNet.parent # child.parent THEN {
oNet ← NEW [VertexRep ← [names: JoinNames[child.names, iNet.names], parent: child.parent, class: net]];
AddVertex[oNet];
[] ← netMapper.Store[iNet, oNet];
};
};
AddEdge[
sibs[i],
IF grandChildAnsss[i][ci].sawBord
THEN oldNets[grandChildAnsss[i][ci].oldChildPortIndex]
ELSE IF grandChildAnsss[i][ci].sawElse
THEN newNets[grandChildAnsss[i][ci].newChildPortIndex - remains]
ELSE MakeDummyNet[oldGCConnectionss[i][ci]]];
ENDLOOP;
ENDLOOP;
NoteChange[child.parent];
[] ← parentTypes.Store[child.parent, chig];
newChildrens ← CONS[sibs, newChildrens];
ENDLOOP;
[] ← parentTypes.Pairs[CheckPerType];
END;
NoteLoss: PROC [netMapper: RefTab.Ref, net: Vertex, oldLosses: CARDINAL] RETURNS [newLosses: CARDINAL] = {
m: REF ANY ← netMapper.Fetch[net].val;
newLosses ← oldLosses;
SELECT m FROM
NIL => {newLosses ← newLosses + 1; [] ← netMapper.Store[net, $DePort]};
$DePort => NULL;
ENDCASE => ERROR;
};
NoteGain: PROC [netMapper: RefTab.Ref, net: Vertex, oldGains: CARDINAL] RETURNS [newGains: CARDINAL] = {
m: REF ANY ← netMapper.Fetch[net].val;
newGains ← oldGains;
SELECT m FROM
NIL => {newGains ← newGains + 1; [] ← netMapper.Store[net, $AddPort]};
$AddPort => NULL;
ENDCASE => ERROR;
};
NameEntry: TYPE = REF NameEntryRep;
NameEntryRep: TYPE = RECORD [name: ROPE, sources: PortNameSourceList];
PortNameSourceList: TYPE = LIST OF PortNameSource;
PortNameSource: TYPE = RECORD [
index: NAT,
oldNet: Vertex,
oldConnections: EdgeList];
GetNameEntryKey: PROC [data: REF ANY] RETURNS [key: ROPE] --RedBlackTree.GetKey-- = {
ne: NameEntry ← NARROW[data]; key ← ne.name};
CompareNameEntries: PROC [k, data: REF ANY] RETURNS [c: Basics.Comparison] --RedBlackTree.Compare-- = {
k1: ROPENARROW[k];
k2: ROPE ← GetNameEntryKey[data];
c ← k1.Compare[k2];
};
NoteNaming: PROC [portNameNotes, portClassNotes: SymbolTable, ports: PortS, index: NAT, oldNet: Vertex, oldConnections: EdgeList] = {
DoName: PROC [name: ROPE, st: SymbolTable] = {
ne: NameEntry ← NARROW[st.Lookup[name]];
IF ne = NIL THEN st.Insert[ne ← NEW [NameEntryRep ← [name, NIL]], name];
ne.sources ← CONS[[index, oldNet, oldConnections], ne.sources];
};
DoList: PROC [rl: RopeList] = {
FOR rl ← rl, rl.rest WHILE rl # NIL DO DoName[rl.first, portNameNotes] ENDLOOP;
};
DoList[ports[index].names.designed];
DoList[ports[index].names.unknown];
DoList[ports[index].names.progged];
DoName[ports[index].equivClass, portClassNotes];
};
NameStuffs: TYPE = REF NameStuffSeq;
NameStuffSeq: TYPE = RECORD [stuffs: SEQUENCE length: CARDINAL OF NameStuff];
NameStuff: TYPE = RECORD [
collided: BOOLFALSE,
oldNet: Vertex ← NIL,
oldConnections: EdgeList ← NIL];
FixNames: PROC [cellType: CellType, ports: PortS, firstIndex: NAT, newPortNamer: NewPortNamer, portNameNotes, portClassNotes: SymbolTable] = {
indices: NAT ← ports.length - firstIndex;
ns: NameStuffs ← NEW [NameStuffSeq[indices]];
first: BOOLTRUE;
DO
st: SymbolTable;
someCollided: BOOLFALSE;
PerName: PROC [ra: REF ANY] RETURNS [stop: BOOL] = {
ne: NameEntry ← NARROW[ra];
IF ne.sources.rest # NIL THEN {
IF st.Delete[ne].data # ne THEN ERROR;
FOR pnsl: PortNameSourceList ← ne.sources, pnsl.rest WHILE pnsl # NIL DO
di: NAT ← pnsl.first.index - firstIndex;
IF ns[di].collided AND (ns[di].oldNet # pnsl.first.oldNet OR ns[di].oldConnections # pnsl.first.oldConnections) THEN ERROR;
ns[di] ← [TRUE, pnsl.first.oldNet, pnsl.first.oldConnections];
someCollided ← TRUE;
ENDLOOP;
};
};
FOR di: NAT IN [0 .. indices) DO ns[di].collided ← FALSE ENDLOOP;
RedBlackTreeExtras.StatelessEnumerateIncreasing[(st ← portNameNotes), PerName, GetNameEntryKey];
RedBlackTreeExtras.StatelessEnumerateIncreasing[(st ← portClassNotes), PerName, GetNameEntryKey];
IF NOT someCollided THEN RETURN;
IF NOT first THEN ERROR;
FOR di: NAT IN [0 .. indices) DO
IF ns[di].collided THEN {
newNames: Names;
newEquivClass: EquivClass;
[newNames, newEquivClass] ← newPortNamer.NameNewPort[data: newPortNamer.data, first: FALSE, ct: cellType, ports: ports, portIndex: firstIndex+di, oldNet: ns[di].oldNet, oldConnections: ns[di].oldConnections];
NoteNaming[portNameNotes, portClassNotes, ports, firstIndex+di, ns[di].oldNet, ns[di].oldConnections];
};
ENDLOOP;
first ← FALSE;
ENDLOOP;
};
RenumberInsideEdges: PROC [ct: CellType] = {
portIndex: NAT ← 0;
FOR e: Edge ← ct.mirror.firstEdge, e.sides[cell].next WHILE e # NIL DO
IF e.sides[cell].v # ct.mirror THEN ERROR;
IF e.portIndex < portIndex THEN ERROR;
e.portIndex ← portIndex;
portIndex ← portIndex + 1;
ENDLOOP;
};
RenumberOutsideEdges: PROC [v: Vertex] = {
portIndex: NAT ← 0;
FOR e: Edge ← v.firstEdge, e.sides[cell].next WHILE e # NIL DO
IF e.sides[cell].v # v THEN ERROR;
IF e.portIndex < portIndex THEN ERROR;
e.portIndex ← portIndex;
portIndex ← portIndex + 1;
ENDLOOP;
};
END.