SCGetStructureImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDSymbolicObjects, CoreOps, CoreProperties, PW, PWPins, Rope, RTBasic, SC, SCCoreUtil, SCInstUtil, SCObjUtil, SCNetUtil, SCUtil, TerminalIO
EXPORTS SCPrivate
SHARES SC =
BEGIN
debug: BOOLEAN ← FALSE;
GetStructure:
PUBLIC
PROCEDURE [handle:
SC.Handle, cellType: Core.CellType]
RETURNS [done: BOOLEAN] = {
InternalWireProc: SCCoreUtil.EachWireProc = {
net: SCPrivate.Net ← SCUtil.FindNet[handle, NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]];
IF net # NIL THEN SC.Signal[callingError, Rope.Cat["Duplicate net name: ", NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]]]
ELSE
net ← SCNetUtil.DefineNet[handle, wire]};
ExternalWireProc: SCCoreUtil.EachWireProc = {
instance: SCPrivate.Instance ← SCUtil.FindInstance[handle, NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]];
net: SCPrivate.Net ← SCUtil.FindNet[handle, NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]];
IF net = NIL THEN SC.Signal[callingError, Rope.Cat["Missing net name: ", NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]]];
IF instance # NIL THEN SC.Signal[callingError, Rope.Cat["Duplicate port name: ", NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]], ", object: ", parms.portObject.name]];
IF instance =
NIL
AND net #
NIL
THEN
{instance ← SCInstUtil.DefineInstance[handle, NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]], parms.portObject, NIL, NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]];
SCNetUtil.AddConnection[handle, net, instance, parms.portObject.pins.p[0], 0];
net.externNet ← externalNet;
GetIOProperties[handle, instance, net, wire]}};
InstanceProc: SCCoreUtil.EachInstanceProc = {
object: SCPrivate.Object ← SCUtil.FindObject[handle, NARROW[CoreProperties.GetCellTypeProp[cellInstance.type, CoreOps.nameProp]]];
IF object =
NIL
THEN
object ← DefineObject[handle, NARROW[CoreProperties.GetCellTypeProp[cellInstance.type, CoreOps.nameProp]], logic, cellInstance.type];
IF object =
NIL
THEN
SC.Signal[callingError, Rope.Cat["Object is not defined: ", NARROW[CoreProperties.GetCellTypeProp[cellInstance.type, CoreOps.nameProp]], "\n"]]
ELSE
{
GetCellName:
PROC [cellInstance: CoreClasses.CellInstance]
RETURNS [name: Rope.
ROPE ← ""] = {
this is a lot to go through to get an instance name
name ← NARROW[CoreProperties.GetCellInstanceProp[cellInstance, CoreOps.nameProp]]};
EachInstancePin: SCCoreUtil.EachInstancePinProc = {
IF ~SCUtil.IsPowerName[handle,
NARROW[CoreProperties.GetWireProp[publicWire, CoreOps.nameProp]]]
THEN
{net: SCPrivate.Net ← SCUtil.FindNet[handle, NARROW[CoreProperties.GetWireProp[actualWire, CoreOps.nameProp]]];
unconnected: REF ANY ← CoreProperties.GetProp[actualWire.properties, SC.unconnectedProp];
this is a HACK!! Core does not permit unconnected pins
IF unconnected =
NIL
THEN {
pin: SCPrivate.ObjectPin ← SCUtil.FindPin[object, NARROW[CoreProperties.GetWireProp[publicWire, CoreOps.nameProp]]]; -- get the pin
IF net =
NIL
THEN
{SC.Signal[callingError, Rope.Cat[Rope.Cat["Net not defined: ", NARROW[CoreProperties.GetWireProp[actualWire, CoreOps.nameProp]], " 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
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];
ENDLOOP}}}};
instance: SCPrivate.Instance ← SCInstUtil.DefineInstance[handle, GetCellName[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 {
[] ← SCCoreUtil.EnumFlatInstancePins[cellInstance, EachInstancePin];
GetLogicProperties[handle, instance, cellInstance]}}};
set up the private data
recCell: CoreClasses.RecordCellType ← NARROW[cellType.data];
parms: SCPrivate.Parms ← NARROW[handle.parms];
portName:Rope.ROPE ← "IOPort"; -- need to get from Core
ftName:Rope.ROPE ← "Feedthru"; -- need to get from Core
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;
parms.portObject ← DefineIOType[handle, portName];
parms.ftObject ← DefineAuxType[handle, ftName, ft];
get auxalliary components
TerminalIO.WriteRope["Getting structure description . . .\n"];
done ← ~SCCoreUtil.EnumerateFlatWires[recCell.internal, InternalWireProc];
done ← done AND ~SCCoreUtil.EnumerateFlatWires[cellType.public, ExternalWireProc];
done ← done AND ~SCCoreUtil.EnumerateInstances[cellType, InstanceProc];
fix up the bus widths based on connectivity
DoBuses[handle, left];
DoBuses[handle, right];
IF debug THEN SCUtil.WriteStructure[handle]};
DoBuses:
PROCEDURE [handle:
SC.Handle, lRSide: RTBasic.LRSide] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
powerBuses: SCPrivate.PowerBuses ← layoutData.powerBuses;
acBuses: SCPrivate.AcBuses ← layoutData.acBuses;
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;
FOR clockIndex:
NAT
IN [0 .. acBuses[lRSide].count)
DO
IF acBuses[lRSide].sigs.c[clockIndex].onSide = lRSide
THEN
{numClocks ← numClocks + 1;
acBuses[lRSide].sigs.c[clockIndex].depth ← pWidth + (numClocks-1)*rules.trunkToTrunk + rules.trunkWidth/2};
ENDLOOP;
acBuses[lRSide].width ← numClocks* rules.trunkToTrunk};
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 = {
name: Rope.ROPE ← CDSymbolicObjects.GetName[inst];
IF ~SCUtil.IsPowerName[handle, name] AND CDSymbolicObjects.IsSymbolicOb[inst.ob] THEN
object.numPins ← object.numPins + 1};
structureData: SCPrivate.StructureData ← NARROW[handle.structureData];
objects: SCPrivate.Objects ← structureData.objects;
parms: SCPrivate.Parms ← NARROW[handle.parms];
ob: CD.Object ← PW.Get[parms.libDesign, objectName];
numPins: NAT ← 0;
obRect: CD.Rect;
size, orgin: RTBasic.PQPos;
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, class, 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 ~SCUtil.IsPowerName[handle, name]
AND CDSymbolicObjects.IsSymbolicOb[inst.ob]
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: SCCoreUtil.EachWireProc = {
IF ~SCUtil.IsPowerName[handle,
NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]]
THEN
{
IF SCUtil.FindPin[object,
NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]]] =
NIL
THEN
SC.Signal[callingError, Rope.Cat["Physical pins and logical pins on object: ", object.name, " do not correspond"]]}};
[] ← SCCoreUtil.EnumerateFlatWires[cellType.public, WireEnum]}};
DefineAuxType:
PROCEDURE [handle:
SC.Handle, name: Rope.
ROPE, class: SCPrivate.CompClass]
RETURNS [object: SCPrivate.Object ←
NIL] = {
object ← SCUtil.FindObject[handle, name];
IF object #
NIL
THEN {
SC.Signal[callingError, Rope.Cat["Duplicate auxillary object: ", name, "\n"]];
RETURN};
object ← DefineObject[handle, name, class];
IF object =
NIL
THEN
SC.Signal[callingError, Rope.Cat["Auxillary object is not defined: ", name, "\n"]]};
DefineIOType:
PROCEDURE [handle:
SC.Handle, name: Rope.
ROPE]
RETURNS [object: SCPrivate.Object ←
NIL] = {
object ← SCUtil.FindObject[handle, name];
IF object #
NIL
THEN {
SC.Signal[callingError, Rope.Cat["Duplicate IO object: ", name, "\n"]];
RETURN};
object ← DefineObject[handle, name, io];
IF object =
NIL
THEN
SC.Signal[callingError, Rope.Cat["IO 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]};
GetLogicProperties:
PROCEDURE [handle:
SC.Handle, instance: SCPrivate.Instance, cellInstance: CoreClasses.CellInstance] = {
ProcProps:
PROC [prop:
ATOM, val:
REF
ANY] ~ {
SELECT
TRUE
FROM
prop = $Row => instance.fnlRow ← NARROW[val, REF INT]^;
prop = $PosOnRow => instance.fnlPos ← NARROW[val, REF INT]^;
ENDCASE;
};
CoreProperties.Enumerate[cellInstance.properties, ProcProps]};
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 = $Side => instance.fnlSide ← NARROW[val, REF SC.SideOrNone]^;
prop = $PosOnSide => instance.fnlPos ← NARROW[val, REF INT]^;
prop = $LeftPower => {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
layoutData.powerBuses[left].name ← NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]];
layoutData.powerBuses[left].net ← net};
prop = $RightPower => {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
layoutData.powerBuses[right].name ← NARROW[CoreProperties.GetWireProp[wire, CoreOps.nameProp]];
layoutData.powerBuses[right].net ← net};
prop = $LeftClock => {};
prop = $RightClock => {};
ENDCASE;
};
CoreProperties.Enumerate[wire.properties, ProcProps]};
get signals to route without feedthrus
ProcClock:
PROCEDURE [descName:
ATOM, lRSide: SCPrivate.LRSide]
RETURNS [acSide: SCPrivate.AcBusSides] =
BEGIN
clockSignalNames: LIST OF Rope.ROPE ← NIL; -- GetRopeListProp[descName];
acSide ← NEW[SCPrivate.AcBusSidesRec];
FOR nameList:
LIST
OF Rope.
ROPE ← clockSignalNames, nameList.rest
WHILE nameList #
NIL
DO
acSide.count ← acSide.count + 1
ENDLOOP;
IF acSide.count > 0
THEN {
index: NAT ← 0;
acSide.sigs ← NEW[SCPrivate.AcBusSigsRec[acSide.count]];
FOR nameList:
LIST
OF Rope.
ROPE ← clockSignalNames, nameList.rest
WHILE nameList #
NIL
DO
acSide.sigs[index].name ← nameList.first;
acSide.sigs[index].onSide ← lRSide;
index ← index + 1;
ENDLOOP};
END;
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.instanceNum] ← NIL};
EachNet: SCNetUtil.EachNetProc ~ {
EachPin: SCNetUtil.EachPinProc ~ {
netPin.pin ← NIL;
netPin.instance ← NIL};
[] ← SCNetUtil.EnumeratePinsOnNet[net, EachPin];
net.pins ← NIL;
net.acBus ← NIL;
net.netDat ← NIL;
nets.nets[net.netNum] ← 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.