SCGetStructureImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Last Edited by: Preas, September 9, 1985 10:06:38 am PDT
Last Edited by: Louis Monier December 15, 1986 10:51:22 pm PST
Frank Bowers February 3, 1986 5:41:01 pm PST
Preas, September 8, 1986 5:20:55 pm PDT
get design data by reading Core connectivity and ChipnDale cells
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: BOOLEANFALSE;
GetStructure: PUBLIC PROCEDURE [handle: SC.Handle, cellType: Core.CellType,
flattenCellType: RTCoreUtil.FlattenCellTypeProc]
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]}};
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 {
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 ← 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;
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];
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"];
fix up the bus widths based on connectivity
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];
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;
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] = {
get physical description and define the type
enter a new object into standard cell data structure
CountPins: PWPins.InstanceEnumerator = {
IF UsePin[inst] THEN object.numPins ← object.numPins + 1};
UsePin: PROC [pin: CD.Instance] RETURNS [useIt: BOOLEANFALSE] ~ {
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};
};
IF class = io THEN {
ob ← BuildIOObject[handle];
useClass ← io}
ELSE IF class = ft OR class = other THEN {
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 -- }
ELSE 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[]];
ob ← PW.Get[parms.libDesign, objectName];
useClass ← logic};
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;
define the pins on the 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.LayerCDSymbolicObjects.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]};
check physical pins against the logical pins
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] = {
analyze cell for relevant parameters
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.