GlobalPlacement.cpp

 avatar
unknown
plain_text
2 years ago
10 kB
6
Indexable
#include "GlobalPlacer.h"
#include "ExampleFunction.h"
#include "NumericalOptimizer.h"
#include <cstdlib>
#include <iostream>
#include <bits/stdc++.h>


GlobalPlacer::GlobalPlacer(wrapper::Placement& placement)
    : _placement(placement)
{
    bin_cut = 10;
    bound_width = _placement.boundryRight() - _placement.boundryLeft();
    bound_height = _placement.boundryTop() - _placement.boundryBottom();
    nets_num = _placement.numNets();
    bin_width = bound_width / bin_cut;
    bin_height = bound_height / bin_cut;

    double max_density = 0.0;
    for (unsigned i = 0; i < _placement.numModules(); i++) {
        max_density += _placement.module(i).area();
    }
    max_density /= (bound_width * bound_height);
    bin_max_area = max_density * bin_width * bin_height;

    module_isPlaced.assign(_placement.numModules(), false);
}

void GlobalPlacer::randomPlace(vector<double>& x)
{
    // random_device rd;
    // mt19937 g(rd());
    // srand(rd());
    srand(time(NULL));
    
    double coreWidth = _placement.boundryRight() - _placement.boundryLeft();
    double coreHeight = _placement.boundryTop() - _placement.boundryBottom();
    for (size_t i = 0; i < _placement.numModules(); ++i)
    {
        if (_placement.module(i).isFixed())
            continue;

        double width = _placement.module(i).width();
        double height = _placement.module(i).height();
        // double x = rand() % (int)(coreWidth - width) + _placement.boundryLeft();
        // double y = rand() % (int)(coreHeight - height) + _placement.boundryBottom();
        // _placement.module(i).setPosition(x, y);
        x[2 * i] = rand() % (int)(coreWidth - width) + _placement.boundryLeft();
        x[2 * i + 1] = rand() % (int)(coreHeight - height) + _placement.boundryBottom();
        _placement.module(i).setPosition(x[2 * i], x[2 * i + 1]);
    }
}

void GlobalPlacer::net_place(vector<double>& x, unsigned seed) {
    // random_device rd;
    // mt19937 g(rd());
    vector<int> net_place_order(nets_num);
    for (unsigned i = 0; i < nets_num; i++) {
        net_place_order[i] = i;
    }

    srand(seed);
    // shuffle(net_place_order.begin(), net_place_order.end(), seed);
    random_shuffle(net_place_order.begin(), net_place_order.end());

    int bin_cnt = 0;
    double cur_bin_area = 0.0;
    for (auto i : net_place_order) {
        for (unsigned j = 0; j < _placement.net(i).numPins(); j++) {

            int cur_module_id = _placement.net(i).pin(j).moduleId();
            if (_placement.module(cur_module_id).isFixed() || module_isPlaced[cur_module_id]) {
                continue;
            }

            double  module_w = _placement.module(cur_module_id).width(),
                module_h = _placement.module(cur_module_id).height();

            if (cur_bin_area + _placement.module(cur_module_id).area() > bin_max_area) {
                cur_bin_area = 0;
                bin_cnt++;
            }

            double x_coor = (bin_cnt % bin_cut) * bin_width + rand() % (int)(module_w)+_placement.boundryLeft();
            double y_coor = (bin_cnt / bin_cut) * bin_height + rand() % (int)(module_h)+_placement.boundryBottom();
            _placement.module(cur_module_id).setPosition(x_coor, y_coor);

            x[2 * cur_module_id] = _placement.module(cur_module_id).x();
            x[2 * cur_module_id + 1] = _placement.module(cur_module_id).y();
            // x[2 * cur_module_id] = _placement.module(cur_module_id).centerX();
            // x[2 * cur_module_id + 1] = _placement.module(cur_module_id).centerY();
            

            module_isPlaced[cur_module_id] = true;
            cur_bin_area += _placement.module(cur_module_id).area();
        }
    }

    for (unsigned i = 0; i < _placement.numModules(); i++) {
        module_isPlaced[i] = false;
    }

}

void GlobalPlacer::findBestInitPlace(vector<double>& x) {
    double BestHPWL = 0.0, curHPWL = 0.0;
    unsigned BestSeed = 0, seed = 0;

    int try_times = 1000;
    for (int i = 0; i < try_times; i++) {
        random_device rd;
        seed = rd();
        // mt19937 g(rd());

        net_place(x, seed);
        curHPWL = _placement.computeHpwl();

        if (curHPWL < BestHPWL || i == 0) {
            BestHPWL = curHPWL;
            BestSeed = seed;
            cout << "Debug: curHPWL = " << curHPWL << endl;
        }
        if (i == try_times - 1) {
            net_place(x, BestSeed);
            curHPWL = _placement.computeHpwl();
            // cout << "Debug: computeHPWL() = " << curHPWL << ", BestHPWL = " << BestHPWL << endl;
        }
    }

}

void GlobalPlacer::place()
{
    ///////////////////////////////////////////////////////////////////
    // The following example is only for analytical methods.
    // if you use other methods, you can skip and delete it directly.
    //////////////////////////////////////////////////////////////////
    const double boundary_left = _placement.boundryLeft();
    const double boundary_right = _placement.boundryRight();
    const double boundary_bottom = _placement.boundryBottom();
    const double boundary_top = _placement.boundryTop();

    ExampleFunction ef(_placement, *this); // require to define the object function and gradient function

    vector<double> x(ef.dimension()); // solution vector, size: num_blocks*2
    // each 2 variables represent the X and Y dimensions of a block
    // x[0] = 100;          // initialize the solution vector
    // x[1] = 100;
    randomPlace(x);
    // net_place(x);
    // findBestInitPlace(x);


    NumericalOptimizer no(ef);
    // no.setNumIteration(35); // user-specified parameter
    // no.solve();             // Conjugate Gradient solver
    for (int i = 0; i < 2; i++) {
        cout << "Debug: solve iteration " << i << endl;
        no.setX(x);             // set initial solution
        no.setStepSizeBound((boundary_right - boundary_left) / 10); // user-specified parameter
        no.setNumIteration((i == 0) ? 150 : 35); // user-specified parameter
        no.solve();             // Conjugate Gradient solver

        for (unsigned j = 0; j < _placement.numModules(); j++) {
            double m_x = no.x(2 * j);
            double m_y = no.x(2 * j + 1);

            const double m_w = _placement.module(j).width() / 2;
            const double m_h = _placement.module(j).height() / 2;

            if (_placement.module(j).isFixed()) {
                m_x = _placement.module(j).x();
                m_y = _placement.module(j).y();
            }
            else {
                m_x = (m_x + m_w > boundary_right) ? (boundary_right - m_w)
                    : (m_x - m_w < boundary_left) ? boundary_left : m_x;

                m_y = (m_y + m_h > boundary_top) ? (boundary_top - m_h)
                    : (m_y - m_h < boundary_bottom) ? boundary_bottom : m_y;
            }

            // _placement.module(j).setPosition(m_x - m_w, m_y - m_h);

            x[2 * j] = m_x;
            x[2 * j + 1] = m_y;
            _placement.module(j).setPosition(m_x, m_y);
        }
        // no.setX(x);
        ef.increase_lambda();
    }

    // cout << "Current solution:\n";
    // for (unsigned i = 0; i < no.dimension(); i++)
    // {
    //     cout << "x[" << i << "] = " << no.x(i) << "\n";
    // }
    cout << "Objective: " << no.objective() << "\n";
    ////////////////////////////////////////////////////////////////

    // An example of random placement implemented by TA.
    // If you want to use it, please uncomment the folllwing 1 line.
    // randomPlace(x);
    // net_place(x);

    /* @@@ TODO
     * 1. Understand above example and modify ExampleFunction.cpp to implement the analytical placement
     * 2. You can choose LSE or WA as the wirelength model, the former is easier to calculate the gradient
     * 3. For the bin density model, you could refer to the lecture notes
     * 4. You should first calculate the form of wirelength model and bin density model and the forms of their gradients ON YOUR OWN
     * 5. Replace the value of f in evaluateF() by the form like "f = alpha*WL() + beta*BinDensity()"
     * 6. Replace the form of g[] in evaluateG() by the form like "g = grad(WL()) + grad(BinDensity())"
     * 7. Set the initial vector x in place(), set step size, set #iteration, and call the solver like above example
     * */
}

// void GlobalPlacer::plotPlacementResult(const string outfilename, bool isPrompt)
// {
//     ofstream outfile(outfilename.c_str(), ios::out);
//     outfile << " " << endl;
//     outfile << "set title \"wirelength = " << _placement.computeHpwl() << "\"" << endl;
//     outfile << "set size ratio 1" << endl;
//     outfile << "set nokey" << endl
//             << endl;
//     outfile << "plot[:][:] '-' w l lt 3 lw 2, '-' w l lt 1" << endl
//             << endl;
//     outfile << "# bounding box" << endl;
//     plotBoxPLT(outfile, _placement.boundryLeft(), _placement.boundryBottom(), _placement.boundryRight(), _placement.boundryTop());
//     outfile << "EOF" << endl;
//     outfile << "# modules" << endl
//             << "0.00, 0.00" << endl
//             << endl;
//     for (size_t i = 0; i < _placement.numModules(); ++i)
//     {
//         wrapper::Module module = _placement.module(i);
//         plotBoxPLT(outfile, module.x(), module.y(), module.x() + module.width(), module.y() + module.height());
//     }
//     outfile << "EOF" << endl;
//     outfile << "pause -1 'Press any key to close.'" << endl;
//     outfile.close();

//     if (isPrompt)
//     {
//         char cmd[200];
//         sprintf(cmd, "gnuplot %s", outfilename.c_str());
//         if (!system(cmd))
//         {
//             cout << "Fail to execute: \"" << cmd << "\"." << endl;
//         }
//     }
// }

// void GlobalPlacer::plotBoxPLT(ofstream &stream, double x1, double y1, double x2, double y2)
// {
//     stream << x1 << ", " << y1 << endl
//            << x2 << ", " << y1 << endl
//            << x2 << ", " << y2 << endl
//            << x1 << ", " << y2 << endl
//            << x1 << ", " << y1 << endl
//            << endl;
// }
Editor is loading...
Leave a Comment