SCGetStructureImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Last Edited by: Preas, September 9, 1985 10:06:38 am PDT
Jean-Marc Frailong October 14, 1987 5:58:31 pm 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, SCNetUtil, SCPrivate, SCUtil, Sinix, TerminalIO;
SCGetStructureImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDCells, CDSymbolicObjects, CoreDirectory, CoreFlat, CoreGeometry, CoreOps, CoreProperties, CoreRoute, IO, PWCore, RefTab, Rope, RouteUtil, RTBasic, RTCoreUtil, SC, SCInstUtil, SCNetUtil, SCUtil, Sinix, TerminalIO
EXPORTS SCPrivate
SHARES SC = BEGIN
debug: BOOLEANFALSE;
Object creation
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;
};
CreateObject: PROC [handle: SC.Handle, class: SCPrivate.CompClass, ob: CD.Object, cellType: Core.CellType] RETURNS [object: SCPrivate.Object] ~ {
Build an SCPrivate object from the components.
Either ob=PWCore.Layout[cellType], or cellType=Sinix.Extract[ob, handle.parms.mode]
The handle is used to compute the pins. Only pins along top and bottom that are in the branchLayer are saved: they are the ones to which nets connect...
PinEnum: CoreGeometry.EachWirePinProc = {
IF (side=top OR side=bottom) AND layer=branchLayer THEN {
This pin fits the requirements
rect: SC.Rect = DefineRect[obRect, min, max, branchWidth, side];
name: Rope.ROPE = CoreOps.GetShortWireName[wire];
IF side=none THEN ERROR;
pinList ← CONS [NEW[SCPrivate.ObjectPinRec ← [name: name, pinPos: [side, 0, (max+min)/2], publicWire: wire, rect: rect, layer: layer, equivClass: name]], pinList];
numPins ← numPins + 1;
};
};
branchLayer: CD.Layer = handle.rules.rowRules.branchLayer; -- shortcut
branchWidth: INT = handle.rules.rowRules.branchWidth; -- shortcut
name: Rope.ROPE = CoreOps.GetCellTypeName[cellType]; -- will be object name
obRect: CD.Rect;
pinList: LIST OF SCPrivate.ObjectPin ← NIL; -- used to build the object pins
numPins: NAT ← 0; -- always the size of pinList
pins: SCPrivate.ObjectPins; -- stored in the object
decoration: CoreGeometry.Decoration = NARROW[handle.parms, SCPrivate.Parms].mode.decoration;
IF ob=NIL THEN ERROR SC.Error[callingError, Rope.Cat["No CD object for CellType ", name]];
obRect ← CD.InterestRect[ob];
[] ← CoreGeometry.EnumerateNonOverlappingSides[decoration, cellType, PinEnum];
pins ← NEW[SCPrivate.ObjectPinsRec[numPins]]; -- just the right size
FOR i: NAT IN [0..numPins) DO -- put the pins in the object structure
pins[i] ← pinList.first; pinList ← pinList.rest;
ENDLOOP;
object ← NEW[SCPrivate.ObjectRec ← [name: name,
size: RTBasic.XYToPQ[horizontal, CDBasics.SizeOfRect[obRect]],
orgin: RTBasic.XYToPQ[horizontal, CDBasics.BaseOfRect[obRect]],
numPins: numPins, pins: pins, typeClass: class, numTimesUsed: 0,
cdOb: ob, cellType: cellType]];
};
DefineFtType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object] = {
Define a feedthrough-type object
parms: SCPrivate.Parms = NARROW[handle.parms];
cellType: Core.CellType = CoreDirectory.Fetch[parms.libName, name]; -- get from library
IF cellType=NIL THEN ERROR SC.Error[callingError, Rope.Cat["FeedThru object not found in library: ", name]]; -- quite deadly...
object ← CreateObject[handle, ft, PWCore.Layout[cellType], cellType];
};
DefinePowerType: PROCEDURE [handle: SC.Handle, name: Rope.ROPE] RETURNS [object: SCPrivate.Object] = {
Define an object used to connect nets to power supplies
parms: SCPrivate.Parms = NARROW[handle.parms];
cellType: Core.CellType = CoreDirectory.Fetch[parms.libName, name]; -- get from library
IF cellType=NIL THEN ERROR SC.Error[callingError, Rope.Cat["Power object not found in library: ", name]]; -- quite deadly...
object ← CreateObject[handle, logic, PWCore.Layout[cellType], cellType]; -- make power connection cells logic cells
};
DefineIOType: PROCEDURE [handle: SC.Handle] RETURNS [object: SCPrivate.Object] = {
Define an IO-type object. This is the only case where the CD object is not derived as the layout for the CellType. The CD object is built explicitly, and the cellType is obtained by explicit extraction (sigh...)
mode: Sinix.Mode = NARROW[handle.parms, SCPrivate.Parms].mode;
ob: CD.Object ← BuildIOObject[handle];
cellType: Core.CellType = NARROW [Sinix.Extract[ob, mode, NIL, NIL].result];
[] ← CoreOps.SetCellTypeName[cellType, "--IO Object--"]; -- documentation only...
object ← CreateObject[handle, io, ob, cellType];
};
BuildIOObject: PROCEDURE [handle: SC.Handle] RETURNS [object: CD.Object] = {
Build the special CD IO object (real messy...)
minSize: SC.Number = handle.rules.rowRules.branchWidth;
symInst: CD.Instance;
object ← CDCells.CreateEmptyCell[];
symInst ← 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];
};
Structure management
GetStructure: PUBLIC PROCEDURE [handle: SC.Handle, flattenCellType: RTCoreUtil.FlattenCellTypeProc] RETURNS [done: BOOLTRUE] ~ {
InternalWireProc: RTCoreUtil.FlatWireProc ~ {
PROC [flatWire: CoreFlat.FlatWireRec] RETURNS [quit: BOOLFALSE];
[] ← SCNetUtil.DefineNet[handle, NEW [CoreFlat.FlatWireRec ← flatWire]];
};
ExternalWireProc: RTCoreUtil.FlatWireProc ~ {
PROC [flatWire: CoreFlat.FlatWireRec] RETURNS [quit: BOOLFALSE];
pathName: Rope.ROPE = CoreRoute.LabelFlatWire[root, flatWire]; -- for port instance names
instance: SCPrivate.Instance ← SCUtil.FindInstance[handle, pathName];
net: SCPrivate.Net = SCNetUtil.FindPublicNet[handle, flatWire.wire];
IF instance # NIL THEN { -- this is an error, signal and return, net already tested
SC.Signal[callingError, Rope.Cat["Duplicate port name: ", CoreRoute.LabelFlatWire[root, flatWire], ", object: ", parms.portObject.name]];
RETURN;
};
net.externNet ← TRUE;
net.publicWire ← flatWire.wire;
IF SCUtil.IsPowerName[handle, CoreOps.GetShortWireName[flatWire.wire]] THEN RETURN; -- nothing more to do
FOR side: DABasics.Side IN [bottom .. right] DO
Make a pin for each side the pin is restricted to
IF NOT WireOnSide[side, flatWire.wire] THEN LOOP; -- not interesting
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;
IF instance = NIL THEN { -- no side restriction, leave the pin free to move
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: BOOLFALSE];
EachPublic: PROC [publicWire: Core.Wire] = {
pinName: Rope.ROPE = CoreOps.GetShortWireName[publicWire];
flatWire: CoreFlat.FlatWire;
net: SCPrivate.Net;
thisPin: SCPrivate.ObjectPin;
IF SCUtil.IsPowerName[handle, pinName] THEN RETURN; -- nothing to do
do binding of public to actual; this is clumsy because of change to Core Geometry
flatWire ← NARROW [RefTab.Fetch[bindings, publicWire].val];
net ← SCNetUtil.FindNet[handle, flatWire]; -- get the net
thisPin ← SCUtil.FindPin[object, pinName]; -- get the pin
IF thisPin=NIL THEN { -- Error case: signal & return, net already handled
SC.Signal[callingError, Rope.Cat["Pin not found: ", pinName, Rope.Cat[" on component: ", instance.name, ", type: ", object.name]]];
RETURN;
};
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 -- add all pins for wire to net
objPin: SCPrivate.ObjectPin = object.pins.p[pinIndex];
IF objPin#NIL AND 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 ← NARROW [RefTab.Fetch[objectTable, cell].val];
IF object = NIL THEN { -- create the new object
object ← CreateObject[handle, logic, PWCore.Layout[cell], cell];
[] ← RefTab.Insert[objectTable, cell, object];
};
instance ← SCInstUtil.DefineInstance[handle, pathName, object, NIL];
SCInstUtil.DefineSourceInstance[handle, NEW [CoreFlat.FlatCellTypeRec ← flatCellType], instance];
CoreOps.VisitRootAtomics[cell.public, EachPublic];
GetLogicProperties[instance, properties];
};
root: Core.CellType = handle.coreCellType;
hasVddConnection, hasGndConnection: BOOLEANFALSE;
usePositions: BOOL ← RTCoreUtil.GetCoreBoolProp[root, SC.usePublicPositionsProp, FALSE];
objectTable: RefTab.Ref ← RefTab.Create[]; -- temporary table cell -> Object
Set up the private data
parms: SCPrivate.Parms ← NARROW[handle.parms];
structureData: SCPrivate.StructureData ← NEW [SCPrivate.StructureDataRec ← [
instances: NEW [SCPrivate.InstancesRec ← [inst: NEW [SCPrivate.InstsOb]]],
nets: RefTab.Create[equal: CoreFlat.FlatWireEqual, hash: CoreFlat.FlatWireHash],
sourceInstances: RefTab.Create[equal: CoreFlat.FlatCellTypeEqual, hash: CoreFlat.FlatCellTypeHash]
]];
handle.structureData ← structureData;
Get auxilliary components
parms.portObject ← DefineIOType[handle];
parms.ftObject ← DefineFtType[handle, "feedthru"];
parms.vddObject ← DefinePowerType[handle, "vdd"];
parms.gndObject ← DefinePowerType[handle, "gnd"];
Do the real work
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];
We are now finished...
TerminalIO.PutF["Statistics: \n instances: %g, wires: %g, public wires: %g cells: %g\n", IO.int[structureData.instances.numLogics], IO.int[RefTab.GetSize[structureData.nets]], IO.int[structureData.instances.numIOs], IO.int[RefTab.GetSize[objectTable]]];
IF debug THEN SCUtil.WriteStructure[handle];
};
DoPower: PROC [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, wireName: Rope.ROPE] ~ {
Make a new power connection
instance: SCPrivate.Instance ← SCInstUtil.DefineInstance[handle, instanceName, object, NIL];
net: SCPrivate.Net ← SCNetUtil.FindPublicNet[handle, CoreOps.FindWire[handle.coreCellType.public, 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] = {
Define a power bus in the handle layoutData
layoutData: SCPrivate.LayoutData = NARROW[handle.layoutData];
wireName: Rope.ROPE = layoutData.powerBuses[lRSide].name;
net: SCPrivate.Net ← SCNetUtil.FindPublicNet[handle, CoreOps.FindWire[handle.coreCellType.public, wireName]];
layoutData.powerBuses[lRSide].net ← net;
};
GetLogicProperties: PROCEDURE [instance: SCPrivate.Instance, properties: Core.Properties] = {
Propagate row & position requirement from source Core properties to the Instance
EachProperty: PROC [prop: ATOM, val: REF ANY] ~ {
SELECT prop FROM
SC.rowProp => instance.fnlRow ← NARROW[val, REF INT]^;
SC.positionProp => instance.fnlPos ← NARROW[val, REF INT]^;
ENDCASE;
};
CoreProperties.Enumerate[properties, EachProperty];
};
WireOnSide: PROC [side: DABasics.Side, wire: Core.Wire] RETURNS [onSide: BOOLFALSE] ~ {
RETURNS TRUE if wire is restricted to side
ProcProps: PROC [prop: ATOM, val: REF ANY] ~ {
SELECT prop FROM
SC.bottomSideProp => IF side = bottom THEN onSide ← TRUE;
SC.rightSideProp => IF side = right THEN onSide ← TRUE;
SC.topSideProp => IF side = top THEN onSide ← TRUE;
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 prop FROM
SC.bottomPositionProp => IF side = bottom THEN position ← NARROW[val, REF INT]^;
SC.rightPositionProp => IF side = right THEN position ← NARROW[val, REF INT]^;
SC.topPositionProp => IF side = top THEN position ← NARROW[val, REF INT]^;
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] ~ {
Destroy the SC structureData field in order to remove all circularities for GC
EachInst: SCInstUtil.EachInstanceProc ~ {
IF instance.pinNets#NIL THEN FOR i: NAT IN [0..instance.pinNets.size) DO -- destroy pinNets
instance.pinNets[i]^ ← []; instance.pinNets[i] ← NIL;
ENDLOOP;
instance.pinNets ← NIL; instance.ftNet ← NIL; instances.inst[instance.num] ← NIL;
instance.object.pins ← NIL; instance.object.cdOb ← NIL; instance.object.cellType ← NIL;
};
EachNet: RefTab.EachPairAction ~ { -- destroy the net thoroughly
net: SCPrivate.Net ← NARROW [val];
netPin: SCPrivate.NetPin ← net.pins;
WHILE netPin#NIL DO -- destroy the list of pins thoroughly
next: SCPrivate.NetPin = netPin.link;
netPin^ ← [];
netPin ← next;
ENDLOOP;
The following fields are assumed to be destroyed before: netDat, pinsOnChan, segsInChan, pinList, edgeList. Check that it is so...
net^ ← [];
};
structureData: SCPrivate.StructureData = NARROW[handle.structureData];
instances: SCPrivate.Instances = structureData.instances;
[] ← SCInstUtil.EnumerateAllInstances[handle, EachInst];
RefTab.Erase[structureData.sourceInstances];
[] ← RefTab.Pairs[structureData.nets, EachNet];
RefTab.Erase[structureData.nets];
structureData^ ← [];
handle.structureData ← NIL;
};
END.