file ///StdCell/SCInstUtilImpl.mesa
compoments utility routines
-- InstWidth - find width of component at current orientation
-- InstHeight - find height of component at current orientation
-- BpHeight - find height of bp when considering side it is on
-- BpWidth - find width of bp when considering side it is on
-- MinMaxBPOffset - find min and max offsets of bonding pads on side
-- BpOffsets - find offsets of bonding pads on side
-- BpPos - find position of inst on side
-- PosOf- find the position (side, x, and y) of a component on a pin
-- PowerPosOf- find the position (x, and y) of a power pin
-- RotateRect- Rotate a rectangle of a cell
-- LgOffsets- determine offsets of components in row
-- AllOffsets - determine all component offsets
-- AsgnChanPos - assign current positions to horizontal and vertical channels
-- CheckInsts - check row and position of comps
-- CheckInst - check row and position of a inst
-- EnumeratePinsOnInst - enumerate the net pins on an instance
DIRECTORY
CoreClasses,
Rope,
SC,
SCInstUtil,
SCPrivate,
SCRowUtil,
SCUtil,
RTSets;
SCInstUtilImpl: CEDAR PROGRAM
IMPORTS SC, SCInstUtil, SCRowUtil, SCUtil, Rope, RTSets
EXPORTS SCInstUtil
SHARES SC =
BEGIN
defltLgOrien: PUBLIC SCPrivate.Orientation ← 1;
defltBpOrien: PUBLIC ARRAY SC.Side OF SCPrivate.Orientation ← [3, 1, 4, 2];
find width of component at current orientation
InstWidth: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[width: SC.Number] =
BEGIN
find current orientation
orien: SCPrivate.OrientationOrNone ← inst.curOrien;
now get width based on orientation
SELECT orien FROM
0, 1, 3, 5, 6 => width ← inst.object.size.p;
2, 4, 7, 8 => width ← inst.object.size.q;
ENDCASE;
END;
find height of component at current orientation
InstHeight: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[height: SC.Number] =
BEGIN
find current orientation
orien: SCPrivate.OrientationOrNone ← inst.curOrien;
now get height based on orientation
SELECT orien FROM
0, 1, 3, 5, 6 => height ← inst.object.size.q;
2, 4, 7, 8 => height ← inst.object.size.p;
ENDCASE;
END;
find height of bp when considering its side
(this is, the dimension perpendicular to side)
BpHeight: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[height: SC.Number] = {
IF inst.whichClass # io THEN
SC.Error[programmingError, Rope.Cat["Instance: ", inst.name, " should be an IO"]];
SELECT inst.curSide FROM
top, bottom => height ← InstHeight[inst];
left, right => height ← InstWidth[inst];
ENDCASE => SC.Error[programmingError, NIL]};
find height of bp when considering side it is on
this is along to side
BpWidth: PUBLIC PROCEDURE[inst: SCPrivate.Instance] RETURNS[width: SC.Number] = {
IF inst.whichClass # io THEN
SC.Error[programmingError, Rope.Cat["Instance: ", inst.name, " should be an IO"]];
SELECT inst.curSide FROM
top, bottom => width ← InstWidth[inst];
left, right => width ← InstHeight[inst];
ENDCASE => SC.Error[programmingError, NIL]};
find offsets of bonding pads on side
MinMaxBPOffset: PUBLIC PROCEDURE[handle: SC.Handle, side: SC.Side] RETURNS [minOffset, maxOffset: SC.Number] = {
InstProc: SCRowUtil.EachInstProc = {
minOffset ← MIN[minOffset, instance.offset];
maxOffset ← MAX[maxOffset, instance.offset]};
minOffset ← LAST[INT];
maxOffset ← -minOffset;
[] ← SCRowUtil.EnumerateAllInstsOnSide[handle, side, InstProc]};
find offsets of bonding pads on side
BpOffsets: PUBLIC PROCEDURE[handle: SC.Handle, side: SC.Side, pos1, pos2: SCPrivate.ZMaxPosSr] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
bpRow: SCPrivate.BpRow ← layoutData.bpRows[side];
offset: SC.Number;
posA: SCPrivate.ZMaxPosSr ← MIN[pos1, pos2];
posB: SCPrivate.ZMaxPosSr ← MAX[pos1, pos2];
IF posA <= 1 THEN {posA ← 1; offset ← 0}
ELSE
{inst: SCPrivate.Instance ← bpRow.bpsOnSide[posA-1];
offset ← inst.offset + InstWidth[inst] + bpRow.bpSpacing};
IF posB = 0 OR posB > bpRow.nBpsOnSide THEN posB ← bpRow.nBpsOnSide;
FOR posIndex: SCPrivate.ZMaxPosSr IN [posA .. posB] DO
inst: SCPrivate.Instance ← bpRow.bpsOnSide[posIndex];
width: SC.Number ← BpWidth[inst];
IF side = bottom OR side = right THEN
inst.offset ← offset
ELSE
inst.offset ← offset + width;
offset ← offset + width + bpRow.bpSpacing;
ENDLOOP};
find position of inst on side
assumes that channel and bp positions have been assigned.
BpPos: PUBLIC PROCEDURE[handle: SC.Handle, inst: SCPrivate.Instance] RETURNS[result: SC.Number] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
bpRow: SCPrivate.BpRow ← layoutData.bpRows[inst.curSide];
IF inst.whichClass # io THEN
SC.Error[programmingError, " "];
SELECT inst.curSide FROM
right => result ← bpRow.sideOrg.q + inst.offset;
bottom => result ← bpRow.sideOrg.p + inst.offset;
left => result ← bpRow.sideOrg.q - inst.offset;
top => result ← bpRow.sideOrg.p - inst.offset;
ENDCASE};
find the position (side, x, and y) of a component on a pin
PosOf: PUBLIC PROCEDURE[inst: SCPrivate.Instance, pin: SCPrivate.ObjectPin]
RETURNS [pinDes: SCInstUtil.PinDescription] = {
x, y: SC.Number;
first find the position at normal orientation
SELECT pin.pinPos.side FROM
bottom => {x ← pin.pinPos.location; y ← pin.pinPos.depth};
right => {x ← InstWidth[inst] - pin.pinPos.depth; y ← pin.pinPos.location};
top => {x ← InstWidth[inst] - pin.pinPos.location; y ← InstHeight[inst] - pin.pinPos.depth};
left => {x ← pin.pinPos.depth; y ← InstHeight[inst] - pin.pinPos.location};
ENDCASE;
now rotate the pin position to current orien
SELECT inst.curOrien FROM
0, 1 => {pinDes.xPos ← x; pinDes.yPos ← y};
2 => {pinDes.xPos ← y; pinDes.yPos ← InstWidth[inst] - x};
3 => {pinDes.xPos ← InstWidth[inst] - x; pinDes.yPos ← InstHeight[inst] - y};
4 => {pinDes.xPos ← InstHeight[inst] - y; pinDes.yPos ← x};
5 => {pinDes.xPos ← InstWidth[inst] - x; pinDes.yPos ← y};
6 => {pinDes.xPos ← x; pinDes.yPos ← InstHeight[inst] - y};
7 => {pinDes.xPos ← y; pinDes.yPos ← x};
8 => {pinDes.xPos ← InstHeight[inst] - y; pinDes.yPos ← InstWidth[inst] - x};
ENDCASE;
pinDes.sideOn ← SCUtil.SideTranslate[pin.pinPos.side, inst.curOrien]};
find the position (x, and y) of a power pin
PowerPosOf: PUBLIC PROCEDURE[handle: SC.Handle, row: SCPrivate.ZMaxRowSr, net: SCPrivate.Net, lRSide: SCPrivate.LRSide]
RETURNS [xPos, yPos: SC.Number ← 0, found: BOOLEANFALSE] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRow: SCPrivate.LgRow ← layoutData.lgRows.rows[row];
maxPos: SCPrivate.ZMaxPosSr ← lgRow.nLgsOnRow;
pd: SCInstUtil.PinDescription ← [0, 0, bottom];
inst: SCPrivate.Instance;
IF maxPos > 0 THEN {
pin: SCPrivate.ObjectPin;
SELECT lRSide FROM
left => inst ← lgRow.lgsOnRow[1];
right => inst ← lgRow.lgsOnRow[maxPos];
ENDCASE;
pin ← SCUtil.FindPin[inst.object, net.name];
IF pin # NIL THEN
{pd ← PosOf[inst, pin]; found ← TRUE}
ELSE -- this is a hack until cells have power pins
{IF Rope.Equal[net.name, layoutData.powerBuses[lRSide].name] THEN
{SELECT lRSide FROM
left => {pd.xPos ← 0;
pd.yPos ← InstHeight[inst] - handle.rules.sideRules.trunkWidth/2;
found ← TRUE};
right => {pd.xPos ← InstWidth[inst];
pd.yPos ← handle.rules.sideRules.trunkWidth/2;
found ← TRUE};
ENDCASE}}};
xPos ← lgRow.rowOrg.p + inst.offset + pd.xPos;
yPos ← lgRow.rowOrg.q + pd.yPos};
find the position of a rotated rectangle wintin a component
RotateRect: PUBLIC PROCEDURE[inst: SCPrivate.Instance, defRect: SC.Rect]
RETURNS [newRect: SC.Rect] = {
now rotate the pin position to current orien
SELECT inst.curOrien FROM
1 =>
{newRect.x1 ← defRect.x1; newRect.y1 ← defRect.y1;
newRect.x2 ← defRect.x2; newRect.y2 ← defRect.y2};
2 =>
{newRect.x1 ← defRect.y1; newRect.y1 ← InstWidth[inst] - defRect.x1;
newRect.x2 ← defRect.y2; newRect.y2 ← InstWidth[inst] - defRect.x2};
3 =>
{newRect.x1 ← InstWidth[inst] - defRect.x1; newRect.y1 ← InstHeight[inst] - defRect.y1;
newRect.x2 ← InstWidth[inst] - defRect.x2; newRect.y2 ← InstHeight[inst] - defRect.y2};
4 =>
{newRect.x1 ← InstHeight[inst] - defRect.y1; newRect.y1 ← defRect.x1;
newRect.x2 ← InstHeight[inst] - defRect.y2; newRect.y2 ← defRect.x2};
5 =>
{newRect.x1 ← InstWidth[inst] - defRect.x1; newRect.y1 ← defRect.y1;
newRect.x2 ← InstWidth[inst] - defRect.x2; newRect.y2 ← defRect.y2};
6 =>
{newRect.x1 ← defRect.x1; newRect.y1 ← InstHeight[inst] - defRect.y1;
newRect.x2 ← defRect.x2; newRect.y2 ← InstHeight[inst] - defRect.y2};
7 =>
{newRect.x1 ← defRect.y1; newRect.y1 ← defRect.x1;
newRect.x2 ← defRect.y2; newRect.y2 ← defRect.x2};
8 =>
{newRect.x1 ← InstHeight[inst] - defRect.y1; newRect.y1 ← InstWidth[inst] - defRect.x1;
newRect.x2 ← InstHeight[inst] - defRect.y2; newRect.y2 ← InstWidth[inst] - defRect.x2};
ENDCASE};
determine offsets of components in row
LgOffsets: PUBLIC PROCEDURE[handle: SC.Handle, row: SCPrivate.ZMaxRowSr, pos1, pos2: SCPrivate.ZMaxPosSr] = {
compute offsets of all comps on row
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
lgRow: SCPrivate.LgRow ← lgRows.rows[row];
offset: SC.Number;
posA: SCPrivate.ZMaxPosSr ← MIN[pos1, pos2];
posB: SCPrivate.ZMaxPosSr ← MAX[pos1, pos2];
IF posA <= 1 THEN {posA ← 1; offset ← 0}
ELSE
{inst: SCPrivate.Instance ← lgRow.lgsOnRow[posA-1];
offset ← inst.offset + InstWidth[inst]};
IF posB = 0 OR posB > lgRow.nLgsOnRow THEN posB ← lgRow.nLgsOnRow;
FOR posIndex: SCPrivate.MaxPosSr IN [posA .. posB] DO
inst: SCPrivate.Instance ← lgRow.lgsOnRow[posIndex];
SELECT inst.whichClass FROM
ft, logic => {inst.offset ← offset; offset ← offset + InstWidth[inst]};
ENDCASE;
ENDLOOP;
update max row widths
IF posB = lgRow.nLgsOnRow THEN
{lgRow.size.p ← offset;
IF lgRow.size.p >= lgRows.maxRowWidth THEN
{lgRows.maxRowWidth ← lgRow.size.p; lgRows.numMaxRows ← 1}
ELSE [lgRows.maxRowWidth, lgRows.numMaxRows] ← SCRowUtil.FindMaxRow[handle]}};
determine all component offsets
AllOffsets: PUBLIC PROCEDURE [handle: SC.Handle] = {
RowRroc: SCRowUtil.EachRowProc = {
LgOffsets[handle, row, 0, 0]};
SideProc: SCRowUtil.EachSideProc = {
BpOffsets[handle, side, 0, 0]};
[] ← SCRowUtil.EnumerateRows[handle, RowRroc];
[] ← SCRowUtil.EnumerateSides[handle, SideProc]};
assign current positions to horizontal and vertical channels
AsgnChanPos: PUBLIC PROCEDURE[handle: SC.Handle] =
BEGIN
compute the minimum channel dimensions
EachSide: SCRowUtil.EachSideProc = {
sideDim[side] ← bpRows[side].size.p + (bpRows[side].nBpsOnSide -1) * bpRows[side].bpSpacing};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
bpRows: SCPrivate.BpRows ← layoutData.bpRows;
sideChans: SCPrivate.SideChans ← layoutData.sideChans;
rowChans: SCPrivate.RowChans ← layoutData.rowChans;
nRows: SCPrivate.MaxRowSr ← lgRows.count;
nChans: SCPrivate.MaxChanSr ← rowChans.count;
sideDim: ARRAY SC.Side OF SC.Number;
upperActiveLimit, rightActiveLimit, realTotHeight: SC.Number;
[] ← SCRowUtil.EnumerateSides[handle, EachSide];
FOR row: SCPrivate.MaxRowSr IN [1 .. nRows] DO
IF lgRows.rows[row].dimInvalid THEN SCRowUtil.ComputeRowHeight[handle, row];
ENDLOOP;
row 1 and channel 1 data
IF bpRows[left].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, left];
IF bpRows[bottom].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, bottom];
rowChans.chans[1].chanPos ← bpRows[bottom].size.q;
sideChans[left].sideChanPos ← bpRows[left].size.q;
lgRows.horzRowOrg ← bpRows[left].size.q + sideChans[left].sideChanResult;
lgRows.rows[1].rowOrg.p ← lgRows.horzRowOrg + (lgRows.maxRowWidth - lgRows.rows[1].size.p)/2;
lgRows.rows[1].rowOrg.q ← rowChans.chans[1].chanPos + rowChans.chans[1].chanResult;
now the interior channels
FOR chan: SCPrivate.MaxChanSr IN [2 .. nChans] DO
rowChans.chans[chan].chanPos ← lgRows.rows[chan-1].rowOrg.q + lgRows.rows[chan-1].size.q;
IF chan <= nRows THEN {
lgRows.rows[chan].rowOrg.q ← rowChans.chans[chan].chanPos + MAX[rowChans.chans[chan].chanWidth, rowChans.chans[chan].minChanWidth];
lgRows.rows[chan].rowOrg.p ← lgRows.horzRowOrg + (lgRows.maxRowWidth - lgRows.rows[chan].size.p)/2};
ENDLOOP;
now the right side
sideChans[right].sideChanPos ← lgRows.horzRowOrg + lgRows.maxRowWidth;
get total height and width
upperActiveLimit ← rowChans.chans[nChans].chanPos + MAX[rowChans.chans[nChans].chanWidth, rowChans.chans[nChans].minChanWidth];
layoutData.totHeight ← realTotHeight ← upperActiveLimit + bpRows[top].size.q;
rightActiveLimit ← sideChans[right].sideChanPos +
MAX[sideChans[right].sideChanWidth, sideChans[right].minSideChanWidth];
layoutData.totWidth ← rightActiveLimit + bpRows[right].size.q;
now update the side orgs
bpRows[bottom].sideOrg.q ← 0;
bpRows[bottom].sideOrg.p ← lgRows.horzRowOrg + (lgRows.maxRowWidth - sideDim[bottom]) / 2;
update right side data
IF bpRows[top].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, top];
IF bpRows[right].dimInvalid THEN SCRowUtil.ComputeSideHeight[handle, right];
bpRows[right].sideOrg.p ← rightActiveLimit;
bpRows[right].sideOrg.q ← (realTotHeight - sideDim[right])/ 2;
update top side data
bpRows[top].sideOrg.p ← lgRows.horzRowOrg + (lgRows.maxRowWidth + sideDim[top])/ 2;
bpRows[top].sideOrg.q ← upperActiveLimit;
update left side data
bpRows[left].sideOrg.p ← 0;
bpRows[left].sideOrg.q ← (realTotHeight +sideDim[left])/ 2;
END;
find chans that these comps touch
ChansForInsts: PUBLIC PROCEDURE[handle: SC.Handle, insts: SCPrivate.InstanceList]
RETURNS [touchesChan: SCPrivate.ChanSet ← RTSets.RTMdSetEmpty] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
FOR instList: SCPrivate.InstanceList ← insts, instList.rest WHILE instList # NIL DO
inst: SCPrivate.Instance ← instList.first;
SELECT inst.whichClass FROM
ft, logic => {IF inst.curRow > 0 THEN
{touchesChan ← RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(inst.curRow+1)-1]];
touchesChan ← RTSets.RTMdSetUnion[touchesChan , RTSets.RTMdSetGenerateElement[(inst.curRow)-1]]}};
io => {IF inst.curSide = bottom THEN
touchesChan ← RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(1)-1]];
IF inst.curSide = top THEN
touchesChan ← RTSets.RTMdSetUnion[touchesChan, RTSets.RTMdSetGenerateElement[(layoutData.rowChans.count)-1]]};
ENDCASE;
ENDLOOP};
check row and position of a inst
CheckInst: PUBLIC PROCEDURE[handle: SC.Handle, inst: SCPrivate.Instance] = {
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
SELECT inst.whichClass FROM
logic, ft =>
{row: SC.Number ← inst.curRow;
pos: SC.Number ← inst.curPos;
lgRow: SCPrivate.LgRow ← layoutData.lgRows.rows[row];
IF row <= 0 OR row > layoutData.rowChans.count THEN
{IF ~(row = 0 AND pos = 0 AND inst.whichClass = ft) THEN
SC.Error[programmingError, " "]}
ELSE IF pos <= 0 OR pos > lgRow.nLgsOnRow THEN
SC.Error[programmingError, " "]
ELSE
{trialInst: SCPrivate.Instance ← lgRow.lgsOnRow[pos];
IF inst # trialInst THEN
SC.Error[programmingError, " "]}};
io =>
{side: SC.Side ← inst.curSide;
pos: SC.Number ← inst.curPos;
bpRow: SCPrivate.BpRow ← layoutData.bpRows[side];
IF side = none THEN
SC.Error[programmingError, " "]
ELSE IF pos <= 0 OR pos > bpRow.nBpsOnSide THEN
SC.Error[programmingError, " "]
ELSE
{trialInst: SCPrivate.Instance ← bpRow.bpsOnSide[pos];
IF inst # trialInst THEN
SC.Error[programmingError, " "]}};
ENDCASE};
check row and position of a inst
CheckInsts: PUBLIC PROCEDURE[handle: SC.Handle] = {
EachInst: SCInstUtil.EachInstanceProc = {
CheckInst[handle, instance]};
[] ← SCInstUtil.EnumerateInstances[handle, EachInst]};
EnumerateInstances: PUBLIC PROC [handle: SC.Handle, eachInstance: SCInstUtil.EachInstanceProc] RETURNS [quit: BOOL] = {
structureData: SCPrivate.StructureData ← NARROW[handle.structureData];
FOR inst: SCPrivate.MaxInstanceSr IN [1 .. structureData.instances.count] DO
[] ← eachInstance[structureData.instances.inst[inst]];
ENDLOOP};
EnumeratePinsOnInst: PUBLIC PROC [instance: SCPrivate.Instance, eachPin: SCInstUtil.EachPinProc] RETURNS [quit: BOOLFALSE] = {
FOR pin: NAT IN [0 .. instance.pinNets.size) WHILE ~quit DO
quit ← eachPin[instance, pin, instance.pinNets.n[pin]];
ENDLOOP};
DefineInstance: PUBLIC PROCEDURE [handle: SC.Handle, instanceName: Rope.ROPE, object: SCPrivate.Object, coreInstance: CoreClasses.CellInstance, equivName: Rope.ROPENIL]
RETURNS [instance: SCPrivate.Instance ← NIL] = {
define a component (an instance of object)
structureData: SCPrivate.StructureData ← NARROW[handle.structureData];
instances: SCPrivate.Instances ← structureData.instances;
object.numTimesUsed ← object.numTimesUsed + 1;
construct he instance record
SELECT object.typeClass FROM
logic =>
{instance ← NEW[logic SCPrivate.InstanceRec];
instance.whichClass ← logic;
instances.numLogics ← instances.numLogics + 1};
ft =>
{instance ← NEW[ft SCPrivate.InstanceRec];
instance.whichClass ← ft;
instances.numFts ← instances.numFts + 1};
io =>
{instance ← NEW[io SCPrivate.InstanceRec];
instance.equivPortClass ← equivName;
instance.whichClass ← io;
instances.numIOs ← instances.numIOs + 1};
ENDCASE => SC.Error[callingError, Rope.Cat["Feedthrus not allowed in input: ", instance.name, ", object: ", object.name, "\n"]];
instance.name ← instanceName;
instance.object ← object;
initialize the nets connected to these pins
instance.pinNets ← NEW[SCPrivate.PinNetsRec[object.numPins]];
instances.count ← instances.count + 1;
instance.instanceNum ← instances.count;
instances.inst[instances.count] ← instance};
NumInstsOnList: PUBLIC PROCEDURE [instances: SCPrivate.InstanceList] RETURNS [count: SCPrivate.ZMaxInstanceSr ← 0] = {
FOR instList: SCPrivate.InstanceList ← instances, instList.rest WHILE instList # NIL DO
count ← count + 1;
ENDLOOP};
END.