<> <> <> <> <> <> <> DIRECTORY CD, CDBasics, CDCells, CDSymbolicObjects, Core, CoreClasses, CoreDirectory, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, DABasics, IO, PWCore, RefTab, Rope, Route, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCNetUtil, SCPrivate, SCUtil, Sinix, TerminalIO; SCGetStructureImpl: CEDAR PROGRAM IMPORTS CD, CDBasics, CDCells, CDSymbolicObjects, CoreDirectory, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PWCore, RefTab, Rope, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCNetUtil, SCUtil, Sinix, TerminalIO EXPORTS SCPrivate SHARES SC = BEGIN debug: BOOLEAN _ FALSE; <> DefineRect: PROC [obRect: SC.Rect, min, max, depth: INT, side: CoreGeometry.Side] RETURNS [pinRect: SC.Rect] ~ { SELECT side FROM bottom => pinRect _ [min, obRect.y1, max, obRect.y1 + depth]; right => pinRect _ [obRect.x2 - depth, min, obRect.x2, max]; top => pinRect _ [min, obRect.y2 - depth, max, obRect.y2]; left => pinRect _ [obRect.x2, min, obRect.x2 + depth, max]; ENDCASE; }; CreateObject: PROC [handle: SC.Handle, class: SCPrivate.CompClass, ob: CD.Object, cellType: Core.CellType] RETURNS [object: SCPrivate.Object] ~ { <> <> <> PinEnum: CoreGeometry.EachWirePinProc = { IF (side=top OR side=bottom) AND layer=branchLayer THEN { <> rect: SC.Rect = DefineRect[obRect, min, max, branchWidth, side]; name: Rope.ROPE = CoreOps.GetShortWireName[wire]; IF side=none THEN ERROR; pinList _ CONS [NEW[SCPrivate.ObjectPinRec _ [name: name, pinPos: [side, 0, (max+min)/2], publicWire: wire, rect: rect, layer: layer, equivClass: name]], pinList]; numPins _ numPins + 1; }; }; branchLayer: CD.Layer = handle.rules.rowRules.branchLayer; -- shortcut branchWidth: INT = handle.rules.rowRules.branchWidth; -- shortcut name: Rope.ROPE = CoreOps.GetCellTypeName[cellType]; -- will be object name obRect: CD.Rect; pinList: LIST OF SCPrivate.ObjectPin _ NIL; -- used to build the object pins numPins: NAT _ 0; -- always the size of pinList pins: SCPrivate.ObjectPins; -- stored in the object decoration: CoreGeometry.Decoration = NARROW[handle.parms, SCPrivate.Parms].mode.decoration; IF ob=NIL THEN ERROR SC.Error[callingError, Rope.Cat["No CD object for CellType ", name]]; obRect _ CD.InterestRect[ob]; [] _ CoreGeometry.EnumerateNonOverlappingSides[decoration, cellType, PinEnum]; pins _ NEW[SCPrivate.ObjectPinsRec[numPins]]; -- just the right size FOR i: NAT IN [0..numPins) DO -- put the pins in the object structure pins[i] _ pinList.first; pinList _ pinList.rest; ENDLOOP; object _ NEW[SCPrivate.ObjectRec _ [name: name, size: RTBasic.XYToPQ[horizontal, CDBasics.SizeOfRect[obRect]], orgin: RTBasic.XYToPQ[horizontal, CDBasics.BaseOfRect[obRect]], numPins: numPins, pins: pins, typeClass: class, numTimesUsed: 0, cdOb: ob, cellType: cellType]]; }; DefineFtType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object] = { <> parms: SCPrivate.Parms = NARROW[handle.parms]; cellType: Core.CellType = CoreDirectory.Fetch[parms.libName, name]; -- get from library IF cellType=NIL THEN ERROR SC.Error[callingError, Rope.Cat["FeedThru object not found in library: ", name]]; -- quite deadly... object _ CreateObject[handle, ft, PWCore.Layout[cellType], cellType]; }; DefinePowerType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object] = { <> parms: SCPrivate.Parms = NARROW[handle.parms]; cellType: Core.CellType = CoreDirectory.Fetch[parms.libName, name]; -- get from library IF cellType=NIL THEN ERROR SC.Error[callingError, Rope.Cat["Power object not found in library: ", name]]; -- quite deadly... object _ CreateObject[handle, logic, PWCore.Layout[cellType], cellType]; -- make power connection cells logic cells }; DefineIOType: PROCEDURE [handle: SC.Handle] RETURNS [object: SCPrivate.Object] = { <> mode: Sinix.Mode = NARROW[handle.parms, SCPrivate.Parms].mode; ob: CD.Object _ BuildIOObject[handle]; cellType: Core.CellType = NARROW [Sinix.Extract[ob, mode, NIL, NIL].result]; [] _ CoreOps.SetCellTypeName[cellType, "--IO Object--"]; -- documentation only... object _ CreateObject[handle, io, ob, cellType]; }; BuildIOObject: PROCEDURE [handle: SC.Handle] RETURNS [object: CD.Object] = { <> minSize: SC.Number = handle.rules.rowRules.branchWidth; symInst: CD.Instance; object _ CDCells.CreateEmptyCell[]; symInst _ RouteUtil.Include[object, CDSymbolicObjects.CreateSegment[length: minSize], [minSize, 0], CDSymbolicObjects.OrientFromDirection[south]]; CDSymbolicObjects.SetLayer[symInst, handle.rules.rowRules.branchLayer]; CDSymbolicObjects.SetName[symInst, "io"]; CDCells.SetInterestRect[design: NIL, cell: object, r: [0, 0, minSize, minSize]]; -- set interestRect of cell RTBasic.RepositionCell[object]; }; <> GetStructure: PUBLIC PROCEDURE [handle: SC.Handle, flattenCellType: RTCoreUtil.FlattenCellTypeProc] RETURNS [done: BOOL _ TRUE] ~ { InternalWireProc: RTCoreUtil.FlatWireProc ~ { <> [] _ SCNetUtil.DefineNet[handle, NEW [CoreFlat.FlatWireRec _ flatWire]]; }; ExternalWireProc: RTCoreUtil.FlatWireProc ~ { <> pathName: Rope.ROPE = CoreRoute.LabelFlatWire[root, flatWire]; -- for port instance names instance: SCPrivate.Instance _ SCUtil.FindInstance[handle, pathName]; net: SCPrivate.Net = SCNetUtil.FindPublicNet[handle, flatWire.wire]; IF instance # NIL THEN { -- this is an error, signal and return, net already tested SC.Signal[callingError, Rope.Cat["Duplicate port name: ", CoreRoute.LabelFlatWire[root, flatWire], ", object: ", parms.portObject.name]]; RETURN; }; net.externNet _ TRUE; net.publicWire _ flatWire.wire; IF SCUtil.IsPowerName[handle, CoreOps.GetShortWireName[flatWire.wire]] THEN RETURN; -- nothing more to do FOR side: DABasics.Side IN [bottom .. right] DO <> IF NOT WireOnSide[side, flatWire.wire] THEN LOOP; -- not interesting instance _ SCInstUtil.DefineInstance[handle, pathName, parms.portObject, pathName]; SCNetUtil.AddConnection[handle, net, instance, parms.portObject.pins.p[0], 0, externalPin]; instance.fnlSide _ side; instance.fnlPos _ GetIOPosition[side, flatWire.wire.properties, usePositions]; ENDLOOP; IF instance = NIL THEN { -- no side restriction, leave the pin free to move instance _ SCInstUtil.DefineInstance[handle, pathName, parms.portObject, pathName]; SCNetUtil.AddConnection[handle, net, instance, parms.portObject.pins.p[0], 0, externalPin]; }; }; InstanceProc: RTCoreUtil.FlatInstanceProc ~ { <> EachPublic: PROC [publicWire: Core.Wire] = { pinName: Rope.ROPE = CoreOps.GetShortWireName[publicWire]; flatWire: CoreFlat.FlatWire; net: SCPrivate.Net; thisPin: SCPrivate.ObjectPin; IF SCUtil.IsPowerName[handle, pinName] THEN RETURN; -- nothing to do <> flatWire _ NARROW [RefTab.Fetch[bindings, publicWire].val]; net _ SCNetUtil.FindNet[handle, flatWire]; -- get the net thisPin _ SCUtil.FindPin[object, pinName]; -- get the pin IF thisPin=NIL THEN { -- Error case: signal & return, net already handled SC.Signal[callingError, Rope.Cat["Pin not found: ", pinName, Rope.Cat[" on component: ", instance.name, ", type: ", object.name]]]; RETURN; }; 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 -- add all pins for wire to net objPin: SCPrivate.ObjectPin = object.pins.p[pinIndex]; IF objPin#NIL AND objPin.publicWire=thisPin.publicWire THEN SCNetUtil.AddConnection[handle, net, instance, objPin, pinIndex, compPin]; ENDLOOP; }; instance: SCPrivate.Instance; pathName: Rope.ROPE _ CoreFlat.InstancePathRope[root, flatCellType.path]; object: SCPrivate.Object _ NARROW [RefTab.Fetch[objectTable, cell].val]; IF object = NIL THEN { -- create the new object object _ CreateObject[handle, logic, PWCore.Layout[cell], cell]; [] _ RefTab.Insert[objectTable, cell, object]; }; instance _ SCInstUtil.DefineInstance[handle, pathName, object, NIL]; SCInstUtil.DefineSourceInstance[handle, NEW [CoreFlat.FlatCellTypeRec _ flatCellType], instance]; CoreOps.VisitRootAtomics[cell.public, EachPublic]; GetLogicProperties[instance, properties]; }; root: Core.CellType = handle.coreCellType; hasVddConnection, hasGndConnection: BOOLEAN _ FALSE; usePositions: BOOL _ RTCoreUtil.GetCoreBoolProp[root, SC.usePublicPositionsProp, FALSE]; objectTable: RefTab.Ref _ RefTab.Create[]; -- temporary table cell -> Object <> parms: SCPrivate.Parms _ NARROW[handle.parms]; structureData: SCPrivate.StructureData _ NEW [SCPrivate.StructureDataRec _ [ instances: NEW [SCPrivate.InstancesRec _ [inst: NEW [SCPrivate.InstsOb]]], nets: RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash], sourceInstances: RefTab.Create[equal: CoreFlat.FlatCellTypeEqual, hash: CoreFlat.FlatCellTypeHash] ]]; handle.structureData _ structureData; <> parms.portObject _ DefineIOType[handle]; parms.ftObject _ DefineFtType[handle, "feedthru"]; parms.vddObject _ DefinePowerType[handle, "vdd"]; parms.gndObject _ DefinePowerType[handle, "gnd"]; <> TerminalIO.PutRope["Getting structure description . . .\n"]; RTCoreUtil.Flatten[root, flattenCellType, ExternalWireProc, InternalWireProc, InstanceProc, SC.interestingProperties]; <> IF hasVddConnection THEN DoPower[handle, "Vdd", parms.vddObject, "Vdd"]; IF hasGndConnection THEN DoPower[handle, "Gnd", parms.gndObject, "Gnd"]; <> DoBuses[handle, left]; DoBuses[handle, right]; <> TerminalIO.PutF["Statistics: \n instances: %g, wires: %g, public wires: %g cells: %g\n", IO.int[structureData.instances.numLogics], IO.int[RefTab.GetSize[structureData.nets]], IO.int[structureData.instances.numIOs], IO.int[RefTab.GetSize[objectTable]]]; IF debug THEN SCUtil.WriteStructure[handle]; }; DoPower: PROC [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, wireName: Rope.ROPE] ~ { <> instance: SCPrivate.Instance _ SCInstUtil.DefineInstance[handle, instanceName, object, NIL]; net: SCPrivate.Net _ SCNetUtil.FindPublicNet[handle, CoreOps.FindWire[handle.coreCellType.public, wireName]]; SCNetUtil.AddConnection[handle, net, instance, object.pins.p[0], 0, compPin]; SCNetUtil.AddConnection[handle, net, instance, object.pins.p[1], 1, compPin]; }; DoBuses: PROCEDURE [handle: SC.Handle, lRSide: RTBasic.LRSide] = { <> layoutData: SCPrivate.LayoutData = NARROW[handle.layoutData]; wireName: Rope.ROPE = layoutData.powerBuses[lRSide].name; net: SCPrivate.Net _ SCNetUtil.FindPublicNet[handle, CoreOps.FindWire[handle.coreCellType.public, wireName]]; layoutData.powerBuses[lRSide].net _ net; }; GetLogicProperties: PROCEDURE [instance: SCPrivate.Instance, properties: Core.Properties] = { <> EachProperty: PROC [prop: ATOM, val: REF ANY] ~ { SELECT prop FROM SC.rowProp => instance.fnlRow _ NARROW[val, REF INT]^; SC.positionProp => instance.fnlPos _ NARROW[val, REF INT]^; ENDCASE; }; CoreProperties.Enumerate[properties, EachProperty]; }; WireOnSide: PROC [side: DABasics.Side, wire: Core.Wire] RETURNS [onSide: BOOL _ FALSE] ~ { <> ProcProps: PROC [prop: ATOM, val: REF ANY] ~ { SELECT prop FROM SC.bottomSideProp => IF side = bottom THEN onSide _ TRUE; SC.rightSideProp => IF side = right THEN onSide _ TRUE; SC.topSideProp => IF side = top THEN onSide _ TRUE; SC.leftSideProp => IF side = left THEN onSide _ TRUE; ENDCASE; }; CoreProperties.Enumerate[wire.properties, ProcProps]; }; GetIOPosition: PROC [side: DABasics.Side, properties: Core.Properties, usePositions: BOOL] RETURNS [position: INT _ 0] ~ { <> ProcProps: PROC [prop: ATOM, val: REF ANY] ~ { SELECT prop FROM SC.bottomPositionProp => IF side = bottom THEN position _ NARROW[val, REF INT]^; SC.rightPositionProp => IF side = right THEN position _ NARROW[val, REF INT]^; SC.topPositionProp => IF side = top THEN position _ NARROW[val, REF INT]^; SC.leftPositionProp => IF side = left THEN position _ NARROW[val, REF INT]^; ENDCASE; }; IF usePositions THEN CoreProperties.Enumerate[properties, ProcProps]; }; DestroyStructure: PUBLIC PROC [handle: SC.Handle] ~ { <> EachInst: SCInstUtil.EachInstanceProc ~ { IF instance.pinNets#NIL THEN FOR i: NAT IN [0..instance.pinNets.size) DO -- destroy pinNets instance.pinNets[i]^ _ []; instance.pinNets[i] _ NIL; ENDLOOP; instance.pinNets _ NIL; instance.ftNet _ NIL; instances.inst[instance.num] _ NIL; instance.object.pins _ NIL; instance.object.cdOb _ NIL; instance.object.cellType _ NIL; }; EachNet: RefTab.EachPairAction ~ { -- destroy the net thoroughly net: SCPrivate.Net _ NARROW [val]; netPin: SCPrivate.NetPin _ net.pins; WHILE netPin#NIL DO -- destroy the list of pins thoroughly next: SCPrivate.NetPin = netPin.link; netPin^ _ []; netPin _ next; ENDLOOP; <> net^ _ []; }; structureData: SCPrivate.StructureData = NARROW[handle.structureData]; instances: SCPrivate.Instances = structureData.instances; [] _ SCInstUtil.EnumerateAllInstances[handle, EachInst]; RefTab.Erase[structureData.sourceInstances]; [] _ RefTab.Pairs[structureData.nets, EachNet]; RefTab.Erase[structureData.nets]; structureData^ _ []; handle.structureData _ NIL; }; END.