<> <> <> <> <> <> <> DIRECTORY CD, CDBasics, CDIO, CDSymbolicObjects, Core, CoreClasses, CoreDirectory, CoreOps, CoreProperties, PW, PWCore, PWPins, Rope, Route, RTBasic, RTCoreUtil, SC, SCInstUtil, SCObjUtil, SCNetUtil, SCPrivate, SCUtil, TerminalIO; SCGetStructureImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDIO, CDSymbolicObjects, CoreClasses, CoreDirectory, CoreOps, CoreProperties, PW, PWCore, PWPins, Rope, RTBasic, RTCoreUtil, SC, SCInstUtil, SCObjUtil, SCNetUtil, SCUtil, TerminalIO EXPORTS SCPrivate SHARES SC = BEGIN debug: BOOLEAN _ FALSE; GetStructure: PUBLIC PROCEDURE [handle: SC.Handle, cellType: Core.CellType, flattenCellType: RTCoreUtil.FlattenCellTypeProc] RETURNS [done: BOOLEAN _ TRUE] = { InternalWireProc: RTCoreUtil.FlatWireProc = { net: SCPrivate.Net _ SCUtil.FindNetByWire[handle, wire]; IF net # NIL THEN SC.Signal[callingError, Rope.Cat["Duplicate net name: ", pathName]] ELSE net _ SCNetUtil.DefineNet[handle, wire, pathName]}; ExternalWireProc: RTCoreUtil.FlatWireProc = { instance: SCPrivate.Instance _ SCUtil.FindInstance[handle, pathName]; net: SCPrivate.Net _ SCUtil.FindNetByWire[handle, wire]; IF net = NIL THEN SC.Signal[callingError, Rope.Cat["Missing net name: ", pathName]]; IF instance # NIL THEN SC.Signal[callingError, Rope.Cat["Duplicate port name: ", pathName, ", object: ", parms.portObject.name]]; IF instance = NIL AND net # NIL AND ~SCUtil.IsPowerName[handle, pathName] THEN {instance _ SCInstUtil.DefineInstance[handle, pathName, parms.portObject, NIL, CoreOps.GetShortWireName[wire]]; SCNetUtil.AddConnection[handle, net, instance, parms.portObject.pins.p[0], 0, externalPin]; net.externNet _ externalNet; GetIOProperties[handle, instance, net, wire]}}; InstanceProc: RTCoreUtil.FlatInstanceProc = { typeName: Rope.ROPE _ CoreOps.GetCellTypeName[cellInstance.type]; object: SCPrivate.Object _ SCUtil.FindObject[handle, typeName]; IF object = NIL THEN object _ DefineObject[handle, typeName, logic, cellInstance.type]; IF object = NIL THEN SC.Signal[callingError, Rope.Cat["Object is not defined: ", typeName, "\n"]] ELSE { EachInstancePin: RTCoreUtil.EachInstancePinProc = { pinName: Rope.ROPE _ CoreOps.GetShortWireName[publicWire]; IF ~SCUtil.IsPowerName[handle, pinName] THEN {net: SCPrivate.Net _ SCUtil.FindNetByWire[handle, actualWire]; pin: SCPrivate.ObjectPin _ SCUtil.FindPin[object, pinName]; -- get the pin IF net = NIL THEN {SC.Signal[callingError, Rope.Cat[Rope.Cat["Net not defined: ", CoreOps.GetShortWireName[actualWire], " on component: ", instance.name], Rope.Cat[", type: ", object.name]]]}; IF pin = NIL THEN {SC.Signal[callingError, Rope.Cat[Rope.Cat["not enough pins on component: ", instance.name], Rope.Cat[", type: ", object.name]]]}; IF pin # NIL AND net # NIL THEN { <> IF Rope.Equal["Vdd", net.name] THEN hasVddConnection _ TRUE; IF Rope.Equal["Gnd", net.name] THEN hasGndConnection _ TRUE; FOR pinIndex: NAT IN [0 .. object.numPins) DO objPin: SCPrivate.ObjectPin _ objectPins.p[pinIndex]; IF objPin # NIL THEN IF Rope.Equal[objPin.name, pin.name] THEN SCNetUtil.AddConnection[handle, net, instance, objPin, pinIndex, compPin]; ENDLOOP}}}; instance: SCPrivate.Instance _ SCInstUtil.DefineInstance[handle, CoreClasses.GetCellInstanceName[cellInstance], object, cellInstance, NIL]; objectPins: SCPrivate.ObjectPins _ object.pins; IF objectPins = NIL THEN SC.Signal[callingError, Rope.Cat[Rope.Cat["Pins not defined on instance: ", instance.name], Rope.Cat[", object: ", object.name, "\n"]]] ELSE { [] _ RTCoreUtil.EnumFlatInstancePins[cellInstance, EachInstancePin]; GetLogicProperties[handle, instance, cellInstance]}}}; hasVddConnection, hasGndConnection: BOOLEAN _ FALSE; <> parms: SCPrivate.Parms _ NARROW[handle.parms]; structureData: SCPrivate.StructureData _ NARROW[NEW[SCPrivate.StructureDataRec], SCPrivate.StructureData]; structureData.objects _ NEW[SCPrivate.ObjectsRec]; structureData.instances _ NEW[SCPrivate.InstancesRec]; structureData.instances.inst _ NEW[SCPrivate.InstsOb]; structureData.nets _ NEW[SCPrivate.NetsRec]; structureData.nets.nets _ NEW[SCPrivate.NetArray]; handle.structureData _ structureData; <<>> <> parms.portObject _ DefineIOType[handle]; parms.ftObject _ DefineFtType[handle, "feedthru"]; parms.vddObject _ DefinePowerType[handle, "vdd"]; parms.gndObject _ DefinePowerType[handle,"gnd"]; TerminalIO.WriteRope["Getting structure description . . .\n"]; RTCoreUtil.Flatten[cellType, flattenCellType, ExternalWireProc, InternalWireProc, InstanceProc, SC.interestingProperties]; <<>> <<-- connect to power cells>> IF hasVddConnection THEN DoPower[handle, "vdd", parms.vddObject, cellType.public, "Vdd"]; IF hasGndConnection THEN DoPower[handle, "gnd", parms.gndObject, cellType.public, "Gnd"]; <<>> <> DoBuses[handle, left]; DoBuses[handle, right]; IF debug THEN SCUtil.WriteStructure[handle]}; DoPower: PROC [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, rootWire: Core.Wire, wireName: Rope.ROPE] ~ { inst: SCPrivate.Instance _ SCInstUtil.DefineInstance[handle, instanceName, object, NIL, NIL]; <> powerWire: Core.Wire _ CoreOps.FindWire[rootWire, wireName]; net: SCPrivate.Net _ SCUtil.FindNetByWire[handle, powerWire]; SCNetUtil.AddConnection[handle, net, inst, object.pins.p[0], 0, compPin]; SCNetUtil.AddConnection[handle, net, inst, object.pins.p[1], 1, compPin]}; DoBuses: PROCEDURE [handle: SC.Handle, lRSide: RTBasic.LRSide] = { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; powerBuses: SCPrivate.PowerBuses _ layoutData.powerBuses; rules: Route.DesignRules _ handle.rules.sideRules; numClocks: NAT _ 0; minWidth: INT _ rules.CDLambda*24 + rules.trunkSpacing; net: SCPrivate.Net _ SCUtil.FindNet[handle, powerBuses[lRSide].name]; pWidth: SC.Number _ IF net # NIL THEN MAX[minWidth, net.trunkWidth + rules.trunkSpacing] ELSE minWidth; powerBuses[lRSide].width _ pWidth; powerBuses[lRSide].net _ net}; DefineObject: PROCEDURE [handle: SC.Handle, objectName: Rope.ROPE, class: SCPrivate.CompClass, cellType: Core.CellType _ NIL] RETURNS [object: SCPrivate.Object _ NIL] = { <> <<>> <> CountPins: PWPins.InstanceEnumerator = { IF UsePin[inst] THEN object.numPins _ object.numPins + 1}; UsePin: PROC [pin: CD.Instance] RETURNS [useIt: BOOLEAN _ FALSE] ~ { IF CDSymbolicObjects.IsSymbolicOb[pin.ob] THEN { side: PWPins.Side _ PWPins.GetSide[ob, pin]; IF side = top OR side = bottom OR useClass = io THEN useIt _ TRUE}}; structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; objects: SCPrivate.Objects _ structureData.objects; parms: SCPrivate.Parms _ NARROW[handle.parms]; numPins: NAT _ 0; obRect: CD.Rect; useClass: SCPrivate.CompClass; size, orgin: RTBasic.PQPos; ob: CD.Object _ NIL; SELECT TRUE FROM class = io => {ob _ BuildIOObject[handle]; useClass _ io}; class = ft OR class = other => { lib: CoreDirectory.Library _ CoreDirectory.FetchLibrary[parms.libName]; ct: Core.CellType _ CoreDirectory.Fetch[lib, objectName]; ob _ PWCore.Layout[ct]; IF class = other THEN useClass _ logic ELSE useClass _ ft; -- make power connection cells logic cells -- }; ENDCASE => { IF PWCore.GetLayoutAtom[cellType] # NIL THEN { ob _ PWCore.Layout[cellType]; useClass _ logic} ELSE IF parms.libName # NIL THEN { IF parms.libDesign # NIL THEN parms.libDesign _ CDIO.ReadDesign[parms.libName, NIL, CDIO.GetWorkingDirectory[]]; -- this is buggy!!! LMM ob _ PW.Get[parms.libDesign, objectName]; useClass _ logic}; }; <> <> <> <> <> <> <> <> <> <<{ob _ PWCore.Layout[cellType];>> <> <> <> <> <> <> <<>> IF ob = NIL THEN { SC.Signal[callingError, Rope.Cat["Core object: ", objectName, " not in CND library"]]; RETURN}; obRect _ CD.InterestRect[ob].r; size _ RTBasic.XYToPQ[horizontal, CDBasics.SizeOfRect[obRect]]; orgin _ RTBasic.XYToPQ[horizontal, CDBasics.BaseOfAnyRect[obRect]]; objects.count _ objects.count + 1; object _ NEW[SCPrivate.ObjectRec _ [objectName, objects.count, size, orgin, 0, NIL, useClass, 0, ob]]; objects.ob[objects.count] _ object; <<>> <> [] _ PWPins.EnumerateDeepPins[ob, CountPins]; object.pins _ NEW[SCPrivate.ObjectPinsRec[object.numPins]]; IF object.numPins > 0 THEN { PinEnum: PWPins.InstanceEnumerator = { name: Rope.ROPE _ CDSymbolicObjects.GetName[inst]; IF UsePin[inst] THEN {pinPos: SCPrivate.PinPos; rect: SC.Rect; objectPin: SCPrivate.ObjectPin; name: Rope.ROPE _ CDSymbolicObjects.GetName[inst]; layer: SC.Layer _ CDSymbolicObjects.GetLayer[inst]; [pinPos, rect] _ GetPinPos[inst.location, inst.ob.size, object, obRect]; objectPin _ NEW[SCPrivate.ObjectPinRec _ [name, pinPos, inst, rect, layer, name]]; object.pins.p[numPins] _ objectPin; numPins _ numPins + 1}}; [] _ PWPins.EnumerateDeepPins[ob, PinEnum]}; <> IF cellType # NIL THEN { WireEnum: RTCoreUtil.EachWireProc = { IF ~SCUtil.IsPowerName[handle, CoreOps.GetShortWireName[wire]] THEN {IF SCUtil.FindPin[object, CoreOps.GetShortWireName[wire]] = NIL THEN SC.Signal[callingError, Rope.Cat["Physical pins and logical pins on object: ", object.name, " do not correspond"]]}}; [] _ RTCoreUtil.EnumerateFlatWires[cellType.public, WireEnum]}}; DefineFtType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object _ NIL] = { IF SCUtil.FindObject[handle, name] # NIL THEN { SC.Signal[callingError, Rope.Cat["Duplicate FeedThru object: ", name, "\n"]]; RETURN}; object _ DefineObject[handle, name, ft]; IF object = NIL THEN SC.Signal[callingError, Rope.Cat["FeedThru object is not defined: ", name, "\n"]]}; DefineIOType: PROCEDURE [handle: SC.Handle] RETURNS [object: SCPrivate.Object] = { object _ DefineObject[handle, NIL, io]; IF object = NIL THEN SC.Signal[callingError, "IO object is not defined \n"]}; DefinePowerType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object _ NIL] = { IF SCUtil.FindObject[handle, name] # NIL THEN { SC.Signal[callingError, Rope.Cat["Duplicate Power object: ", name, "\n"]]; RETURN}; object _ DefineObject[handle, name, other]; IF object = NIL THEN SC.Signal[callingError, Rope.Cat["Power object is not defined: ", name, "\n"]]}; GetPinPos: PROCEDURE [loc, size: SC.Pos, object: SCPrivate.Object, obRect: CD.Rect] RETURNS [pinPos: SCPrivate.PinPos, rect: SC.Rect] = { <> px, py: SC.Number; rect.x1 _ loc.x - obRect.x1; rect.y1 _ loc.y - obRect.y1; rect.x2 _ loc.x + size.x - obRect.x1; rect.y2 _ loc.y + size.y - obRect.y1; py _ (rect.y1 + rect.y2)/2; px _ (rect.x1 + rect.x2)/2; IF py > object.size.q/2 THEN RETURN [[top, object.size.q - py, object.size.p - px], rect] ELSE RETURN [[bottom, py, px], rect]}; BuildIOObject: PROCEDURE [handle: SC.Handle] RETURNS [object: CD.Object _ PW.CreateEmptyCell[]] = { minSize: SC.Number _ handle.rules.rowRules.trunkWidth; [] _ PW.IncludeInCell[object, CDSymbolicObjects.CreateSegment[length: minSize]]; CDCells.SetInterestRect[object, [0, 0, minSize, minSize]]; -- set interestRect of cell RTBasic.RepositionCell[object]}; GetLogicProperties: PROCEDURE [handle: SC.Handle, instance: SCPrivate.Instance, cellInstance: CoreClasses.CellInstance] = { ProcProps: PROC [prop: ATOM, val: REF ANY] ~ { SELECT TRUE FROM prop = SC.rowProp => instance.fnlRow _ NARROW[val, REF INT]^; prop = SC.positionProp => instance.fnlPos _ NARROW[val, REF INT]^; ENDCASE; }; CoreProperties.Enumerate[cellInstance.properties, ProcProps]}; GetSide: PROC [atom: ATOM] RETURNS [side: SC.SideOrNone] ~ { side _ SELECT atom FROM SC.bottomSideValue => bottom, SC.rightSideValue => right, SC.topSideValue => top, SC.leftSideValue => left, ENDCASE => SC.Error[programmingError, "Not suppose to happen."]; }; GetIOProperties: PROCEDURE [handle: SC.Handle, instance: SCPrivate.Instance, net: SCPrivate.Net, wire: Core.Wire] = { ProcProps: PROC [prop: ATOM, val: REF ANY] ~ { SELECT TRUE FROM prop = SC.sideProp => instance.fnlSide _ GetSide[NARROW[val, ATOM]]; prop = SC.positionProp => instance.fnlPos _ NARROW[val, REF INT]^; prop = SC.leftPowerProp => { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; layoutData.powerBuses[left].name _ NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]; layoutData.powerBuses[left].net _ net}; prop = SC.rightPowerProp => { layoutData: SCPrivate.LayoutData _ NARROW[handle.layoutData]; layoutData.powerBuses[right].name _ NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]; layoutData.powerBuses[right].net _ net}; ENDCASE; }; CoreProperties.Enumerate[wire.properties, ProcProps]}; DestroyStructure: PUBLIC PROC [handle: SC.Handle] ~ { EachObj: SCObjUtil.EachObjectProc ~ { EachPin: SCObjUtil.EachPinProc ~ { objectPin.cdPin _ NIL}; [] _ SCObjUtil.EnumeratePinsOnObject[object, EachPin]; object.pins _ NIL; object.cdOb _ NIL; objects.ob[object.objectNum] _ NIL}; EachInst: SCInstUtil.EachInstanceProc ~ { EachPin: SCInstUtil.EachPinProc ~ { netPin.pin _ NIL; netPin.net _ NIL}; [] _ SCInstUtil.EnumeratePinsOnInst[instance, EachPin]; instance.pinNets _ NIL; instance.ftNet _ NIL; instances.inst[instance.num] _ NIL}; EachNet: SCNetUtil.EachNetProc ~ { EachPin: SCNetUtil.EachPinProc ~ { netPin.pin _ NIL; netPin.instance _ NIL}; [] _ SCNetUtil.EnumeratePinsOnNet[net, EachPin]; net.pins _ NIL; net.netDat _ NIL; nets.nets[net.num] _ NIL}; structureData: SCPrivate.StructureData _ NARROW[handle.structureData]; objects: SCPrivate.Objects _ structureData.objects; instances: SCPrivate.Instances _ structureData.instances; nets: SCPrivate.Nets _ structureData.nets; [] _ SCObjUtil.EnumerateAllObjects[handle, EachObj]; [] _ SCInstUtil.EnumerateAllInstances[handle, EachInst]; [] _ SCNetUtil.EnumerateNets[handle, EachNet]; structureData.objects _ NIL; structureData.instances _ NIL; structureData.nets _ NIL; handle.structureData _ NIL}; END.