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: BOOL ← TRUE;
grandChildAnsss: GrandChildAnsSS;
dif: BOOL ← FALSE;
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: BOOL ← FALSE;
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:
BOOL ←
FALSE;
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: LORA ← LIST[$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: BOOL ← FALSE];
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: BOOL ← FALSE;
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:
BOOL ←
FALSE;
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: BOOL ← TRUE;
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: ROPE ← NARROW[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: BOOL ← FALSE,
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: BOOL ← TRUE;
DO
st: SymbolTable;
someCollided: BOOL ← FALSE;
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.