<> <> <> DIRECTORY CD, CDBasics, CDDirectory, CDSymbolicObjects, Convert, Core, CoreClasses, CoreFlat, CoreGeometry, CoreOps, CoreProperties, HashTable, Properties, PW, PWCore, PWPins, Rope, RTBasic, RTCoreUtil, RTStructure, TerminalIO; RTStructureImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDDirectory, CDSymbolicObjects, Convert, CoreClasses, CoreGeometry, CoreOps, CoreProperties, HashTable, PW, PWCore, PWPins, Rope, RTBasic, RTCoreUtil, RTStructure, TerminalIO EXPORTS RTStructure = BEGIN <> Error: PUBLIC ERROR[errorType: RTStructure.ErrorType _ callingError, explanation: Rope.ROPE _ NIL] = CODE; Signal: PUBLIC SIGNAL[signalType: RTStructure.ErrorType _ callingError, explanation: Rope.ROPE _ NIL] = CODE; <> <> CreateForRopes: PUBLIC PROC [name: Rope.ROPE, nInsts, nObjs, nNets, nPubs: HashTable.SeqIndex _ 17, netWidth: RTStructure.NetWidthProc _ WidestPinProc, properties: Properties.PropList _ NIL] RETURNS [RTStructure.Structure] ~ { RETURN[NEW[RTStructure.StructureRec _ [name: name, instances: HashTable.Create[nInsts, HashTable.RopeEqual, HashTable.HashRope], objects: HashTable.Create[nObjs, HashTable.RopeEqual, HashTable.HashRope], nets: HashTable.Create[nNets, HashTable.RopeEqual, HashTable.HashRope], netWidth: netWidth -- , properties: CoreProperties.CopyProps[properties] -- ]]]}; <> CreateForRefs: PUBLIC PROC [name: Rope.ROPE, nInsts, nObjs, nNets, nPubs: HashTable.SeqIndex _ 17, netWidth: RTStructure.NetWidthProc _ WidestPinProc, properties: Properties.PropList _ NIL] RETURNS [RTStructure.Structure] ~ { RETURN[NEW[RTStructure.StructureRec _ [name: name, instances: HashTable.Create[nInsts], objects: HashTable.Create[nObjs], nets: HashTable.Create[nNets], netWidth: netWidth -- , properties: CoreProperties.CopyProps[properties] -- ]]]}; <> <> FetchInstance: PUBLIC PROC [structure: RTStructure.Structure, key: RTStructure.Key] RETURNS [found: BOOLEAN, instance: RTStructure.Instance] ~ { <> <> <> value: REF; [found, value] _ HashTable.Fetch[structure.instances, key]; instance _ NARROW[value]}; FetchInstancePin: PUBLIC PROC [instance: RTStructure.Instance, key: RTStructure.Key] RETURNS [found: BOOLEAN, iPin: RTStructure.InstancePin] ~ { <> <> <> value: REF; [found, value] _ HashTable.Fetch[instance.iPins, key]; iPin _ NARROW[value]}; EnumerateInstances: PUBLIC PROC [structure: RTStructure.Structure, action: RTStructure.EachInstanceAction] RETURNS [quit: BOOLEAN] ~ { <> <> <> <> eachPair: HashTable.EachPairAction ~ { TRUSTED{instance _ LOOPHOLE[value]}; quit _ action[key, instance]}; instance: RTStructure.Instance; RETURN[HashTable.Pairs[structure.instances, eachPair]]}; EnumerateInstancePins: PUBLIC PROC [instance: RTStructure.Instance, action: RTStructure.EachInstancePinAction] RETURNS [quit: BOOLEAN] ~ { <> <> <> <> eachPair: HashTable.EachPairAction ~ { TRUSTED{instancePin _ LOOPHOLE[value]}; quit _ action[key, instance, instancePin]}; instancePin: RTStructure.InstancePin; RETURN[HashTable.Pairs[instance.iPins, eachPair]]}; <> FetchObject: PUBLIC PROC [structure: RTStructure.Structure, key: RTStructure.Key] RETURNS [found: BOOLEAN, object: RTStructure.Object] ~ { <> <> <> value: REF; [found, value] _ HashTable.Fetch[structure.objects, key]; object _ NARROW[value]}; FetchObjectPin: PUBLIC PROC [object: RTStructure.Object, key: RTStructure.Key] RETURNS [found: BOOLEAN, oPin: RTStructure.ObjectPin] ~ { <> <> <> value: REF; [found, value] _ HashTable.Fetch[object.oPins, key]; oPin _ NARROW[value]}; EnumerateObjects: PUBLIC PROC [structure: RTStructure.Structure, action: RTStructure.EachObjectAction] RETURNS [quit: BOOLEAN] ~ { <> <> <> <> eachPair: HashTable.EachPairAction ~ { TRUSTED{object _ LOOPHOLE[value]}; quit _ action[key, object]}; object: RTStructure.Object; RETURN[HashTable.Pairs[structure.objects, eachPair]]}; EnumerateObjectPins: PUBLIC PROC [object: RTStructure.Object, action: RTStructure.EachObjectPinAction] RETURNS [quit: BOOLEAN] ~ { <> <> <> <> eachPair: HashTable.EachPairAction ~ { TRUSTED{oPin _ LOOPHOLE[value]}; quit _ action[key, object, oPin]}; oPin: RTStructure.ObjectPin; RETURN[HashTable.Pairs[object.oPins, eachPair]]}; EnumeratePhysicalPins: PUBLIC PROC [oPin: RTStructure.ObjectPin, action: RTStructure.EachPhysicalPinAction] RETURNS [quit: BOOLEAN _ FALSE] ~ { <> <> <> <> FOR list: LIST OF RTStructure.PhysicalPin _ oPin.physicalPins, list.rest WHILE list # NIL AND ~quit DO quit _ action[oPin, list.first] ENDLOOP; }; PosOfObjectPin: PUBLIC PROC [object: RTStructure.Object, pPin: RTStructure.PhysicalPin] RETURNS [position: CD.Position] ~ { <> position _ SELECT pPin.side FROM bottom => [pPin.range.min, 0], right => [CD.InterestSize[object.cdObject].x, pPin.range.min], top => [pPin.range.min, CD.InterestSize[object.cdObject].y], left => [0, pPin.range.min], ENDCASE => [0, 0]}; <> FetchNet: PUBLIC PROC [structure: RTStructure.Structure, key: RTStructure.Key] RETURNS [found: BOOLEAN, net: RTStructure.Net] ~ { <> <> <> value: REF; [found, value] _ HashTable.Fetch[structure.nets, key]; net _ NARROW[value]}; FetchNetPin: PUBLIC PROC [net: RTStructure.Net, key: RTStructure.Key] RETURNS [found: BOOLEAN, nPin: RTStructure.NetPin] ~ { <> <> <> value: REF; [found, value] _ HashTable.Fetch[net.nPins, key]; nPin _ NARROW[value]}; EnumerateNets: PUBLIC PROC [structure: RTStructure.Structure, action: RTStructure.EachNetAction] RETURNS [quit: BOOLEAN] ~ { <> <> <> <> eachPair: HashTable.EachPairAction ~ { TRUSTED{net _ LOOPHOLE[value]}; quit _ action[key, net]}; net: RTStructure.Net; RETURN[HashTable.Pairs[structure.nets, eachPair]]}; EnumerateNetPins: PUBLIC PROC [net: RTStructure.Net, action: RTStructure.EachNetPinAction] RETURNS [quit: BOOLEAN] ~ { <> <> <> <> <<>> eachPair: HashTable.EachPairAction ~ { TRUSTED{nPin _ LOOPHOLE[value]}; quit _ action[key, net, nPin]}; nPin: RTStructure.NetPin; RETURN[HashTable.Pairs[net.nPins, eachPair]]}; WidestPinProc: PUBLIC RTStructure.NetWidthProc ~ { <> EachNetPin: RTStructure.EachNetPinAction ~ { <> EachPhysicalPin: RTStructure.EachPhysicalPinAction ~ { <> wireWidth _ MAX[wireWidth, pPin.range.max - pPin.range.min]}; [] _ EnumeratePhysicalPins[nPin.oPin, EachPhysicalPin]}; wireWidth _ 0; [] _ EnumerateNetPins[net, EachNetPin]}; IsPublic: PUBLIC PROC [net: RTStructure.Net] RETURNS [isPublic: BOOLEAN] ~ { <> EachNetPin: RTStructure.EachNetPinAction ~ { <> quit _ nPin.instance.object.heirarchyLevel = nextHigher}; isPublic _ EnumerateNetPins[net, EachNetPin]}; <> CreateFromCore: PUBLIC PROC [cellType: Core.CellType, flattenCellType: RTCoreUtil.FlattenCellTypeProc, pinFilter: RTStructure.CorePinFilterProc _ NIL, interestingProperties: RTCoreUtil.PropertyKeys, userData: REF ANY _ NIL, decoration: CoreGeometry.Decoration, libDesign: CD.Design, properties: Properties.PropList] RETURNS [ structure: RTStructure.Structure] ~ { <> <> <> <> <> <> <> <> <<>> InternalWireProc: RTCoreUtil.FlatWireProc = { <> <> net: RTStructure.Net _ NEW[RTStructure.NetRec _ [name: pathName, nPins: HashTable.Create[] -- , properties: CoreProperties.CopyProps[wire.properties] -- ]]; [] _ RTStructure.StoreNet[structure, wire, net]}; ExternalWireProc: RTCoreUtil.FlatWireProc = { <> <> objectPin: RTStructure.ObjectPin _ NEW[RTStructure.ObjectPinRec _ [name: pathName, heirarchyLevel: nextHigher -- , properties: CoreProperties.CopyProps[wire.properties] -- ]]; netPin: RTStructure.NetPin _ NEW[RTStructure.NetPinRec _ [oPin: objectPin, instance: structure.outerInstance]]; net: RTStructure.Net _ FetchNet[structure, wire].net; instancePin: RTStructure.InstancePin _ NEW[RTStructure.InstancePinRec _ [oPin: objectPin, net: net]]; [] _ RTStructure.StoreObjectPin[structure.outerInstance.object, wire, objectPin]; [] _ RTStructure.StoreInstancePin[structure.outerInstance, wire, instancePin]; [] _ RTStructure.StoreNetPin[net, wire, netPin]}; InstanceProc: RTCoreUtil.FlatInstanceProc = { <> <<>> EachInstancePin: RTCoreUtil.EachInstancePinProc = { <> EachObjectPin: RTStructure.EachObjectPinAction ~ { IF Rope.Equal[oPin.name, name] THEN { IF net # NIL THEN { <> netPin: RTStructure.NetPin _ NEW[RTStructure.NetPinRec _ [oPin: oPin, instance: instance]]; instancePin: RTStructure.InstancePin _ NEW[RTStructure.InstancePinRec _ [oPin: oPin, net: net]]; [] _ RTStructure.StoreInstancePin[instance, publicWire, instancePin]; [] _ RTStructure.StoreNetPin[net, netPin, netPin]}}}; name: Rope.ROPE _ CoreOps.GetShortWireName[publicWire]; net: RTStructure.Net _ FetchNet[structure, actualWire].net; IF net = NIL THEN Signal[callingError, Rope.Cat[Rope.Cat["Net not defined: ", CoreOps.GetShortWireName[actualWire], " on component: ", instance.name], Rope.Cat[", type: ", object.name]]]; [] _ EnumerateObjectPins[object, EachObjectPin]; -- get the pin }; object: RTStructure.Object _ DefineObject[structure, cellInstance.type, pinFilter, userData, decoration, libDesign]; instance: RTStructure.Instance _ DefineInstance[structure, object, cellInstance]; [] _ RTCoreUtil.EnumFlatInstancePins[cellInstance, EachInstancePin]}; outerName: Rope.ROPE _ CoreOps.GetCellTypeName[cellType]; outerObject: RTStructure.Object _ NEW[RTStructure.ObjectRec _ [name: outerName, cdObject: NIL, heirarchyLevel: nextHigher, oPins: HashTable.Create[] -- , properties: CoreProperties.CopyProps[cellType.properties] -- ]]; outerInstance: RTStructure.Instance _ NEW[RTStructure.InstanceRec _ [name: CoreOps.GetCellTypeName[cellType], object: outerObject, iPins: HashTable.Create[]]]; outerCoreInstance: CoreClasses.CellInstance _ CoreClasses.CreateInstance[NIL, cellType]; structure _ CreateForRefs[name: CoreOps.GetCellTypeName[cellType]]; [] _ RTStructure.StoreInstance[structure, outerCoreInstance, outerInstance]; [] _ RTStructure.StoreObject[structure, cellType, outerObject]; structure.outerInstance _ outerInstance; TerminalIO.PutRope["Getting structure description . . .\n"]; RTCoreUtil.Flatten[cellType, flattenCellType, ExternalWireProc, InternalWireProc, InstanceProc, interestingProperties]; }; InsertPublic: PUBLIC PROC [structure: RTStructure.Structure, name: Rope.ROPE, cdObject: CD.Object, pinFilter: RTStructure.CDPinFilterProc, userData: REF ANY, makeHashKey: RTStructure.HashKeyProc] ~ { <> <> }; InsertInstance: PUBLIC PROC [structure: RTStructure.Structure, name: Rope.ROPE, position: CD.Position, orientation: CD.Orientation, cdObject: CD.Object, pinFilter: RTStructure.CDPinFilterProc, userData: REF ANY, makeHashKey: RTStructure.HashKeyProc] ~ { <> <> EachInstPin: CDSymbolicObjects.InstEnumerator = { <<[inst: CD.Instance] RETURNS [quit: BOOL _ FALSE]>> usePin: BOOLEAN _ IF pinFilter = NIL THEN TRUE ELSE pinFilter[inst, cdObject, userData]; IF usePin THEN { InsertInstPin[structure, object, instance, inst, makeHashKey]}}; EachObjPin: CDSymbolicObjects.InstEnumerator = { <<[inst: CD.Instance] RETURNS [quit: BOOL _ FALSE]>> usePin: BOOLEAN _ IF pinFilter = NIL THEN TRUE ELSE pinFilter[inst, cdObject, userData]; IF usePin THEN { InsertObjectPin[structure, object, cdObject, inst, makeHashKey]}}; object: RTStructure.Object; instance: RTStructure.Instance; IF cdObject # NIL THEN { objectName: Rope.ROPE _ CDDirectory.Name[cdObject]; object _ FetchObject[structure, objectName].object; IF object = NIL THEN { object _ NEW[RTStructure.ObjectRec _ [objectName, cdObject, this, HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope] -- , properties: CoreProperties.CopyProps[cdObject.properties] -- ]]; [] _ RTStructure.StoreObject[structure, objectName, object]; [] _ PWPins.EnumerateEdgePins[cdObject, EachObjPin]}; instance _ NEW[RTStructure.InstanceRec _ [name, TRUE, position, orientation, object, HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]]]; [] _ RTStructure.StoreInstance[structure, name, instance]; [] _ PWPins.EnumerateEdgePins[cdObject, EachInstPin]}}; PrintStructure: PUBLIC PROC [structure: RTStructure.Structure] ~ { <> TerminalIO.PutRopes["Writing structure for: ", structure.name, "\n"]; TerminalIO.PutRope[" Objects\n"]; [] _ EnumerateObjects[structure, PrintObject]; TerminalIO.PutRope[" Instances\n"]; [] _ EnumerateInstances[structure, PrintInstance]; TerminalIO.PutRope[" Nets\n"]; [] _ EnumerateNets[structure, PrintNet]}; <> <> InsertInstPin: PROC [structure: RTStructure.Structure, object: RTStructure.Object, instance: RTStructure.Instance, pin: CD.Instance, makeHashKey: RTStructure.HashKeyProc] ~ { netPin: RTStructure.NetPin; instancePin: RTStructure.InstancePin; pinName: Rope.ROPE _ CDSymbolicObjects.GetName[pin]; tabIndex: Rope.ROPE _ IF makeHashKey=NIL THEN pinName ELSE makeHashKey[pin]; netPinName: Rope.ROPE _ Rope.Cat[tabIndex, "/", instance.name]; rect: CD.Rect _ CDSymbolicObjects.Denotes[pin]; objectPin: RTStructure.ObjectPin _ FetchObjectPin[object, tabIndex].oPin; net: RTStructure.Net _ FetchNet[structure, tabIndex].net; IF net = NIL THEN { net _ NEW[RTStructure.NetRec _ [name: tabIndex, nPins: HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope]]]; [] _ RTStructure.StoreNet[structure, tabIndex, net]}; netPin _ NEW[RTStructure.NetPinRec _ [oPin: objectPin, instance: instance]]; instancePin _ NEW[RTStructure.InstancePinRec _ [oPin: objectPin, net: net]]; [] _ RTStructure.StoreInstancePin[instance, netPinName, instancePin]; [] _ RTStructure.StoreNetPin[net, netPinName, netPin]}; <> InsertObjectPin: PROC [structure: RTStructure.Structure, object: RTStructure.Object, cdObject: CD.Object, pin: CD.Instance, makeHashKey: RTStructure.HashKeyProc] ~ { physicalPin: RTStructure.PhysicalPin; pinName: Rope.ROPE _ CDSymbolicObjects.GetName[pin]; tabIndex: Rope.ROPE _ IF makeHashKey=NIL THEN pinName ELSE makeHashKey[pin]; side: RTBasic.Side _ FromSideToSide[PWPins.GetSide[cdObject, pin].side]; outsideRect: CD.Rect _ CD.InterestRect[cdObject]; pinRect: CD.Rect _ CDSymbolicObjects.Denotes[pin]; depth: INT _ SELECT side FROM bottom => pinRect.y1 - outsideRect.y1, right => outsideRect.x2 - pinRect.x2, top => outsideRect.y2 - pinRect.y2, left => pinRect.x1 - outsideRect.x1, ENDCASE => Error[programmingError, "Call maintainer"]; objectPin: RTStructure.ObjectPin _ FetchObjectPin[object, tabIndex].oPin; IF objectPin = NIL THEN { objectPin _ NEW[RTStructure.ObjectPinRec _ [name: tabIndex, heirarchyLevel: this -- , properties: CoreProperties.CopyProps[pin.properties] -- ]]; [] _ RTStructure.StoreObjectPin[object, tabIndex, objectPin]}; physicalPin _ NEW[RTStructure.PhysicalPinRec _ [range: CoordsAlongSide[pin, cdObject, side], side: side, layer: CDSymbolicObjects.GetLayer[pin], depth: depth -- , properties: CoreProperties.CopyProps[pin.properties] -- ]]; RTStructure.StorePhysicalPin[objectPin, physicalPin]}; CoordsAlongSide: PUBLIC PROC [instance: CD.Instance, object: CD.Object, side: RTBasic.Side] RETURNS [range: RTStructure.Range] ~ { pos: CD.Position _ instance.trans.off; size: CD.Position _ CDBasics.SizeOfRect[CDSymbolicObjects.Denotes[instance]]; SELECT side FROM top, bottom => range _ [pos.x, pos.x + size.x]; left, right => range _ [pos.y, pos.y + size.y]; ENDCASE}; FromSideToSide: PUBLIC PROC [side: PWPins.Side] RETURNS [routeSide: RTBasic.Side] = { routeSide _ SELECT side FROM left => left, right => right, top => top, bottom => bottom, ENDCASE => ERROR}; DefineObject: PROC [structure: RTStructure.Structure, cellType: Core.CellType, pinFilter: RTStructure.CorePinFilterProc, userData: REF ANY, decoration: CoreGeometry.Decoration, libDesign: CD.Design] RETURNS [object: RTStructure.Object] = { EachWire: PROC [wire: Core.Wire] ~ { <> name: Rope.ROPE _ CoreOps.GetShortWireName[wire]; objectPin: RTStructure.ObjectPin _ NEW[RTStructure.ObjectPinRec _ [name: name, heirarchyLevel: this -- , properties: CoreProperties.CopyProps[wire.properties] -- ]]; [] _ RTStructure.StoreObjectPin[object, wire, objectPin]}; EachPhysicalPin: CoreGeometry.EachWirePinProc = { <> <> rtSide: RTBasic.Side _ SELECT side FROM bottom => bottom, right => right, top => top, left => left, ENDCASE => RTBasic.Error[programmingError, "Not suppose to happen."]; usePin: BOOLEAN _ IF pinFilter = NIL THEN TRUE ELSE pinFilter[wire, [min, max], rtSide, layer, userData]; IF usePin THEN { range: RTStructure.Range _ [min, max]; depth: INT _ 0; physicalPin: RTStructure.PhysicalPin _ NEW[RTStructure.PhysicalPinRec _ [range: range, side: rtSide, layer: layer, depth: depth -- , properties: CoreProperties.CopyProps[wire.properties] -- ]]; objectPin: RTStructure.ObjectPin _ FetchObjectPin[object, wire].oPin; RTStructure.StorePhysicalPin[objectPin, physicalPin]}}; cdObject: CD.Object _ NIL; object _ FetchObject[structure, cellType].object; IF object = NIL THEN { objectName: Rope.ROPE _ CoreOps.GetCellTypeName[cellType]; <> IF PWCore.GetLayoutAtom[cellType] # NIL THEN cdObject _ PWCore.Layout[cellType] ELSE IF libDesign # NIL THEN cdObject _ PW.Get[libDesign, objectName] ELSE { Signal[callingError, Rope.Cat["Core object: ", objectName, " not in found"]]; RETURN}; IF cdObject = NIL THEN { Signal[callingError, Rope.Cat["Core object: ", objectName, " not in found"]]; RETURN}; <> object _ NEW[RTStructure.ObjectRec _ [name: objectName, cdObject: cdObject, heirarchyLevel: this, oPins: HashTable.Create[] -- , properties: CoreProperties.CopyProps[cellType.properties] -- ]]; [] _ RTStructure.StoreObject[structure, cellType, object]; <> CoreOps.VisitRootAtomics[cellType.public, EachWire]; [] _ CoreGeometry.EnumerateNonOverlappingSides[decoration, cellType, EachPhysicalPin]; }}; DefineInstance: PROC [structure: RTStructure.Structure, object: RTStructure.Object, cellInstance: CoreClasses.CellInstance] RETURNS [instance: RTStructure.Instance] = { name: Rope.ROPE _ NARROW[CoreProperties.GetCellInstanceProp[cellInstance, CoreOps.nameProp]]; instance _ NEW[RTStructure.InstanceRec _ [name: name, object: object, iPins: HashTable.Create[] -- , properties: CoreProperties.CopyProps[cellInstance.properties] -- ]]; [] _ RTStructure.StoreInstance[structure, cellInstance, instance]}; PrintObject: RTStructure.EachObjectAction ~ { PrintObjectPins: RTStructure.EachObjectPinAction ~ { PrintPhysicalPins: RTStructure.EachPhysicalPinAction ~ { TerminalIO.PutRope[Rope.Cat[" range: [", Convert.RopeFromInt[pPin.range.min], ", ", Convert.RopeFromInt[pPin.range.max], "], "]]; TerminalIO.PutRope[Rope.Cat["side: ", RTBasic.sideName[pPin.side], "\n"]]}; TerminalIO.PutRope[Rope.Cat[" ", oPin.name, IF object.heirarchyLevel = this THEN " this" ELSE " nextHigher"]]; [] _ EnumeratePhysicalPins[oPin, PrintPhysicalPins]}; TerminalIO.PutRope[Rope.Cat[" ", object.name, IF object.heirarchyLevel = this THEN " this" ELSE " nextHigher", "\n"]]; TerminalIO.PutRope[Rope.Cat[" connections: ", "\n"]]; [] _ EnumerateObjectPins[object, PrintObjectPins]}; PrintInstance: RTStructure.EachInstanceAction ~ { PrintInstancePins: RTStructure.EachInstancePinAction ~ { TerminalIO.PutRope[Rope.Cat[" net: ", iPin.net.name, ", pin: ", iPin.oPin.name, "\n"]]; }; TerminalIO.PutRope[Rope.Cat[" ", instance.name, "\n"]]; TerminalIO.PutRope[Rope.Cat[" position: [", Convert.RopeFromInt[instance.position.x], ", ", Convert.RopeFromInt[instance.position.y], "], \n"]]; TerminalIO.PutRope[Rope.Cat[" object: ", instance.object.name, "\n"]]; TerminalIO.PutRope[Rope.Cat[" connections: ", "\n"]]; [] _ EnumerateInstancePins[instance, PrintInstancePins]}; PrintNet: RTStructure.EachNetAction ~ { PrintNetPins: RTStructure.EachNetPinAction ~ { TerminalIO.PutRope[Rope.Cat[" instance: ", nPin.instance.name, ", pin: ", nPin.oPin.name, "\n"]]; }; TerminalIO.PutRope[Rope.Cat[" ", net.name, "\n"]]; TerminalIO.PutRope[Rope.Cat[" connections: ", "\n"]]; [] _ EnumerateNetPins[net, PrintNetPins]}; TranslateRange: PUBLIC PROC [instance: RTStructure.Instance, pPin: RTStructure.PhysicalPin] RETURNS [range: RTStructure.Range]~ { <> range _ SELECT pPin.side FROM top, bottom => [instance.position.x + pPin.range.min, instance.position.x + pPin.range.max], left, right => [instance.position.y + pPin.range.min, instance.position.y + pPin.range.max], ENDCASE => RTBasic.Error[programmingError, "Call maintainer."]; }; END.