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, FS, IO, PWCore, RedBlackTree, 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, FS, IO, RedBlackTree, PWCore, Rope, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCObjUtil, SCNetUtil, SCUtil, Sinix, SinixOps, TerminalIO
EXPORTS SCPrivate
SHARES SC =
BEGIN
debug: BOOLEANFALSE;
GetStructure: PUBLIC PROCEDURE [handle: SC.Handle, cellType: Core.CellType,
flattenCellType: RTCoreUtil.FlattenCellTypeProc, decoration: CoreGeometry.Decoration]
RETURNS [done: BOOLEANTRUE] = {
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];
SCUtil.AddPad[padTable, instance, pathName]}}; -- for TimberWolf .cel file
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
first: BOOLEANTRUE;
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];
SCUtil.AddPin[celStream, instance, objPin, net, first]; -- for TimberWolf .cel file
first ← FALSE};
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];
SCUtil.AddCell[celStream, instance, pathName]; -- for TimberWolf .cel file
[] ← RTCoreUtil.EnumFlatInstancePins[cellInstance, EachInstancePin];
GetLogicProperties[handle, instance, cellInstance]};
celStream: FS.STREAMFS.StreamOpen[Rope.Cat[handle.name, ".cel"], $create];
padTable: RedBlackTree.Table ← RedBlackTree.Create[SCUtil.GetKey, SCUtil.Compare];
hasVddConnection, hasGndConnection: BOOLEANFALSE;
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", celStream];
IF hasGndConnection THEN DoPower[handle, "Gnd", parms.gndObject, cellType.public, "Gnd", celStream];
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]];
SCUtil.CopyPadToCel[celStream, padTable];
IO.Flush[celStream]; IO.Close[celStream];
IF debug THEN SCUtil.WriteStructure[handle]};
DoPower: PROC [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, rootWire: Core.Wire, wireName: Rope.ROPE, celStream: FS.STREAM] ~ {
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];
SCUtil.AddCell[celStream, instance, wireName]; -- for TimberWolf .cel file
SCNetUtil.AddConnection[handle, net, instance, object.pins.p[0], 0, compPin];
SCNetUtil.AddConnection[handle, net, instance, object.pins.p[1], 1, compPin];
SCUtil.AddPin[celStream, instance, object.pins.p[0], net, TRUE]; -- for TimberWolf .cel file
SCUtil.AddPin[celStream, instance, object.pins.p[1], net, FALSE]}; -- for TimberWolf .cel file
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: BOOLEANFALSE] ~ {
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.