SCGetStructureImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Last Edited by: Preas, September 9, 1985 10:06:38 am PDT
Frank Bowers February 3, 1986 5:41:01 pm PST
Preas, July 21, 1987 5:19:57 pm PDT
get design data by reading Core connectivity and ChipnDale cells
DIRECTORY
CD, CDBasics, CDCells, CDSymbolicObjects, Core, CoreClasses, CoreDirectory, CoreGeometry, CoreOps, CoreProperties, IO, PWCore, Rope, Route, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCObjUtil, SCNetUtil, SCPrivate, SCUtil, Sinix, SinixOps, TerminalIO;
SCGetStructureImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDSymbolicObjects, 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, usePositions]}};
InstanceProc: RTCoreUtil.FlatInstanceProc = {
-- PROC [cellInstance: CoreClasses.CellInstance, pathName: Rope.ROPE] RETURNS [quit: BOOL ← FALSE];
EachInstancePin: RTCoreUtil.EachInstancePinProc = {
IF ~SCUtil.IsPowerName[handle, CoreOps.GetShortWireName[publicWire]]
THEN
do binding of public to actual; this is clumsy because of chane 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, pathName, object, cellInstance, NIL];
[] ← RTCoreUtil.EnumFlatInstancePins[cellInstance, EachInstancePin];
GetLogicProperties[handle, instance, cellInstance]};
hasVddConnection, hasGndConnection: BOOLEAN ← FALSE;
usePositions: BOOL ← RTCoreUtil.GetCoreBoolProp[cellType, SC.usePublicPositionsProp, 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] ~ {
instance: 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, 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];
powerBuses: SCPrivate.PowerBuses ← layoutData.powerBuses;
net: SCPrivate.Net ← SCUtil.FindNet[handle, powerBuses[lRSide].name];
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;
objectPins.p[numPins] ← NEW[SCPrivate.ObjectPinRec ← [name: name, pinPos: [scSide, 0, (max+min)/2], 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.rowParms.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.rowParms.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.rowParms.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: CD.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, usePositions:
BOOL] = {
ProcProps:
PROC [prop:
ATOM, val:
REF
ANY] ~ {
SELECT
TRUE
FROM
prop = SC.sideProp => instance.fnlSide ← GetSide[NARROW[val, ATOM]];
prop = SC.positionProp => instance.fnlPos ← IF usePositions THEN NARROW[val, REF INT]^ ELSE 0;
ENDCASE};
CoreProperties.Enumerate[wire.properties, ProcProps]};
DestroyStructure:
PUBLIC
PROC [handle:
SC.Handle] ~ {
EachObj: SCObjUtil.EachObjectProc ~ {
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.