CompareTransforms.Mesa
Last Edited by: Spreitzer, November 12, 1984 8:40:10 am PST
DIRECTORY Basics, CompareDataStructure, CompareOps, DFUtilities, FS, IO, List, OrderedSymbolTableRef, RefTab, Rope, ViewerIO;
CompareTransforms: CEDAR PROGRAM
IMPORTS CompareDataStructure, CompareOps, IO, OrderedSymbolTableRef, RefTab, Rope
EXPORTS CompareOps =
BEGIN OPEN CompareDataStructure, CompareOps;
--Not YET implemented-- nyet: ERROR = CODE;
Error: ERROR [format: ROPE, v1, v2, v3, v4, v5: IO.Value ← [null[]]] = CODE;
Differentiate: PROC [design: Design, newNames: Names, instances: REF ANY] RETURNS [newCT: CellType] =
BEGIN
oldCT: CellType ← NIL;
vl: LORANIL;
ConsumeInstance: PROC [v: Vertex] = {
IF oldCT = NIL THEN oldCT ← v.type ELSE IF oldCT # v.type THEN Err[[], "%g of type %g, not %g", IO.rope[PickAName[v.names]], IO.rope[PickAName[v.type.names]], IO.rope[PickAName[oldCT.names]]];
vl ← CONS[v, vl]};
EnumerateInstances[design, instances, ConsumeInstance];
newCT ← NEW [CellTypeRep ← [design: design, names: newNames, file: NIL, publicKnown: TRUE, privateKnown: TRUE, ports: CopyPorts[oldCT.ports], parts: NIL]];
CopyParts[newCT, oldCT];
FOR vl ← vl, vl.rest WHILE vl # NIL DO
ChangeType[v: NARROW[vl.first], from: oldCT, to: newCT];
ENDLOOP;
END;
Undifferentiate: PROC [design: Design, toType: CellType, fromTypes: REF ANY] RETURNS [changed: VertexList] =
BEGIN
oldTypes: LIST OF CellType ← NIL;
oldCount: NAT ← 0;
ConsumeType: PROC [ct: CellType] = {
oldTypes ← CONS[ct, oldTypes];
oldCount ← oldCount + 1};
EnumerateCellTypes[design, fromTypes, ConsumeType];
FOR oldTypes ← oldTypes, oldTypes.rest WHILE oldTypes # NIL DO
WHILE oldTypes.first.firstInstance # NIL DO
v: Vertex ← oldTypes.first.firstInstance;
IF IsMirror[v] THEN ERROR; --AM2
ChangeType[v: v, from: oldTypes.first, to: toType];
changed ← CONS[v, changed];
ENDLOOP;
DeleteType[design, oldTypes.first];
ENDLOOP;
END;
CreateEmpty: PROC [design: Design, childNames: Names, childType, parentType: CellType] RETURNS [child: Vertex] =
BEGIN
child ← NEW [VertexRep ← [names: childNames, type: childType, parent: parentType, class: component]];
IF NOT IsEmpty[childType] THEN Err[[], "Asked to create empty child %g of non-empty type %g in %g", IO.refAny[PickAName[childNames]], IO.refAny[PickAName[childType.names]], IO.refAny[PickAName[parentType.names]]];
LinkInstance[child];
AddVertex[child];
NoteChange[child.parent];
END;
DeleteEmpty: PROC [design: Design, child: Vertex] RETURNS [parentType: CellType] =
BEGIN
parentType ← child.parent;
IF NOT IsEmpty[child.type] THEN Err[[], "Child %g in %g is of a non-empty type (%g)", IO.rope[PickAName[child.names]], IO.rope[PickAName[child.parent.names]], IO.rope[PickAName[child.type.names]]];
IF child.firstEdge # NIL OR child.lastEdge # NIL THEN ERROR;
NoteChange[child.parent];
DeleteVertex[child];
END;
KeepPort: NAT = LAST[NAT] - 1;
LowerChild: PROC [design: Design, childTypeA: REF ANY, gcNames: Names, sibber: Mapper--child => sibling--, newPortNamer: NewPortNamer] RETURNS [gc: Vertex, children: VertexList] =
BEGIN
childType: CellType ← ToType[design, childTypeA];
gcType: CellType ← NIL;
first: BOOLTRUE;
grandChildAnses: GrandChildAnses;
dif: BOOLFALSE;
oldPorts: PortS ← childType.ports;
childAnses: ChildAnses ← NEW [ChildAnsesRep[oldPorts.length]];
losses, gains, remains, newChildPortIndex: NAT ← 0;
oldGCConnections: NamesS--gcIndex--;
Survey: PROC [child, gc: Vertex] = {
IF first THEN gcType ← gc.type;
IF gc.type # gcType THEN {
Warn[[], "%g is a %g, not a %g", IO.refAny[GlobalVertexName[gc]], IO.refAny[PickAName[gc.type.names]], IO.refAny[PickAName[gcType.names]]];
dif ← TRUE}
ELSE {
gcPortIndex: NAT ← 0;
IF first THEN {
grandChildAnses ← NEW [GrandChildAnsesRep[gcType.ports.length]];
oldGCConnections ← NEW [NamesSeq[gcType.ports.length]];
FOR gcpi: NAT IN [0 .. grandChildAnses.length) DO
grandChildAnses[gcpi] ← [];
ENDLOOP};
FOR e: Edge ← gc.firstEdge, e.sides[component].next WHILE e # NIL DO
sawSelf, sawBord, sawBords, sawElse: BOOLFALSE;
net: Vertex ← e.sides[net].v;
IF e.sides[component].v # gc 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[component].v = gc THEN sawSelf ← TRUE
ELSE IF f.sides[component].v = child THEN {
sawBords ← sawBord;
sawBord ← TRUE;
grandChildAnses[gcPortIndex].oldChildPortIndex ← f.portIndex;
}
ELSE sawElse ← TRUE;
ENDLOOP;
IF NOT sawSelf THEN ERROR;
IF first THEN {
grandChildAnses[gcPortIndex].sawBord ← sawBord;
grandChildAnses[gcPortIndex].sawBords ← sawBords;
grandChildAnses[gcPortIndex].sawElse ← sawElse;
IF sawBord AND NOT (sawElse OR sawBords) THEN {
losses ← losses + 1;
childAnses[grandChildAnses[gcPortIndex].oldChildPortIndex].newPortIndex ← NullPortIndex;
};
IF sawElse AND NOT sawBord THEN gains ← gains + 1;
oldGCConnections[gcPortIndex] ← net.names;
}
ELSE {
Dif: PROC = {Warn[[], "%g & %g are connected differently than the first pair", IO.refAny[GlobalVertexName[child]], IO.refAny[GlobalVertexName[gc]]]; dif ← TRUE};
IF grandChildAnses[gcPortIndex].sawBord # sawBord THEN Dif[];
IF grandChildAnses[gcPortIndex].sawBords # sawBords THEN Dif[];
IF grandChildAnses[gcPortIndex].sawElse # sawElse THEN Dif[]};
gcPortIndex ← gcPortIndex + 1;
ENDLOOP;
};
first ← FALSE;
};
newPorts: PortS;
newPortIndex: NAT ← 0;
inside: VertexS--oldChildIndex--NEW [VertexSeq[oldPorts.length]];
insideEdge: Edge;
parentTypes: RefTab.Ref ← RefTab.Create[];
children ← NIL;
IF KeepPort = NullPortIndex THEN ERROR;
FOR e: Edge ← childType.mirror.firstEdge, e.sides[component].next WHILE e # NIL DO
IF e.sides[component].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
sibAsAny: REF ANY;
IF IsMirror[child] THEN ERROR; --AM2
sibAsAny ← sibber.map[sibber.data, child];
IF sibAsAny = NIL
THEN {Warn[[], "No sibling given for %g", IO.rope[GlobalVertexName[child]]]; dif ← TRUE}
ELSE WITH sibAsAny SELECT FROM
v: Vertex => Survey[child, v];
ENDCASE => {Warn[[], "Sibling for %g should be a vertex, not %g", IO.rope[GlobalVertexName[child]], IO.refAny[sibAsAny]]; dif ← TRUE};
ENDLOOP;
IF first OR dif THEN RETURN [NIL, NIL];
NoteChange[childType];
gc ← NEW [VertexRep ← [names: gcNames, type: gcType, parent: childType, class: component]];
AddVertex[gc]; LinkInstance[gc];
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[component].next;
IF insideEdge.sides[component].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 gcIndex: NAT IN [0 .. gcType.ports.length) DO
AddPort: PROC RETURNS [insideNet: Vertex] = {
insideNet ← NEW [VertexRep ← [names: oldGCConnections[gcIndex], parent: childType, class: net]];
AddVertex[insideNet];
newPorts[newChildPortIndex] ← [netNames: LIST[PickAName[insideNet.names]]];
[newPorts[newChildPortIndex].names, newPorts[newChildPortIndex].equivClass] ← newPortNamer.NameNewPort[newPortNamer.data, childType, newPorts, newChildPortIndex, insideNet, gcType, gcIndex];
grandChildAnses[gcIndex].newChildPortIndex ← newChildPortIndex;
newChildPortIndex ← newChildPortIndex + 1;
};
MakeDummy: PROC RETURNS [insideNet: Vertex] = {
insideNet ← NEW [VertexRep ← [names: oldGCConnections[gcIndex], parent: childType, class: net]];
AddVertex[insideNet];
};
AddEdge[gc, IF grandChildAnses[gcIndex].sawBord THEN inside[grandChildAnses[gcIndex].oldChildPortIndex] ELSE IF grandChildAnses[gcIndex].sawElse THEN AddPort[] ELSE MakeDummy[]];
ENDLOOP;
IF newChildPortIndex # newPorts.length THEN ERROR;
childType.ports ← newPorts;
CheckType[childType, check, TRUE];
FOR child: Vertex ← childType.firstInstance, child.nextInstance WHILE child # NIL DO
sib: Vertex;
IF IsMirror[child] THEN ERROR; --AM2
children ← CONS[child, children];
sib ← NARROW[sibber.map[sibber.data, child]];
WHILE sib.firstEdge # NIL DO
e: Edge ← sib.firstEdge;
net: Vertex ← e.sides[net].v;
gcPortIndex: NAT ← e.portIndex;
IF NOT (grandChildAnses[gcPortIndex].sawElse OR grandChildAnses[gcPortIndex].sawBords) THEN DeleteVertex[net] ELSE RemoveEdge[e];
ENDLOOP;
NoteChange[child.parent];
IF losses>0 THEN RenumberOutsideEdges[child];
DeleteVertex[sib];
[] ← parentTypes.Store[child.parent, $T];
ENDLOOP;
[] ← parentTypes.Pairs[CheckParentType];
END;
VertexS: TYPE = REF VertexSeq;
VertexSeq: TYPE = RECORD [SEQUENCE length: NAT OF Vertex];
NamesS: TYPE = REF NamesSeq;
NamesSeq: TYPE = RECORD [SEQUENCE length: NAT OF Names];
ChildAnses: TYPE = REF ChildAnsesRep;
ChildAnsesRep: TYPE = RECORD [SEQUENCE--oldChildIndex-- length: NAT OF ChildAns];
ChildAns: TYPE = RECORD [newPortIndex: NAT];
GrandChildAnses: TYPE = REF GrandChildAnsesRep;
GrandChildAnsesRep: TYPE = RECORD [
SEQUENCE--gcIndex-- length: PortIndex OF GrandChildAns];
GrandChildAns: TYPE = RECORD [
oldChildPortIndex, newChildPortIndex: PortIndex ← NullPortIndex,
sawBord, sawBords, sawElse: BOOLFALSE];
RaiseGrandchild: PROC [design: Design, gcA: REF ANY, newPortNamer: NewPortNamer] RETURNS [newChildren: VertexList] =
BEGIN
gc: Vertex ← ToVertex[design, gcA];
oldPorts: PortS ← gc.parent.ports;
newPorts: PortS;
inside: VertexS--oldChildIndex--NEW [VertexSeq[oldPorts.length]];
oldGCConnections: NamesS--gcIndex--NEW [NamesSeq[gc.type.ports.length]];
losses, gains, remains, gcPortIndex, newChildPortIndex: NAT ← 0;
childAnses: ChildAnses ← NEW [ChildAnsesRep[oldPorts.length]];
grandChildAnses: GrandChildAnses ← NEW [GrandChildAnsesRep[gc.type.ports.length]];
parentTypes: RefTab.Ref ← RefTab.Create[];
newChildren ← NIL;
FOR p: NAT IN [0 .. inside.length) DO inside[p] ← NIL ENDLOOP;
FOR p: NAT IN [0 .. grandChildAnses.length) DO grandChildAnses[p] ← [] ENDLOOP;
IF gc.parent = gc.type THEN ERROR;
FOR e: Edge ← gc.firstEdge, e.sides[component].next WHILE e # NIL DO
sawSelf, sawBord, sawBords, sawElse: BOOLFALSE;
net: Vertex ← e.sides[net].v;
IF e.sides[component].v # gc THEN ERROR;
oldGCConnections[gcPortIndex] ← net.names;
FOR f: Edge ← net.firstEdge, f.sides[net].next WHILE f # NIL DO
IF f.sides[net].v # net THEN ERROR;
IF f.sides[component].v = gc THEN sawSelf ← TRUE
ELSE IF IsMirror[f.sides[component].v] THEN {
sawBords ← sawBord;
sawBord ← TRUE;
grandChildAnses[gcPortIndex].oldChildPortIndex ← f.portIndex;
IF (inside[f.portIndex] # NIL) AND (inside[f.portIndex] # net) THEN ERROR ELSE inside[f.portIndex] ← net}
ELSE sawElse ← TRUE;
ENDLOOP;
IF NOT sawSelf THEN ERROR;
grandChildAnses[gcPortIndex].sawBord ← sawBord;
grandChildAnses[gcPortIndex].sawBords ← sawBords;
grandChildAnses[gcPortIndex].sawElse ← sawElse;
IF (net.suspect ← (sawBord AND NOT (sawElse OR sawBords))) THEN losses ← losses + 1;
IF sawElse AND NOT sawBord THEN gains ← gains + 1;
gcPortIndex ← gcPortIndex + 1;
ENDLOOP;
IF gcPortIndex # gc.type.ports.length THEN ERROR;
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 e: Edge ← gc.firstEdge, e.sides[component].next WHILE e # NIL DO
net: Vertex ← e.sides[net].v;
gcPortIndex: NAT ← e.portIndex;
IF e.sides[component].v # gc THEN ERROR;
IF grandChildAnses[gcPortIndex].sawElse AND NOT grandChildAnses[gcPortIndex].sawBord THEN {
newPorts[newChildPortIndex]← [netNames: LIST[PickAName[net.names]]];
[newPorts[newChildPortIndex].names, newPorts[newChildPortIndex].equivClass] ← newPortNamer.NameNewPort[newPortNamer.data, gc.parent, newPorts, newChildPortIndex, net, gc.type, gcPortIndex];
grandChildAnses[gcPortIndex].newChildPortIndex ← newChildPortIndex;
newChildPortIndex ← newChildPortIndex + 1};
ENDLOOP;
IF newChildPortIndex # newPorts.length THEN ERROR;
NoteChange[gc.parent];
gc.parent.ports ← newPorts;
WHILE gc.firstEdge # NIL DO
e: Edge ← gc.firstEdge;
net: Vertex ← e.sides[net].v;
gcPortIndex: NAT ← e.portIndex;
IF NOT (grandChildAnses[gcPortIndex].sawElse OR grandChildAnses[gcPortIndex].sawBords) THEN DeleteVertex[net] ELSE RemoveEdge[e];
ENDLOOP;
IF losses>0 THEN RenumberInsideEdges[gc.parent];
DeleteVertex[gc];
CheckType[gc.parent, check, TRUE];
FOR child: Vertex ← gc.parent.firstInstance, child.nextInstance WHILE child # NIL DO
sib: Vertex ← NEW [VertexRep ← [names: JoinNames[child.names, gc.names], type: gc.type, parent: child.parent, class: component]];
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
AddVertex[sib];
LinkInstance[sib];
FOR ce: Edge ← child.firstEdge, nextChildEdge WHILE ce # NIL DO
nextChildEdge ← ce.sides[component].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 ci: NAT IN [0 .. gc.type.ports.length) DO
MakeDummyNet: PROC RETURNS [net: Vertex] = {
net ← NEW [VertexRep ← [names: JoinNames[child.names, oldGCConnections[ci]], parent: child.parent, class: net]];
AddVertex[net];
};
AddEdge[
sib,
IF grandChildAnses[ci].sawBord
THEN oldNets[grandChildAnses[ci].oldChildPortIndex]
ELSE IF grandChildAnses[ci].sawElse
THEN newNets[grandChildAnses[ci].newChildPortIndex - remains]
ELSE MakeDummyNet[]];
ENDLOOP;
NoteChange[child.parent];
[] ← parentTypes.Store[child.parent, $T];
newChildren ← CONS[sib, newChildren];
ENDLOOP;
[] ← parentTypes.Pairs[CheckParentType];
END;
NameNewPortFromOld: PROC
[
data: REF ANY, ct: CellType,
ports: PortS, portIndex: PortIndex,
net: Vertex, fromType: CellType, fromIndex: PortIndex]
RETURNS [names: Names, equivClass: EquivClass] =
{
names ← fromType.ports[fromIndex].names;
equivClass ← fromType.ports[fromIndex].equivClass};
DontNameNewPort: PROC
[
data: REF ANY, ct: CellType,
ports: PortS, portIndex: PortIndex,
net: Vertex, fromType: CellType, fromIndex: PortIndex]
RETURNS [names: Names, equivClass: EquivClass] =
{ERROR};
RenameCellType: PROC [design: Design] RETURNS [] =
BEGIN
ERROR nyet;
END;
RenamePort: PROC [design: Design] RETURNS [] =
BEGIN
ERROR nyet;
END;
RenamePart: PROC [design: Design] RETURNS [] =
BEGIN
ERROR nyet;
END;
ExpandVertex: PROC [design: Design, childA: REF ANY] =
BEGIN
child: Vertex ← ToVertex[design, childA];
parentType: CellType ← child.parent;
childType: CellType ← child.type;
[] ← ExpandVertexWork[child];
NoteChange[parentType];
CheckType[parentType, establish];
CheckType[childType, establish];
END;
ExpandChildren: PROC [design: Design, parentTypeA: REF ANY, flatten: BOOLFALSE] =
BEGIN
parentType: CellType ← ToType[design, parentTypeA];
childTypes: RefTab.Ref ← RefTab.Create[];
children: RefTab.Ref ← RefTab.Create[];
NoteOldChild: PROC [ra: REF ANY] RETURNS [stop: BOOL] = {
v: Vertex ← NARROW[AntiAlias[ra]];
[] ← children.Insert[v, $T];
stop ← FALSE};
ExpandOldChild: PROC [key, val: REF ANY] RETURNS [quit: BOOL] = {
v: Vertex ← NARROW[key];
quit ← FALSE;
SELECT v.class FROM
component => {
childType: CellType ← v.type;
EnsureParts[childType];
IF ExpansionKnown[childType] THEN {
sibs: VertexList ← ExpandVertexWork[v];
[] ← childTypes.Insert[childType, $T];
IF flatten THEN {
FOR sibs ← sibs, sibs.rest WHILE sibs # NIL DO
[] ← ExpandOldChild[sibs.first, NIL];
ENDLOOP;
};
};
};
net => NULL;
ENDCASE => ERROR;
};
EnsureParts[parentType];
IF NOT ExpansionKnown[parentType] THEN ERROR;
parentType.parts.EnumerateIncreasing[NoteOldChild];
[] ← children.Pairs[ExpandOldChild];
NoteChange[parentType];
CheckType[parentType, establish];
[] ← childTypes.Pairs[EstablishType];
END;
EstablishType: PROC [key, val: REF ANY] RETURNS [quit: BOOL] = {
ct: CellType ← NARROW[key];
CheckType[ct, establish];
quit ← FALSE};
ExpandVertexWork: PROC [childCell: Vertex] RETURNS [newSibs: VertexList] =
BEGIN
parentType: CellType ← childCell.parent;
childType: CellType ← childCell.type;
NILEquiv: PROC [ra: REF ANY] RETURNS [stop: BOOL] = {
v: Vertex ← NARROW[AntiAlias[ra]];
stop ← FALSE;
v.equiv ← NIL};
SetPortedNetEquivs: PROC = {
innerEdge: Edge ← childType.mirror.firstEdge;
outerEdge: Edge ← childCell.firstEdge;
FOR portIndex: NAT IN [0 .. childType.ports.length) DO
IF innerEdge.portIndex # portIndex THEN ERROR;
IF outerEdge.portIndex # portIndex THEN ERROR;
IF innerEdge.sides[component].v # childType.mirror THEN ERROR;
IF outerEdge.sides[component].v # childCell THEN ERROR;
innerEdge.sides[net].v.equiv ← outerEdge.sides[net].v;
innerEdge ← innerEdge.sides[component].next;
outerEdge ← outerEdge.sides[component].next;
ENDLOOP;
IF innerEdge # NIL OR outerEdge # NIL THEN ERROR};
Copy: PROC [ra: REF ANY] RETURNS [stop: BOOL] = {
v: Vertex ← NARROW[AntiAlias[ra]];
stop ← FALSE;
[] ← CopyWork[v]};
CopyWork: PROC [gc: Vertex] RETURNS [newChild: Vertex] = {
IF gc.equiv # NIL THEN RETURN [gc.equiv];
gc.equiv ← newChild ← NEW [VertexRep ← [names: JoinNames[childCell.names, gc.names], type: gc.type, parent: parentType, class: gc.class]];
AddVertex[newChild];
IF newChild.class = net THEN RETURN;
LinkInstance[newChild];
FOR oldE: Edge ← gc.firstEdge, oldE.sides[component].next WHILE oldE # NIL DO
newNet: Vertex ← CopyWork[oldE.sides[net].v];
IF oldE.sides[component].v # gc THEN ERROR;
AddEdge[newChild, newNet];
ENDLOOP;
newSibs ← CONS[newChild, newSibs];
};
newSibs ← NIL;
EnsureParts[childType];
IF NOT ExpansionKnown[childType] THEN ERROR;
childType.mirror.equiv ← NIL;
childType.parts.EnumerateIncreasing[NILEquiv];
childType.mirror.equiv ← childCell;
SetPortedNetEquivs[];
childType.parts.EnumerateIncreasing[Copy];
DeleteVertex[childCell];
childType.mirror.equiv ← NIL;
childType.parts.EnumerateIncreasing[NILEquiv];
CheckType[parentType, check, TRUE];
END;
EnumerateInstances: PROC [design: Design, ra: REF ANY, consume: PROC [Vertex]] = {
WITH ra SELECT FROM
vl: VertexList => FOR l: VertexList ← vl, l.rest WHILE l # NIL DO
consume[l.first]
ENDLOOP;
lora: LORA => FOR l: LORA ← lora, l.rest WHILE l # NIL DO
consume[ToVertex[design, l.first]]
ENDLOOP;
ENDCASE => ERROR};
EnumerateCellTypes: PROC [design: Design, ra: REF ANY, consume: PROC [CellType]] = {
WITH ra SELECT FROM
cl: LIST OF CellType => FOR l: LIST OF CellType ← cl, l.rest WHILE l # NIL DO
consume[l.first]
ENDLOOP;
lora: LORA => FOR l: LORA ← lora, l.rest WHILE l # NIL DO
consume[ToType[design, l.first]]
ENDLOOP;
ENDCASE => ERROR};
ToType: PROC [design: Design, ra: REF ANY] RETURNS [type: CellType] = {
WITH ra SELECT FROM
r: ROPE => type ← NARROW[Lookup[design.componentTypes, r]];
ct: CellType => type ← ct;
ENDCASE => ERROR};
ToRope: PROC [ra: REF ANY] RETURNS [rope: ROPE] = {rope ← NARROW[ra]};
ToVertex: PROC [design: Design, ra: REF ANY] RETURNS [v: Vertex] = {
WITH ra SELECT FROM
vertex: Vertex => v ← vertex;
lora: LORA => {
ct: CellType ← ToType[design, lora.first];
name: ROPENARROW[lora.rest.first];
EnsureParts[ct];
v ← NARROW[Lookup[ct.parts, name]]};
ENDCASE => ERROR};
VVMapFromTIINames: PROC [design: Design, l: TIINamesList] RETURNS [m: Mapper] = {
rtm: RefTabMapper ← NEW [RefTabMapperRep ← [NIL, RefTab.Create[]]];
rtm.asMapper ← m ← NEW [MapperRep ← [RefTabMap, rtm]];
FOR tiil: TIINamesList ← l, tiil.rest WHILE tiil # NIL DO
tiin: TIINames ← tiil.first;
ct: CellType ← NARROW[Lookup[design.componentTypes, tiin.typeName]];
v1: Vertex ← NARROW[Lookup[ct.parts, tiin.v1Name]];
v2: Vertex ← NARROW[Lookup[ct.parts, tiin.v2Name]];
[] ← rtm.refTab.Store[v1, v2];
ENDLOOP;
};
GenName: PROC RETURNS [name: ROPE] =
{name ← IO.PutFR[" gen%g", IO.card[genCount ← genCount + 1]]};
genCount: NAT ← 0;
JoinNames: PROC [parent, child: Names] RETURNS [joined: Names] =
{joined ← [progged: LIST[PickAName[parent].Cat[".", PickAName[child]]]]};
IsEmpty: PROC [type: CellType] RETURNS [isEmpty: BOOL] = {
EnsureParts[type];
EnsurePorts[type];
isEmpty ← type.ports.length = 0 AND type.cellCount = 0};
CopyPorts: PROC [p: PortS] RETURNS [q: PortS] = {
q ← NEW [PortSeq[p.length]];
FOR pi: NAT IN [0 .. q.length) DO q[pi] ← p[pi] ENDLOOP;
};
CopyParts: PROC [newCT, oldCT: CellType] = {
oldParts: SymbolTable ← oldCT.parts;
newParts: SymbolTable;
Copy: PROC [ra: REF ANY] RETURNS [stop: BOOL] = {
oldV: Vertex ← NARROW[AntiAlias[ra]];
AM1 says this can't be the mirror.
newV: Vertex;
stop ← FALSE;
newV ← CopyWork[oldV]};
CopyWork: PROC [oldV: Vertex] RETURNS [newV: Vertex] = {
newV ← NARROW[Lookup[newParts, PickAName[oldV.names]]];
IF newV # NIL THEN RETURN;
newV ← NEW [VertexRep ← [names: oldV.names, type: oldV.type, parent: newCT, class: oldV.class]];
AddVertex[newV];
IF newV.class = net THEN RETURN;
LinkInstance[newV];
FOR oldE: Edge ← oldV.firstEdge, oldE.sides[component].next WHILE oldE # NIL DO
newNet: Vertex ← CopyWork[oldE.sides[net].v];
IF oldE.sides[component].v # oldV THEN ERROR;
AddEdge[newV, newNet];
ENDLOOP;
};
IF oldCT.parts = NIL OR newCT.parts # NIL THEN ERROR;
IF newCT.mirror # NIL THEN ERROR;
newCT.parts ← newParts ← OrderedSymbolTableRef.CreateTable[CompareVertices];
oldParts.EnumerateIncreasing[Copy];
AddWorld[newCT];
};
DeleteType: PROC [design: Design, type: CellType] = {
IF (type.firstInstance = NIL) # (type.lastInstance = NIL) THEN ERROR;
IF (type.firstInstance # NIL) OR (type.lastInstance # NIL) THEN ERROR; --AM2
Delete[design.componentTypes, type.names, type];
};
ChangeType: PROC [v: Vertex, from, to: CellType] = {
IF v.type # from THEN ERROR;
NoteChange[v.parent];
UnlinkInstance[v];
v.type ← to;
LinkInstance[v]};
UnlinkInstance: PUBLIC PROC [v: Vertex] = {
IF v.prevInstance # NIL THEN v.prevInstance.nextInstance ← v.nextInstance ELSE v.type.firstInstance ← v.nextInstance;
IF v.nextInstance # NIL THEN v.nextInstance.prevInstance ← v.prevInstance ELSE v.type.lastInstance ← v.prevInstance;
};
LinkInstance: PUBLIC PROC [v: Vertex] = {
v.nextInstance ← NIL;
v.prevInstance ← v.type.lastInstance;
IF v.prevInstance # NIL THEN v.prevInstance.nextInstance ← v ELSE v.type.firstInstance ← v;
IF v.nextInstance # NIL THEN v.nextInstance.prevInstance ← v ELSE v.type.lastInstance ← v;
};
AddEdge: PROC [cv, nv: Vertex] = {
pi: NAT = IF cv.lastEdge # NIL THEN cv.lastEdge.portIndex+1 ELSE 0;
e: Edge ← NEW [EdgeRep ← [sides: [component: [v: cv, next: NIL, prev: cv.lastEdge], net: [v: nv, next: NIL, prev: nv.lastEdge]], color: noColor, portIndex: pi]];
IF cv.class # component OR nv.class # net THEN ERROR;
IF e.sides[component].prev # NIL THEN e.sides[component].prev.sides[component].next ← e ELSE cv.firstEdge ← e;
IF e.sides[net].prev # NIL THEN e.sides[net].prev.sides[net].next ← e ELSE nv.firstEdge ← e;
cv.lastEdge ← nv.lastEdge ← e;
};
RenumberInsideEdges: PROC [ct: CellType] = {
portIndex: NAT ← 0;
FOR e: Edge ← ct.mirror.firstEdge, e.sides[component].next WHILE e # NIL DO
IF e.sides[component].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[component].next WHILE e # NIL DO
IF e.sides[component].v # v THEN ERROR;
IF e.portIndex < portIndex THEN ERROR;
e.portIndex ← portIndex;
portIndex ← portIndex + 1;
ENDLOOP;
};
DeleteVertex: PUBLIC PROC [v: Vertex] = {
v ← v;
WHILE v.firstEdge # NIL DO RemoveEdge[v.firstEdge] ENDLOOP;
Delete[v.parent.parts, v.names, v];
SELECT v.class FROM
net => v.parent.netCount ← v.parent.netCount - 1;
component => {v.parent.cellCount ← v.parent.cellCount - 1;
UnlinkInstance[v]};
ENDCASE => ERROR;
v ← v};
RemoveEdge: PUBLIC PROC [e: Edge] = {
UnlinkSide: PROC [side: VertexClass] = {
head: Vertex ← e.sides[side].v;
IF e.sides[side].next # NIL
THEN e.sides[side].next.sides[side].prev ← e.sides[side].prev
ELSE head.lastEdge ← e.sides[side].prev;
IF e.sides[side].prev # NIL
THEN e.sides[side].prev.sides[side].next ← e.sides[side].next
ELSE head.firstEdge ← e.sides[side].next;
e.sides[side].next ← e.sides[side].prev ← badEdge};
UnlinkSide[net];
UnlinkSide[component];
};
badEdge: Edge ← NEW [EdgeRep ← [sides: [[NIL, NIL, NIL], [NIL, NIL, NIL]], color: 0, portIndex: NullPortIndex]];
RefTabMap: PROC [data, domain: REF ANY] RETURNS [range: REF ANY] = {
rtm: RefTabMapper ← NARROW[data];
range ← rtm.refTab.Fetch[domain].val};
END.
g:  

— !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^←`abcdefghijklmnopqrstuvwxyz{|}~
m: ııııııı 
ıı
ıııııııııııııııııı# °÷'P`± +˜Ë¡.•–— Æ"§®d`e¿ï!‚…‡[ ÜÄ]H¥*({ ´õzı{Ëbıè©CéÒËĞ%¬¢«®gfh¡¢)£¼ı¾ı