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: BOOLEAN ← FALSE;
GetStructure:
PUBLIC
PROCEDURE [handle:
SC.Handle, cellType: Core.CellType,
flattenCellType: RTCoreUtil.FlattenCellTypeProc]
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]}};
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:
BOOLEAN ←
FALSE] ~ {
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.Layer ← CDSymbolicObjects.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.