<> <> <> 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: BOOLEAN _ FALSE; ChooseNonZero: PROCEDURE [num1, num2, num3: SC.Number _ 0] RETURNS[ result: SC.Number] = { << >> <> 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] = { << >> <> SideProc: SCRowUtil.EachSideProc = { <> 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] = { << >> <> RowProc: SCRowUtil.EachRowProc = { <> 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] = { <
>

        PrePlacLg: PROCEDURE[handle: SC.Handle, instance: SCPrivate.Instance, initialized: BOOLEAN] = {
            <>

            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};
             
            <>
            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}}
            <<>>
            <>
            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]}
            <<>>
            <>
            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};
            <<>>
            <>
            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] = {
            <>

            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};
                <<>>
            <>
            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}}
            <<>>
            <>
            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]}
                <<>>
            <>
            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};
            <<>>
            <>
            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]= {
        <>

        EachInstance: SCInstUtil.EachInstanceProc = {
            <>
            IF instance.whichClass = logic THEN {
                maxRowSpec _ MAX[instance.initRow, MAX[maxRowSpec, instance.fnlRow]];
                <>
                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 {
            <>
            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] = {

        <>
        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;

        <>
        [] _ 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: BOOLEAN _ TRUE] = {

        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]}; 
    }.