SCGetStructureImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDSymbolicObjects, CoreClasses, CoreDirectory, CoreGeometry, CoreOps, CoreProperties, IO, PWCore, Rope, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCObjUtil, SCNetUtil, SCUtil, Sinix, SinixOps, TerminalIO
EXPORTS SCPrivate
SHARES SC =
BEGIN
debug: BOOLEAN ← FALSE;
GetStructure:
PUBLIC
PROCEDURE [handle:
SC.Handle, cellType: Core.CellType,
flattenCellType: RTCoreUtil.FlattenCellTypeProc, decoration: CoreGeometry.Decoration]
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 = {
EachInstancePin: RTCoreUtil.EachInstancePinProc = {
IF ~SCUtil.IsPowerName[handle, CoreOps.GetShortWireName[publicWire]]
THEN
do binding of public to actual; this is clumsy because of chaneg to Core Geometry
{net: SCPrivate.Net ← SCUtil.FindNetByWire[handle, actualWire];
thisPin: SCPrivate.ObjectPin ← SCUtil.FindPinByWire[object, publicWire]; -- 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 thisPin =
NIL
THEN
{SC.Signal[callingError, Rope.Cat[Rope.Cat["not enough pins on component: ", instance.name], Rope.Cat[", type: ", object.name]]]};
IF thisPin #
NIL
AND net #
NIL
THEN {
add connection for comp, pin
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 ← object.pins.p[pinIndex];
IF objPin #
NIL
THEN
IF objPin.publicWire = thisPin.publicWire
THEN
SCNetUtil.AddConnection[handle, net, instance, objPin, pinIndex, compPin];
ENDLOOP}}};
instance: SCPrivate.Instance;
object: SCPrivate.Object ← SCUtil.FindObjectByCell[handle, cellInstance.type];
IF object =
NIL
THEN {
object ← DefineObject[handle, CoreOps.GetCellTypeName[cellInstance.type], logic, cellInstance.type];
object.pins ← DefinePinsFromDecoration[handle, object, cellInstance.type, decoration]};
instance ← SCInstUtil.DefineInstance[handle, CoreClasses.GetCellInstanceName[cellInstance], object, cellInstance, NIL];
[] ← RTCoreUtil.EnumFlatInstancePins[cellInstance, EachInstancePin];
GetLogicProperties[handle, instance, cellInstance]};
hasVddConnection, hasGndConnection:
BOOLEAN ←
FALSE;
set up the private data
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;
get auxalliary components
parms.portObject ← DefineIOType[handle, decoration];
parms.ftObject ← DefineFtType[handle, "feedthru", decoration];
parms.vddObject ← DefinePowerType[handle, "vdd", decoration];
parms.gndObject ← DefinePowerType[handle, "gnd", decoration];
TerminalIO.PutRope["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"];
fix up the bus widths based on connectivity
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[structureData.nets.count], IO.int[structureData.instances.numIOs], IO.int[structureData.objects.count]];
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];
construct and add an entry to net list for this instance
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;
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].net ← net};
DefineObject:
PROCEDURE [handle:
SC.Handle, objectName: Rope.
ROPE, class: SCPrivate.CompClass, cellType: Core.CellType ←
NIL]
RETURNS [object: SCPrivate.Object ← NIL] = {
get physical description and define the type
enter a new object into standard cell data structure
structureData: SCPrivate.StructureData ← NARROW[handle.structureData];
objects: SCPrivate.Objects ← structureData.objects;
parms: SCPrivate.Parms ← NARROW[handle.parms];
obRect: CD.Rect;
useClass: SCPrivate.CompClass;
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];
ob ← PWCore.Layout[CoreDirectory.Fetch[lib, objectName]];
IF class = other THEN useClass ← logic ELSE useClass ← ft; -- make power connection cells logic cells -- };
PWCore.GetLayoutAtom[cellType] #
NIL => {
ob ← PWCore.Layout[cellType]; useClass ← logic};
ENDCASE => NULL;
IF ob =
NIL
THEN {
SC.Signal[callingError, Rope.Cat["No layout for cellType: ", CoreOps.GetCellTypeName[cellType]]];
RETURN};
obRect ← CD.InterestRect[ob].r;
objects.count ← objects.count + 1;
object ←
NEW[SCPrivate.ObjectRec ← [name: objectName, objectNum: objects.count,
size: RTBasic.XYToPQ[horizontal, CDBasics.SizeOfRect[obRect]],
orgin: RTBasic.XYToPQ[horizontal, CDBasics.BaseOfRect[obRect]],
numPins: 0, pins: NIL, typeClass: useClass, numTimesUsed: 0,
cdOb: ob, cellType: cellType]];
objects.ob[objects.count] ← object};
DefinePinsFromDecoration:
PROCEDURE [handle:
SC.Handle, object: SCPrivate.Object, cellType: Core.CellType ←
NIL, decoration: CoreGeometry.Decoration]
RETURNS [objectPins: SCPrivate.ObjectPins] = {
get physical description and define the type
enter a new object into standard cell data structure
CountPins: CoreGeometry.EachWirePinProc = {
IF UsePin[min, max, side, layer] THEN object.numPins ← object.numPins + 1};
UsePin:
PROC [min, max:
INT, side: CoreGeometry.Side, layer:
CD.Layer]
RETURNS [useIt:
BOOLEAN ←
FALSE] ~ {
IF (side = top OR side = bottom) AND layer = handle.rules.rowRules.branchLayer THEN useIt ← TRUE};
PinEnum: CoreGeometry.EachWirePinProc = {
IF UsePin[min, max, side, layer]
THEN
{rect: SC.Rect ← DefineRect[obRect, min, max, handle.rules.rowRules.branchWidth, side];
name: Rope.ROPE ← CoreOps.GetShortWireName[wire];
scSide: SC.Side ← SELECT side FROM right => right, left => left, top => top, bottom => bottom, ENDCASE => ERROR;
inst: CD.Instance ← CDSymbolicObjects.CreateSymInst[name: name, denotes: rect, layer: layer, approachFrom: SCUtil.DirectionFromSide[side]];
objectPins.p[numPins] ← NEW[SCPrivate.ObjectPinRec ← [name: name, pinPos: [scSide, 0, (max+min)/2], cdPin: inst, publicWire: wire, rect: rect, layer: layer, equivClass: name]];
numPins ← numPins + 1}};
numPins: NAT ← 0;
obRect: CD.Rect ← CD.InterestRect[object.cdOb].r;
define the pins on the object
[] ← CoreGeometry.EnumerateNonOverlappingSides[decoration, cellType, CountPins];
objectPins ← NEW[SCPrivate.ObjectPinsRec[object.numPins]];
IF object.numPins > 0
THEN
[] ← CoreGeometry.EnumerateNonOverlappingSides[decoration, cellType, PinEnum]};
DefineFtType:
PROCEDURE [handle:
SC.Handle, name: Rope.
ROPE, decoration: CoreGeometry.Decoration]
RETURNS [object: SCPrivate.Object] = {
mode: Sinix.Mode = SinixOps.GetExtractMode[handle.rules.technology];
object ← DefineObject[handle, name, ft, NIL];
object.cellType ← NARROW [Sinix.Extract[object.cdOb, mode].result];
IF object =
NIL
THEN {
SC.Signal[callingError, Rope.Cat["FeedThru object is not defined: ", name, "\n"]];
RETURN};
object.pins ← DefinePinsFromDecoration[handle, object, object.cellType, decoration]};
object.pins ← DefinePinsFromBoundry[handle, object, ft]};
DefineIOType:
PROCEDURE [handle:
SC.Handle, decoration: CoreGeometry.Decoration]
RETURNS [object: SCPrivate.Object ←
NIL] = {
mode: Sinix.Mode = SinixOps.GetExtractMode[handle.rules.technology];
object ← DefineObject[handle, NIL, io, NIL];
object.cellType ← NARROW [Sinix.Extract[object.cdOb, mode].result];
IF object =
NIL
THEN {
SC.Signal[callingError, "IO object is not defined \n"];
RETURN};
object.pins ← DefinePinsFromDecoration[handle, object, object.cellType, decoration]};
object.pins ← DefinePinsFromBoundry[handle, object, io];
DefinePowerType:
PROCEDURE [handle:
SC.Handle, name: Rope.
ROPE, decoration: CoreGeometry.Decoration]
RETURNS [object: SCPrivate.Object ←
NIL] = {
mode: Sinix.Mode = SinixOps.GetExtractMode[handle.rules.technology];
object ← DefineObject[handle, name, other, NIL];
object.cellType ← NARROW [Sinix.Extract[object.cdOb, mode].result];
IF object =
NIL
THEN {
SC.Signal[callingError, Rope.Cat["Power object is not defined: ", name, "\n"]];
RETURN[NIL]};
object.pins ← DefinePinsFromDecoration[handle, object, object.cellType, decoration];
RETURN[object]};
object.pins ← DefinePinsFromBoundry[handle, object, logic]};
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};
BuildIOObject:
PROCEDURE [handle:
SC.Handle]
RETURNS [object:
CD.Object ← CDCells.CreateEmptyCell[]] = {
minSize: SC.Number ← handle.rules.rowRules.branchWidth;
symInst: Route.Instance ← 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]};
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]^;
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]};
END.