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: LORA _ NIL; 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: BOOL _ TRUE; grandChildAnses: GrandChildAnses; dif: BOOL _ FALSE; 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: BOOL _ FALSE; 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: BOOL _ FALSE]; 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: BOOL _ FALSE; 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: 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 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: BOOL _ FALSE] = 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: ROPE _ NARROW[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]]; 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:   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ |CompareTransforms.Mesa Last Edited by: Spreitzer, November 12, 1984 8:40:10 am PST AM1 says this can't be the mirror. Κi– "cedar" style˜Icode™J™;K˜KšΟk œ8œœ6˜}K˜šΠbxœœ˜ Kšœ#œ%˜QKšœ ˜K˜Kšœœ"˜,K˜KšΟcœœœ˜+K˜Kš œœ œœœ˜LK˜š Οn œœ.œœœ˜eKš˜Kšœœ˜Kšœœœ˜š œœ˜%Kšœ œœœœœ"œœ œ˜ΐKšœœ ˜—Kšœ7˜7Kš œœ8œœœ(œ˜›Kšœ˜šœœœ˜&Kšœœ$˜8Kšœ˜—Kšœ˜—K˜š  œœ/œœœ˜lKš˜Kšœ œœ œ˜!Kšœ œ˜š  œœ˜$Kšœ œ˜Kšœ˜—Kšœ3˜3šœ$œ œ˜>šœ œ˜+K˜)Kšœ œœŸ˜ Kšœ3˜3Kšœ œ ˜Kšœ˜—K˜#Kšœ˜—Kšœ˜—K˜š  œœFœ˜pKš˜KšœœZ˜eKš œœœFœ œ%œ&˜ΥK˜K˜K˜Kšœ˜—K˜š  œœ!œ˜RKš˜K˜Kš œœœ7œœ&œ$˜ΕKš œœœœœœ˜Kšœ+œ˜3KšœŸ œ˜$š œœ˜$Kšœœ˜šœœ˜Kšœ!œœ#œ"˜‹Kšœœ˜ —šœ˜Kšœ œ˜šœœ˜Kšœœ+˜@Kšœœ!˜7šœœœ˜1Kšœ˜Kšœ˜ ——šœ1œœ˜DKšœ%œœ˜2K˜Kšœœœ˜(šœ,œœ˜?Kšœœœ˜#Kšœœ ˜0šœœœ˜+Kšœ˜Kšœ œ˜Kšœ=˜=Kšœ˜—Kšœ œ˜Kšœ˜—Kšœœ œœ˜šœœ˜Kšœ/˜/Kšœ1˜1Kšœ/˜/š œ œœ œ œ˜/Kšœ˜KšœX˜XK˜—Kšœ œœ œ˜2K˜*Kšœ˜—šœ˜Kš  œœFœ"œ&œ˜‘Kšœ0œ˜=Kšœ2œ˜?Kšœ0œ˜>—Kšœ˜Kšœ˜—K˜—Kšœœ˜K˜—K˜Kšœœ˜KšœŸœœ˜DK˜K˜*Kšœ œ˜Kšœœœ˜'šœ?œœ˜RKšœ)œœ˜6K˜%Kšœ˜—šœœœ˜*Kšœ,˜,Kšœ˜—šœ=œ œ˜TKšœ œœ˜KšœœœŸ˜$Kšœ*˜*šœ ˜Kšœ&œ'œ˜Xšœœ œ˜K˜Kšœ;œ œœ˜†——Kšœ˜—Kš œœœœœœ˜'K˜KšœœS˜[K˜ K˜#Kšœ œ˜*K˜(šœœœ˜2K˜8Kšœ2œœ˜?Kšœ%œœ˜2šœ'˜1˜ Kšœ5˜5Kšœ:˜:Kšœ)˜)Kšœ+˜+—Kšœ(˜(Kšœœ˜—K˜Kšœ˜—Kšœœœœ˜Kšœœœ˜*šœ œœ˜1š œœœ˜-Kšœ œQ˜`K˜Kšœ)œ˜KKšœΎ˜ΎKšœ?˜?Kšœ*˜*K˜—š  œœœ˜/Kšœ œQ˜`K˜K˜—Kš œ œ"œ4œœ"œ œ˜²Kšœ˜—Kšœ%œœ˜2Kšœ˜Kšœœ˜"šœ=œ œ˜TKšœ ˜ KšœœœŸ˜$Kšœ œ˜!Kšœœ!˜-šœœ˜Kšœ˜K˜Kšœ œ˜Kš œœ'œ(œœ˜Kšœ˜—K˜Kšœ œ˜-Kšœ˜K˜)Kšœ˜—K˜(Kšœ˜—K˜Kšœ œœ ˜Kš œ œœœ œœ ˜:K˜Kšœœœ ˜Kš œ œœœ œœ˜8K˜Kšœ œœ˜%Kš œœœŸœ œœ ˜QKšœ œœœ˜,K˜Kšœœœ˜/šœœœ˜#KšŸ œœ˜8—šœœœ˜Kšœ@˜@Kšœœœ˜*—K˜š  œœœœœ˜tKš˜K˜#K˜"K˜KšœŸœœ˜DKšœŸ œœ"˜KKšœ8œ˜@Kšœœ"˜>Kšœ#œ,˜RK˜*Kšœœ˜Kš œœœœ œœ˜>Kš œœœœœ˜OKšœœœ˜"šœ1œœ˜DKšœ%œœ˜2K˜Kšœœœ˜(Kšœ*˜*šœ,œœ˜?Kšœœœ˜#Kšœœ ˜0šœœ œ˜-Kšœ˜Kšœ œ˜Kšœ=˜=Kš œœœœœœ˜i—Kšœ œ˜Kšœ˜—Kšœœ œœ˜Kšœ/˜/Kšœ1˜1Kšœ/˜/Kš œœœ œ œ˜TKšœ œœ œ˜3Kšœ˜Kšœ˜—Kšœ$œœ˜1K˜#Kšœ œ˜*Kšœ˜šœœœ˜)Kšœœœ˜šœœœ˜Kšœœ˜Kšœœ˜—Kšœœœœ˜Qšœœ˜Kšœ,˜,Kšœ+˜+—Kšœ˜—Kšœœœ˜*šœ1œœ˜DK˜Kšœ œ˜Kšœœœ˜(šœ&œœ&œ˜[Kšœ(œ˜DKšœ½˜½KšœC˜CKšœ+˜+—Kšœ˜—Kšœ%œœ˜2K˜K˜šœœ˜Kšœ˜K˜Kšœ œ˜Kš œœ'œ(œœ˜Kšœ˜—Kšœ œ ˜0K˜Kšœœ˜"šœ=œ œ˜TKšœœp˜KšœŸœœ˜EKšœŸœœ˜2Kšœœ˜&K˜KšœœœŸ˜$Kšœ˜K˜šœ+œœ˜?Kšœ)˜)Kšœ)˜)Kšœœœ˜+šœ9˜;šœ˜Kšœ8œœ˜EKšœ3˜3—Kšœ˜—Kšœ"˜"Kšœ˜—Kšœ*œœ˜7šœœ$˜:KšœœC˜\Kšœœa˜wKšœ˜Kšœ˜Kšœ,˜,Kšœ˜—šœœœ˜-š  œœœ˜,Kšœœg˜pK˜K˜—šœ˜Kšœ˜šœ˜Kšœ/˜3—šœœ˜#Kšœ9˜=—Kšœ˜—Kšœ˜—K˜K˜)Kšœœ˜%Kšœ˜—K˜(Kšœ˜—K˜š œ˜šœ˜Kšœœœ˜Kšœ#˜#Kšœ6˜6—Kšœ)˜0Kšœ˜Kšœ(˜(Kšœ3˜3—K˜š œ˜šœ˜Kšœœœ˜Kšœ#˜#Kšœ6˜6—Kšœ)˜0Kšœœ˜—K˜š œœœ˜2Kš˜Kšœ˜ Kšœ˜—K˜š  œœœ˜.Kš˜Kšœ˜ Kšœ˜—K˜š  œœœ˜.Kš˜Kšœ˜ Kšœ˜—K˜š  œœœœ˜6Kš˜K˜)K˜$K˜!K˜K˜Kšœ!˜!K˜ Kšœ˜—K˜š  œœœœ œœ˜TKš˜Kšœ3˜3K˜)K˜'š   œœœœœœ˜9Kšœ œ˜"K˜Kšœœ˜—š  œœ œœœœ˜AKšœ œ˜Kšœœ˜ šœ ˜˜K˜K˜šœœ˜#K˜'K˜&šœ œ˜šœœœ˜.Kšœ œ˜%Kšœ˜—K˜—K˜—K˜—Kšœœ˜ Kšœœ˜—K˜—K˜Kšœœœœ˜-Kšœ3˜3Kšœ$˜$K˜Kšœ!˜!Kšœ%˜%Kšœ˜—K˜š   œœ œœœœ˜@Kšœœ˜Kšœ˜Kšœœ˜—K˜š œœœ˜JKš˜Kšœ(˜(Kšœ%˜%š  œœœœœœ˜5Kšœ œ˜"Kšœœ˜ Kšœ œ˜—š œœ˜K˜-K˜&šœ œœ˜6Kšœ!œœ˜.Kšœ!œœ˜.Kšœ1œœ˜>Kšœ*œœ˜7K˜6K˜,K˜,Kšœ˜—Kš œ œœ œœœ˜2—š  œœœœœœ˜1Kšœ œ˜"Kšœœ˜ Kšœ˜—š œœœ˜:Kšœ œœœ ˜)Kšœœq˜ŠK˜Kšœœœ˜$K˜šœ7œœ˜MK˜-Kšœœœ˜+K˜Kšœ˜—Kšœ œ˜"K˜—Kšœ œ˜K˜Kšœœœœ˜,Kšœœ˜K˜.K˜#K˜K˜*K˜Kšœœ˜K˜.Kšœœ˜#Kšœ˜—K˜š  œœœœ œ˜Ršœœ˜šœœœœ˜AKšœ˜Kšœ˜—š œœœœœœ˜9K˜"Kšœ˜—Kšœœ˜——K˜š  œœœœ œ˜Tšœœ˜šœœœ œœœœœ˜MKšœ˜Kšœ˜—š œœœœœœ˜9K˜ Kšœ˜—Kšœœ˜——K˜š  œœœœœ˜Gšœœ˜Kšœœ œ#˜;K˜Kšœœ˜——K˜Kš œœœœœœ œ˜FK˜š  œœœœœ˜Dšœœ˜Kšœ˜šœœ˜K˜*Kšœœœ˜%K˜Kšœœ˜$—Kšœœ˜——K˜š œœ#œ˜QKšœœœ˜CKšœœ ˜6šœ#œœ˜9K˜Kšœœ/˜DKšœ œ ˜3Kšœ œ ˜3K˜Kšœ˜—K˜—K˜š œœœœ˜$Kšœœœ!˜>Kšœ œ˜—K˜š  œœœ˜@Kšœœ1˜I—K˜š œœœ œ˜:K˜K˜Kšœ œ˜8—K˜š  œœ œ˜1Kšœœ˜Kš œœœœœ˜8K˜—K˜š  œœ˜,Kšœ$˜$Kšœ˜š  œœœœœœ˜1šœœ˜%K™"—K˜ Kšœœ˜ Kšœ˜—š œœœ˜8Kšœœ*˜7Kšœœœœ˜KšœœV˜`K˜Kšœœœ˜ K˜šœ9œœ˜OK˜-Kšœ œœ˜-K˜Kšœ˜—K˜—Kš œœœœœœ˜5Kšœœœœ˜!KšœL˜LKšœ#˜#Kšœ˜K˜—K˜š  œœ%˜5Kš œœœœœ˜EKš œœœœœœŸ˜LKšœ0˜0Kšœ˜—K˜š  œœ$˜4Kšœœœ˜K˜Kšœ˜Kšœ ˜ Kšœ˜—K˜š œœœ˜+Kšœœœ.œ'˜uKšœœœ.œ&˜tK˜—K˜š  œœœ˜)Kšœœ˜K˜%Kšœœœ!œ˜[Kšœœœ!œ˜ZK˜—K˜š œœ˜"Kš œœœœœœ˜CKšœ œ.œ)œ7˜‘Kšœœœœ˜5Kšœœœ3œ˜nKšœœœ'œ˜\K˜K˜—K˜š œœ˜,Kšœ œ˜šœ8œœ˜KKšœ"œœ˜/Kšœœœ˜&K˜K˜Kšœ˜—Kšœ˜—K˜š œœ˜*Kšœ œ˜šœ0œœ˜CKšœœœ˜'Kšœœœ˜&K˜K˜Kšœ˜—Kšœ˜—K˜š  œœœ˜)Kšœ˜Kšœœœœ˜;K˜#šœ ˜K˜1˜:K˜—Kšœœ˜—Kšœ˜—K˜š  œœœ˜%š  œœ˜(K˜šœ˜Kšœ9˜=Kšœ$˜(—šœ˜Kšœ9˜=Kšœ%˜)—Kšœ3˜3—Kšœ˜Kšœ˜K˜Kšœœœœœœœœ)˜p—K˜š  œœœœœ œœ˜DKšœœ˜!K˜&—K˜Kšœ˜K˜KšœΟg}˜€KšœΟm}˜€——…—dΌ‚‘