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, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, DABasics, IO, PWCore, RefTab, Rope, Route, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCObjUtil, SCNetUtil, SCPrivate, SCUtil, Sinix, SinixOps, TerminalIO;
SCGetStructureImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDSymbolicObjects, CoreDirectory, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PWCore, RefTab, 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, root: Core.CellType,
flattenCellType: RTCoreUtil.FlattenCellTypeProc, decoration: CoreGeometry.Decoration]
RETURNS [done: BOOLEAN ← TRUE] = {
InternalWireProc: RTCoreUtil.FlatWireProc = {
PROC [flatWire: CoreFlat.FlatWireRec] RETURNS [quit: BOOL ← FALSE];
pathName: Rope.ROPE ← CoreRoute.LabelFlatWire[root, flatWire];
net: SCPrivate.Net ← SCUtil.FindNet[handle, pathName];
IF net # NIL THEN SC.Signal[callingError, Rope.Cat["Duplicate net name: ", pathName]]
ELSE net ← SCNetUtil.DefineNet[handle, pathName]};
ExternalWireProc: RTCoreUtil.FlatWireProc = {
PROC [flatWire: CoreFlat.FlatWireRec] RETURNS [quit: BOOL ← FALSE];
pathName: Rope.ROPE ← CoreRoute.LabelFlatWire[root, flatWire];
instance: SCPrivate.Instance ← SCUtil.FindInstance[handle, pathName];
net: SCPrivate.Net ← SCUtil.FindNet[handle, pathName];
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
THEN {
net.externNet ← externalNet;
net.publicWire ← flatWire.wire;
IF ~SCUtil.IsPowerName[handle, pathName]
THEN {
make a pin for each side that the pin is restricted to
FOR side: DABasics.Side
IN [bottom .. right]
DO
IF WireOnSide[side, flatWire.wire]
THEN {
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;
no side restriction, leave the pin free to move
IF instance =
NIL
THEN {
instance ← SCInstUtil.DefineInstance[handle, pathName, parms.portObject, pathName];
SCNetUtil.AddConnection[handle, net, instance, parms.portObject.pins.p[0], 0, externalPin]}}}};
InstanceProc: RTCoreUtil.FlatInstanceProc = {
PROC [flatCellType: CoreFlat.FlatCellTypeRec, cell: Core.CellType, bindings: CoreFlat.Bindings, properties: Core.Properties] RETURNS [quit: BOOL ← FALSE];
EachPublic:
PROC [publicWire: Core.Wire] = {
pinName: Rope.ROPE ← CoreOps.GetShortWireName[publicWire];
IF ~SCUtil.IsPowerName[handle, pinName]
THEN
do binding of public to actual; this is clumsy because of chane to Core Geometry
{
flatWire: CoreFlat.FlatWire ← NARROW [RefTab.Fetch[bindings, publicWire].val];
wireName: Rope.ROPE ← CoreRoute.LabelFlatWire[root, flatWire^];
net: SCPrivate.Net ← SCUtil.FindNet[handle, wireName];
thisPin: SCPrivate.ObjectPin ← SCUtil.FindPin[object, pinName]; -- get the pin
IF net =
NIL
THEN
{SC.Signal[callingError, Rope.Cat[Rope.Cat["Net not defined: ", wireName, " 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;
pathName: Rope.ROPE ← CoreFlat.InstancePathRope[root, flatCellType.path];
object: SCPrivate.Object ← SCUtil.FindObjectByCell[handle, cell];
IF object =
NIL
THEN {
object ← DefineObject[handle, CoreOps.GetCellTypeName[cell], logic, cell];
object.pins ← DefinePinsFromDecoration[handle, object, cell, decoration]};
instance ← SCInstUtil.DefineInstance[handle, pathName, object, NIL];
CoreOps.VisitRootAtomics[cell.public, EachPublic];
GetLogicProperties[instance, properties]};
hasVddConnection, hasGndConnection: BOOLEAN ← FALSE;
usePositions:
BOOL ← RTCoreUtil.GetCoreBoolProp[root,
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[root, flattenCellType, ExternalWireProc, InternalWireProc, InstanceProc, SC.interestingProperties];
-- connect to power cells
IF hasVddConnection THEN DoPower[handle, "Vdd", parms.vddObject, "Vdd"];
IF hasGndConnection THEN DoPower[handle, "Gnd", parms.gndObject, "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, wireName: Rope.
ROPE] ~ {
instance: SCPrivate.Instance ← SCInstUtil.DefineInstance[handle, instanceName, object, NIL];
construct and add an entry to net list for this instance
net: SCPrivate.Net ← SCUtil.FindNet[handle, 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];
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 [instance: SCPrivate.Instance, properties: Core.Properties] = {
assign row and position to instance
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[properties, ProcProps]};
WireOnSide:
PROC [side: DABasics.Side, wire: Core.Wire]
RETURNS [onSide:
BOOL ←
FALSE] ~ {
RETURNS TRUE if wire is restricted to side
ProcProps:
PROC [prop:
ATOM, val:
REF
ANY] ~ {
SELECT
TRUE
FROM
prop = SC.bottomSideProp => IF side = bottom THEN onSide ← TRUE;
prop = SC.rightSideProp => IF side = right THEN onSide ← TRUE;
prop = SC.topSideProp => IF side = top THEN onSide ← TRUE;
prop = 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] ~ {
find position for wire on side
ProcProps:
PROC [prop:
ATOM, val:
REF
ANY] ~ {
SELECT
TRUE
FROM
prop = SC.bottomPositionProp => IF side = bottom THEN position ← NARROW[val, REF INT]^;
prop = SC.rightPositionProp => IF side = right THEN position ← NARROW[val, REF INT]^;
prop = SC.topPositionProp => IF side = top THEN position ← NARROW[val, REF INT]^;
prop = 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] ~ {
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.