SCPrePlaceImpl.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
last edited by Bryan Preas, July 10, 1987 9:11:56 pm PDT
DIRECTORY
Convert, IO, Rope, Real, SC, SCChanUtil, SCInitialPlace, SCInstUtil, SCPlaceUtil, SCPrivate, SCRowUtil, TerminalIO;
SCPrePlaceImpl: CEDAR PROGRAM
IMPORTS Convert, IO, Real, Rope, SC, SCChanUtil, SCInstUtil, SCPlaceUtil, SCRowUtil, TerminalIO
EXPORTS SCInitialPlace
SHARES SC = {
debug: BOOLEANFALSE;
ChooseNonZero: PROCEDURE [num1, num2, num3: SC.Number ← 0]
RETURNS[ result: SC.Number] = {
Choose non zero num in priority order
IF num1 # 0 THEN result ← num1
ELSE IF num2 # 0 THEN result ← num2
ELSE result ← num3};
IntBounds: PROCEDURE[checkNum, lowLimit, upLimit, default: SC.Number, name: Rope.ROPE]
RETURNS[ result: SC.Number] = {
IF lowLimit <= checkNum AND checkNum <= upLimit THEN
result ← checkNum
ELSE {
result ← default;
TerminalIO.PutRope[Rope.Cat[Rope.Cat[" instance: ", name, " variable: ", Convert.RopeFromInt[checkNum], " limits: "], Rope.Cat[Convert.RopeFromInt[lowLimit], " .. ", Convert.RopeFromInt[upLimit], "\n"]]]}};
SideBounds: PROCEDURE[checkNum, lowLimit, upLimit, default: SC.SideOrNone, name: Rope.ROPE]
RETURNS[ result: SC.SideOrNone] = {
IF lowLimit <= checkNum AND checkNum <= upLimit THEN
result ← checkNum
ELSE {
result ← default;
TerminalIO.PutRope[Rope.Cat[Rope.Cat[" instance: ", name, " variable: ", SCRowUtil.sideName[checkNum], " limits: "], Rope.Cat[SCRowUtil.sideName[lowLimit], " .. ", SCRowUtil.sideName[upLimit], "\n"]]]}};
InitBpSide: PROCEDURE [handle: SC.Handle] = {
make the bonding pad rows empty
SideProc: SCRowUtil.EachSideProc = {
PROC [side: SC.Side, bpRow: SCPrivate.BpRow] RETURNS [quit: BOOL ← FALSE];
bpRow.maxBpsOnSide ← bpRow.initMaxBpsOnSide;
bpRow.size.p ← 0;
bpRow.size.q ← 0;
bpRow.dimInvalid ← FALSE;
bpRow.nBpsOnSide ← 0;
bpRow.fnlBpFxd ← FALSE;
bpRow.initBpFxd ← FALSE};
[] ← SCRowUtil.EnumerateSides[handle, SideProc]};
InitLgRow: PROCEDURE [handle: SC.Handle] = {
make the interior rows empty
RowProc: SCRowUtil.EachRowProc = {
PROC [row: SCPrivate.MaxRowSr, lgRow: SCPrivate.LgRow] RETURNS [quit: BOOL ← FALSE];
lgRow.size.p ← 0;
lgRow.size.q ← 0;
lgRow.dimInvalid ← FALSE;
lgRow.nLgsOnRow ← 0;
lgRow.nFtsOnRow ← 0;
lgRow.fnlLgFxd ← FALSE;
lgRow.initLgFxd ← FALSE};
[] ← SCRowUtil.EnumerateRows[handle, RowProc]};
PrePlaceComps: PROCEDURE [handle: SC.Handle, initialized: BOOLEAN] = {
pre place the components
PrePlacLg: PROCEDURE[handle: SC.Handle, instance: SCPrivate.Instance, initialized: BOOLEAN] = {
preplace the logic component instance
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
iRow, fRow: SCPrivate.ZMaxRowSr;
IF initialized THEN {
instance.curRow ← instance.initRow;
instance.curPos ← instance.initPos;
instance.curOrien ← instance.initOrien};
check if this instance has a currently defined position
fRow ← IntBounds[instance.fnlRow, 0, SCPrivate.maxLgRows, 0, instance.name];
iRow ← IntBounds[instance.initRow, 0, SCPrivate.maxLgRows, 0, instance.name];
IF instance.preRow > 0 THEN {
instance.preRow ← IntBounds[instance.preRow, 1, SCPrivate.maxLgRows, 0, instance.name];
instance.prePos ← IntBounds[instance.prePos, FIRST[INT], LAST[INT], 0, instance.name];
instance.preOrien ← IntBounds[instance.preOrien, 1, SCPrivate.maxOrien, SCInstUtil.defltLgOrien, instance.name];
IF instance.preRow = 0 OR instance.prePos = 0 OR instance.preOrien = 0 THEN {
instance.preRow ← 0;
instance.prePos ← 0;
instance.preOrien ← 0}}
check if the final position is specified
ELSE IF fRow > 0 THEN {
instance.preRow ← fRow;
instance.prePos ← IntBounds[ChooseNonZero[instance.fnlPos, instance.initPos], FIRST[INT], LAST[INT], 0, instance.name];
instance.preOrien ← IntBounds[ChooseNonZero[instance.fnlOrien, instance.initOrien, SCInstUtil.defltLgOrien], 1, SCPrivate.maxOrien, SCInstUtil.defltLgOrien, instance.name]}
check for initial position specified
ELSE IF iRow > 0 THEN {
instance.preRow ← iRow;
instance.prePos ← IntBounds[ChooseNonZero[instance.fnlPos, instance.initPos], FIRST[INT], LAST[INT], 0, instance.name];
instance.preOrien ← IntBounds[ChooseNonZero[instance.fnlOrien, instance.initOrien, SCInstUtil.defltLgOrien], 1, SCPrivate.maxOrien, SCInstUtil.defltLgOrien, instance.name]};
IF instance.preRow > 0 THEN SCPlaceUtil.PutLgRow[handle, instance, instance.preRow, instance.preOrien]
ELSE {instance.curRow ← 0; instance.curPos ← 0; instance.curOrien ← 0};
check if this instance restricts a row by specifying a position on a row
IF instance.preRow > 0 AND instance.prePos > 0 THEN {
IF fRow > 0 AND instance.fnlPos > 0 THEN lgRows.rows[fRow].fnlLgFxd ← TRUE;
IF iRow > 0 AND instance.initPos > 0 THEN lgRows.rows[iRow].initLgFxd ← TRUE}};
PrePlacBp: PROCEDURE[handle: SC.Handle, instance: SCPrivate.Instance, initialized:BOOLEAN] = {
preplace the bonding pad component instance
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
bpRows: SCPrivate.BpRows ← layoutData.bpRows;
iSide, fSide: SC.SideOrNone;
IF initialized THEN {
instance.curSide ← instance.initSide;
instance.curPos ← instance.initPos;
instance.curOrien ← instance.initOrien};
check if this instance has a currently defined position
iSide ← SideBounds[instance.initSide, bottom, none, none, instance.name];
fSide ← SideBounds[instance.fnlSide, bottom, none, none, instance.name];
IF instance.preSide # none THEN {
instance.preSide ← SideBounds[instance.preSide, bottom, right, none, instance.name];
instance.prePos ← IntBounds[instance.prePos, FIRST[INT], LAST[INT], 0, instance.name];
instance.preOrien ← IntBounds[instance.preOrien, 1, SCPrivate.maxOrien, SCInstUtil.defltBpOrien[instance.preSide], instance.name];
IF instance.preSide = none OR instance.prePos = 0 OR instance.preOrien = 0 THEN {
instance.preSide ← none;
instance.prePos ← 0;
instance.preOrien ← 0}}
check if the final position is specified
ELSE IF fSide # none THEN {
instance.preSide ← fSide;
instance.prePos ← IntBounds[ChooseNonZero[instance.fnlPos, instance.initPos], FIRST[INT], LAST[INT], 0, instance.name];
instance.preOrien ← IntBounds[ChooseNonZero[instance.fnlOrien, instance.initOrien, SCInstUtil.defltBpOrien[instance.preSide]], 1, SCPrivate.maxOrien, SCInstUtil.defltBpOrien[instance.preSide], instance.name]}
check for initial position specified
ELSE IF iSide # none THEN {
instance.preSide ← iSide;
instance.prePos ← IntBounds[ChooseNonZero[instance.fnlPos, instance.initPos], FIRST[INT], LAST[INT], 0, instance.name];
instance.preOrien ← IntBounds[ChooseNonZero[instance.fnlOrien, instance.initOrien, SCInstUtil.defltBpOrien[iSide]], 1, SCPrivate.maxOrien, SCInstUtil.defltBpOrien[iSide], instance.name]};
IF instance.preSide # none THEN SCPlaceUtil.PutBpSide[handle, instance, instance.preSide]
ELSE {instance.curSide ← none; instance.curPos ← 0; instance.curOrien ← 0};
check to see if this bp restricts this side by having a position assigned
IF instance.preSide # none AND instance.prePos > 0 THEN {
IF fSide # none AND instance.fnlPos > 0 THEN bpRows[fSide].fnlBpFxd ← TRUE;
IF iSide # none AND instance.initPos >0 THEN bpRows[iSide].initBpFxd ← TRUE}};
EachInstance: SCInstUtil.EachInstanceProc = {
SELECT instance.whichClass FROM
logic, ft => PrePlacLg[handle, instance, initialized];
io => PrePlacBp[handle, instance, initialized];
ENDCASE};
[] ← SCInstUtil.EnumerateAllInstances[handle, EachInstance]};
DetermineRows: PROCEDURE [handle: SC.Handle, numRows: NAT, routingFactor: REAL] RETURNS[width, height: SC.Number]= {
determine the number of rows to use
EachInstance: SCInstUtil.EachInstanceProc = {
PROC [instance: SCPrivate.Instance] RETURNS [quit: BOOL ← FALSE];
IF instance.whichClass = logic THEN {
maxRowSpec ← MAX[instance.initRow, MAX[maxRowSpec, instance.fnlRow]];
must use direct data access, no placement exists yet
totLinComps ← totLinComps + SCInstUtil.InstWidth[instance];
avgHeight ← avgHeight + SCInstUtil.InstHeight[instance]}};
layoutData: SCPrivate.LayoutData ← NARROW[handle.layoutData];
lgRows: SCPrivate.LgRows ← layoutData.lgRows;
structureData: SCPrivate.StructureData ← NARROW[handle.structureData];
instances: SCPrivate.Instances ← structureData.instances;
routFact: REAL = 3.0;
detRow: NAT;
maxRowSpec, avgHeight, totLinComps: SC.Number ← 0;
area: REAL;
[] ← SCInstUtil.EnumerateAllInstances[handle, EachInstance];
avgHeight ← avgHeight /MAX[1, instances.numLogics];
area ← totLinComps * avgHeight* routingFactor;
IF avgHeight <= 0 THEN detRow ← 0
ELSE {
Cedar problem: mixing NAT's and INT's
temp: NAT ← Real.Round[Real.SqRt[area] / (avgHeight * routingFactor)];
detRow ← MAX[1, temp]};
IF numRows > 0 THEN
lgRows.count ← MIN[SC.Number[SCPrivate.maxLgRows], MAX[maxRowSpec, numRows]]
ELSE IF maxRowSpec > 0 THEN
lgRows.count ← MIN[SC.Number[SCPrivate.maxLgRows], MAX[maxRowSpec, detRow]]
ELSE
lgRows.count ← MIN[SCPrivate.maxLgRows, detRow];
lgRows.count ← MAX[1, lgRows.count];
layoutData.rowChans.count ← lgRows.count +1;
height ← Real.Round[avgHeight*(lgRows.count + layoutData.rowChans.count*routingFactor)];
width ← Real.Round[area / height];
TerminalIO.PutRope[" number of rows calculation:\n"];
TerminalIO.PutF1[" maximum row specified: %g\n", IO.int[maxRowSpec]];
TerminalIO.PutF1[" computed number of rows: %g\n", IO.int[detRow]];
TerminalIO.PutF1[" number of rows specified: %g\n", IO.int[numRows]];
TerminalIO.PutF1[" number of rows used: %g\n", IO.int[lgRows.count]]};
DetermineSides: PROCEDURE [handle: SC.Handle, width, height: SC.Number] = {
determine the number of Bps on sides to use
SideSlots: SCRowUtil.EachSideProc = {
-- PROC [side: SC.Side, bpRow: SCPrivate.BpRow] RETURNS [quit: BOOL ← FALSE];
bpRow.maxBpsOnSide ← MAX[bpRow.initMaxBpsOnSide, bpRow.nBpsOnSide];
IF bpRow.maxBpsOnSide > 0 THEN {
totBpSlots ← totBpSlots + bpRow.maxBpsOnSide;
nSidesAvail ← nSidesAvail -1}};
SetSlots: SCRowUtil.EachSideProc = {
-- PROC [side: SC.Side, bpRow: SCPrivate.BpRow] RETURNS [quit: BOOL ← FALSE];
2X is a HACK
IF bpRow.maxBpsOnSide <= 0 THEN bpRow.maxBpsOnSide ← nBps*2;
bpRow.bpSpacing ← IF side = top OR side = bottom THEN width/bpRow.maxBpsOnSide
ELSE height/bpRow.maxBpsOnSide};
structureData: SCPrivate.StructureData ← NARROW[handle.structureData];
instances: SCPrivate.Instances ← structureData.instances;
nSidesAvail: NAT[0..4] ← 4;
totBpSlots: NAT ← 0; 
nBps: NAT;
compute number of slots to put on currently empty sides
[] ← SCRowUtil.EnumerateSides[handle, SideSlots];
IF nSidesAvail > 0 THEN
nBps ← MAX[0, (instances.numIOs - totBpSlots +3) /nSidesAvail]
ELSE {
nBps ← 0;
IF instances.numIOs > totBpSlots THEN SC.Error[callingError, "Too many IO's"]};
[] ← SCRowUtil.EnumerateSides[handle, SetSlots]};
PrePlace: PUBLIC PROCEDURE[handle: SC.Handle, numRows: NAT ← 0, routingFactor: REAL ← 2.5, initialized: BOOLEANTRUE] = {
width, height: SC.Number;
TerminalIO.PutRope["Pre placement\n"];
InitBpSide[handle];
InitLgRow[handle];
SCChanUtil.ClearRouteDat[handle];
PrePlaceComps[handle, initialized];
[width, height] ← DetermineRows[handle, numRows, routingFactor];
DetermineSides[handle, width, height];
TerminalIO.PutRope["End pre placement\n"];
IF debug THEN SCPlaceUtil.WriteCurPlace[handle]};
}.