110448Snilay@cs.wisc.edu/* Copyright (c) 2012 Massachusetts Institute of Technology
210448Snilay@cs.wisc.edu *
310448Snilay@cs.wisc.edu * Permission is hereby granted, free of charge, to any person obtaining a copy
410448Snilay@cs.wisc.edu * of this software and associated documentation files (the "Software"), to deal
510448Snilay@cs.wisc.edu * in the Software without restriction, including without limitation the rights
610448Snilay@cs.wisc.edu * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
710448Snilay@cs.wisc.edu * copies of the Software, and to permit persons to whom the Software is
810448Snilay@cs.wisc.edu * furnished to do so, subject to the following conditions:
910448Snilay@cs.wisc.edu *
1010448Snilay@cs.wisc.edu * The above copyright notice and this permission notice shall be included in
1110448Snilay@cs.wisc.edu * all copies or substantial portions of the Software.
1210448Snilay@cs.wisc.edu *
1310448Snilay@cs.wisc.edu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1410448Snilay@cs.wisc.edu * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1510448Snilay@cs.wisc.edu * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1610448Snilay@cs.wisc.edu * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1710448Snilay@cs.wisc.edu * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1810448Snilay@cs.wisc.edu * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1910448Snilay@cs.wisc.edu * THE SOFTWARE.
2010448Snilay@cs.wisc.edu */
2110448Snilay@cs.wisc.edu
2210447Snilay@cs.wisc.edu#include "tech/TechModel.h"
2310447Snilay@cs.wisc.edu
2410447Snilay@cs.wisc.edu#include <cmath>
2510447Snilay@cs.wisc.edu
2610447Snilay@cs.wisc.edu#include "model/std_cells/StdCellLib.h"
2710447Snilay@cs.wisc.edu
2810447Snilay@cs.wisc.edunamespace DSENT
2910447Snilay@cs.wisc.edu{
3010447Snilay@cs.wisc.edu    TechModel::TechModel()
3110448Snilay@cs.wisc.edu        : m_std_cell_lib_(NULL), m_available_wire_layers_(NULL)
3210447Snilay@cs.wisc.edu    {}
3310447Snilay@cs.wisc.edu
3410447Snilay@cs.wisc.edu    TechModel::~TechModel()
3510447Snilay@cs.wisc.edu    {}
3610447Snilay@cs.wisc.edu
3710448Snilay@cs.wisc.edu    const String& TechModel::get(const String &key_) const
3810448Snilay@cs.wisc.edu    {
3910448Snilay@cs.wisc.edu        return params.at(key_);
4010448Snilay@cs.wisc.edu    }
4110448Snilay@cs.wisc.edu
4210447Snilay@cs.wisc.edu    void TechModel::setStdCellLib(const StdCellLib* std_cell_lib_)
4310447Snilay@cs.wisc.edu    {
4410447Snilay@cs.wisc.edu        m_std_cell_lib_ = std_cell_lib_;
4510447Snilay@cs.wisc.edu        return;
4610447Snilay@cs.wisc.edu    }
4710447Snilay@cs.wisc.edu
4810447Snilay@cs.wisc.edu    const StdCellLib* TechModel::getStdCellLib() const
4910447Snilay@cs.wisc.edu    {
5010447Snilay@cs.wisc.edu        return m_std_cell_lib_;
5110447Snilay@cs.wisc.edu    }
5210447Snilay@cs.wisc.edu
5310447Snilay@cs.wisc.edu    TechModel* TechModel::clone() const
5410447Snilay@cs.wisc.edu    {
5510447Snilay@cs.wisc.edu        return new TechModel(*this);
5610447Snilay@cs.wisc.edu    }
5710447Snilay@cs.wisc.edu
5810447Snilay@cs.wisc.edu    void TechModel::readFile(const String& filename_)
5910447Snilay@cs.wisc.edu    {
6010447Snilay@cs.wisc.edu        // Read the main technology file
6110448Snilay@cs.wisc.edu        LibUtil::readFile(filename_, params);
6210447Snilay@cs.wisc.edu
6310447Snilay@cs.wisc.edu        // Search for "INCLUDE" to include more technology files
6410448Snilay@cs.wisc.edu        for (const auto &it : params)
6510447Snilay@cs.wisc.edu        {
6610448Snilay@cs.wisc.edu            const String& key = it.first;
6710447Snilay@cs.wisc.edu            if(key.compare(0, 8, "INCLUDE_") == 0)
6810447Snilay@cs.wisc.edu            {
6910448Snilay@cs.wisc.edu                const String& include_filename = it.second;
7010448Snilay@cs.wisc.edu                LibUtil::readFile(include_filename, params);
7110447Snilay@cs.wisc.edu            }
7210447Snilay@cs.wisc.edu        }
7310447Snilay@cs.wisc.edu
7410447Snilay@cs.wisc.edu        // Set the available wire layers
7510447Snilay@cs.wisc.edu        const vector<String>& available_wire_layer_vector = get("Wire->AvailableLayers").split("[,]");
7610447Snilay@cs.wisc.edu        m_available_wire_layers_ = new std::set<String>;
7710447Snilay@cs.wisc.edu        for(unsigned int i = 0; i < available_wire_layer_vector.size(); ++i)
7810447Snilay@cs.wisc.edu        {
7910447Snilay@cs.wisc.edu            m_available_wire_layers_->insert(available_wire_layer_vector[i]);
8010447Snilay@cs.wisc.edu        }
8110447Snilay@cs.wisc.edu    }
8210447Snilay@cs.wisc.edu
8310447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
8410447Snilay@cs.wisc.edu    // Transistor Related Functions
8510447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
8610447Snilay@cs.wisc.edu    //Returns the leakage current of NMOS transistors, given the transistor stakcing, transistor widths, and input combination
8710447Snilay@cs.wisc.edu    double TechModel::calculateNmosLeakageCurrent(unsigned int num_stacks_, double uni_stacked_mos_width_, unsigned int input_vector_) const
8810447Snilay@cs.wisc.edu    {
8910447Snilay@cs.wisc.edu        vector<double> stacked_mos_widths_(num_stacks_, uni_stacked_mos_width_);
9010447Snilay@cs.wisc.edu        return calculateNmosLeakageCurrent(num_stacks_, stacked_mos_widths_, input_vector_);
9110447Snilay@cs.wisc.edu    }
9210447Snilay@cs.wisc.edu
9310447Snilay@cs.wisc.edu    //Returns the leakage current of NMOS transistors, given the transistor stakcing, transistor widths, and input combination
9410447Snilay@cs.wisc.edu    double TechModel::calculateNmosLeakageCurrent(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_) const
9510447Snilay@cs.wisc.edu    {
9610447Snilay@cs.wisc.edu        // Get technology parameters
9710447Snilay@cs.wisc.edu        double vdd = get("Vdd");
9810447Snilay@cs.wisc.edu        double temp = get("Temperature");
9910447Snilay@cs.wisc.edu        double char_temp = get("Nmos->CharacterizedTemperature");
10010447Snilay@cs.wisc.edu        double min_off_current = get("Nmos->MinOffCurrent");
10110447Snilay@cs.wisc.edu        double off_current = get("Nmos->OffCurrent");
10210447Snilay@cs.wisc.edu        double subthreshold_swing = get("Nmos->SubthresholdSwing");
10310447Snilay@cs.wisc.edu        double dibl = get("Nmos->DIBL");
10410447Snilay@cs.wisc.edu        double temp_swing = get("Nmos->SubthresholdTempSwing");
10510447Snilay@cs.wisc.edu
10610447Snilay@cs.wisc.edu        // Map dibl to a swing value for easier calculation
10710447Snilay@cs.wisc.edu        double dibl_swing = subthreshold_swing / dibl;
10810447Snilay@cs.wisc.edu
10910447Snilay@cs.wisc.edu        //Calculate the leakage current factor
11010447Snilay@cs.wisc.edu        double leakage_current_factor = calculateLeakageCurrentFactor(num_stacks_, stacked_mos_widths_, input_vector_, vdd, subthreshold_swing, dibl_swing);
11110447Snilay@cs.wisc.edu
11210447Snilay@cs.wisc.edu        // Calcualte actual leakage current at characterized temperature
11310447Snilay@cs.wisc.edu        double leakage_current_char_tmp = stacked_mos_widths_[0] * off_current * std::pow(10.0, leakage_current_factor);
11410447Snilay@cs.wisc.edu        leakage_current_char_tmp = std::max(min_off_current, leakage_current_char_tmp);
11510447Snilay@cs.wisc.edu
11610447Snilay@cs.wisc.edu        // Calculate actual leakage current at temp
11710447Snilay@cs.wisc.edu        double leakage_current = leakage_current_char_tmp * std::pow(10.0, (temp - char_temp) / temp_swing);
11810447Snilay@cs.wisc.edu
11910447Snilay@cs.wisc.edu        return leakage_current;
12010447Snilay@cs.wisc.edu    }
12110447Snilay@cs.wisc.edu
12210447Snilay@cs.wisc.edu    double TechModel::calculatePmosLeakageCurrent(unsigned int num_stacks_, double uni_stacked_mos_width_, unsigned int input_vector_) const
12310447Snilay@cs.wisc.edu    {
12410447Snilay@cs.wisc.edu        vector<double> stacked_mos_widths_(num_stacks_, uni_stacked_mos_width_);
12510447Snilay@cs.wisc.edu        return calculatePmosLeakageCurrent(num_stacks_, stacked_mos_widths_, input_vector_);
12610447Snilay@cs.wisc.edu    }
12710447Snilay@cs.wisc.edu
12810447Snilay@cs.wisc.edu    //Returns the leakage current of PMOS transistors, given the transistor stakcing, transistor widths, and input combination
12910447Snilay@cs.wisc.edu    double TechModel::calculatePmosLeakageCurrent(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_) const
13010447Snilay@cs.wisc.edu    {
13110447Snilay@cs.wisc.edu        // Get technology parameters
13210447Snilay@cs.wisc.edu        double vdd = get("Vdd");
13310447Snilay@cs.wisc.edu        double temp = get("Temperature");
13410447Snilay@cs.wisc.edu        double char_temp = get("Pmos->CharacterizedTemperature");
13510447Snilay@cs.wisc.edu        double min_off_current = get("Pmos->MinOffCurrent");
13610447Snilay@cs.wisc.edu        double off_current = get("Pmos->OffCurrent");
13710447Snilay@cs.wisc.edu        double dibl = get("Pmos->DIBL");
13810447Snilay@cs.wisc.edu        double subthreshold_swing = get("Pmos->SubthresholdSwing");
13910447Snilay@cs.wisc.edu        double temp_swing = get("Nmos->SubthresholdTempSwing");
14010447Snilay@cs.wisc.edu
14110447Snilay@cs.wisc.edu        // Map dibl to a swing value for easier calculation
14210447Snilay@cs.wisc.edu        double dibl_swing = subthreshold_swing / dibl;
14310447Snilay@cs.wisc.edu
14410447Snilay@cs.wisc.edu        //Calculate the leakage current factor
14510447Snilay@cs.wisc.edu        double leakage_current_factor = calculateLeakageCurrentFactor(num_stacks_, stacked_mos_widths_, input_vector_, vdd, subthreshold_swing, dibl_swing);
14610447Snilay@cs.wisc.edu
14710447Snilay@cs.wisc.edu        // Calcualte actual leakage current at characterized temperature
14810447Snilay@cs.wisc.edu        double leakage_current_char_tmp = stacked_mos_widths_[0] * off_current * std::pow(10.0, leakage_current_factor);
14910447Snilay@cs.wisc.edu        leakage_current_char_tmp = std::max(min_off_current, leakage_current_char_tmp);
15010447Snilay@cs.wisc.edu
15110447Snilay@cs.wisc.edu        // Calculate actual leakage current at temp
15210447Snilay@cs.wisc.edu        double leakage_current = leakage_current_char_tmp * std::pow(10.0, (temp - char_temp) / temp_swing);
15310447Snilay@cs.wisc.edu
15410447Snilay@cs.wisc.edu        return leakage_current;
15510447Snilay@cs.wisc.edu    }
15610447Snilay@cs.wisc.edu
15710447Snilay@cs.wisc.edu    //Returns the leakage current, given the transistor stakcing, transistor widths, input combination,
15810447Snilay@cs.wisc.edu    //and technology information (vdd, subthreshold swing, subthreshold dibl swing)
15910447Snilay@cs.wisc.edu    double TechModel::calculateLeakageCurrentFactor(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_, double vdd_, double subthreshold_swing_, double dibl_swing_) const
16010447Snilay@cs.wisc.edu    {
16110447Snilay@cs.wisc.edu        // check everything is valid
16210447Snilay@cs.wisc.edu        ASSERT(num_stacks_ >= 1, "[Error] Number of stacks must be >= 1!");
16310447Snilay@cs.wisc.edu        ASSERT(stacked_mos_widths_.size() == num_stacks_, "[Error] Mismatch in number of stacks and the widths specified!");
16410447Snilay@cs.wisc.edu
16510447Snilay@cs.wisc.edu        //Use short name in this method
16610447Snilay@cs.wisc.edu        const double s1 = subthreshold_swing_;
16710447Snilay@cs.wisc.edu        const double s2 = dibl_swing_;
16810447Snilay@cs.wisc.edu
16910447Snilay@cs.wisc.edu        // Decode input combinations from input_vector_
17010447Snilay@cs.wisc.edu        std::vector<double> vs(num_stacks_, 0.0);
17110447Snilay@cs.wisc.edu        for(int i = 0; i < (int)num_stacks_; ++i)
17210447Snilay@cs.wisc.edu        {
17310447Snilay@cs.wisc.edu            double current_input = (double(input_vector_ & 0x1))*vdd_;
17410447Snilay@cs.wisc.edu            vs[i] = (current_input);
17510447Snilay@cs.wisc.edu            input_vector_ >>= 1;
17610447Snilay@cs.wisc.edu        }
17710447Snilay@cs.wisc.edu        // If the widths pointer is NULL, width is set to 1 by default
17810447Snilay@cs.wisc.edu        vector<double> ws = stacked_mos_widths_;
17910447Snilay@cs.wisc.edu
18010447Snilay@cs.wisc.edu        //Solve voltages at internal nodes of stacked transistors
18110447Snilay@cs.wisc.edu        // v[0] = 0
18210447Snilay@cs.wisc.edu        // v[num_stacks_] = vdd_
18310447Snilay@cs.wisc.edu        // v[i] = (1.0/(2*s1 + s2))*((s1 + s2)*v[i - 1] + s1*v[i + 1]
18410447Snilay@cs.wisc.edu        //                 + s2*(vs[i + 1] - vs[i]) + s1*s2*log10(ws[i + 1]/ws[i]))
18510447Snilay@cs.wisc.edu        //Use tri-matrix solver to solve the above linear system
18610447Snilay@cs.wisc.edu
18710447Snilay@cs.wisc.edu        double A = -(s1 + s2);
18810447Snilay@cs.wisc.edu        double B = 2*s1 + s2;
18910447Snilay@cs.wisc.edu        double C = -s1;
19010447Snilay@cs.wisc.edu        std::vector<double> a(num_stacks_ - 1, 0);
19110447Snilay@cs.wisc.edu        std::vector<double> b(num_stacks_ - 1, 0);
19210447Snilay@cs.wisc.edu        std::vector<double> c(num_stacks_ - 1, 0);
19310447Snilay@cs.wisc.edu        std::vector<double> d(num_stacks_ - 1, 0);
19410447Snilay@cs.wisc.edu        std::vector<double> v(num_stacks_ + 1, 0);
19510447Snilay@cs.wisc.edu        unsigned int eff_num_stacks = num_stacks_;
19610447Snilay@cs.wisc.edu        bool is_found_valid_v = false;
19710447Snilay@cs.wisc.edu        do
19810447Snilay@cs.wisc.edu        {
19910447Snilay@cs.wisc.edu            //Set boundary condition
20010447Snilay@cs.wisc.edu            v[0] = 0;
20110447Snilay@cs.wisc.edu            v[eff_num_stacks] = vdd_;
20210447Snilay@cs.wisc.edu
20310447Snilay@cs.wisc.edu            //If the effective number of stacks is 1, no matrix needs to be solved
20410447Snilay@cs.wisc.edu            if(eff_num_stacks == 1)
20510447Snilay@cs.wisc.edu            {
20610447Snilay@cs.wisc.edu                break;
20710447Snilay@cs.wisc.edu            }
20810447Snilay@cs.wisc.edu
20910447Snilay@cs.wisc.edu            //----------------------------------------------------------------------
21010447Snilay@cs.wisc.edu            //Setup the tri-matrix
21110447Snilay@cs.wisc.edu            //----------------------------------------------------------------------
21210447Snilay@cs.wisc.edu            for(int i = 0; i < (int)eff_num_stacks-2; ++i)
21310447Snilay@cs.wisc.edu            {
21410447Snilay@cs.wisc.edu                a[i + 1] = A;
21510447Snilay@cs.wisc.edu                c[i] = C;
21610447Snilay@cs.wisc.edu            }
21710447Snilay@cs.wisc.edu            for(int i = 0; i < (int)eff_num_stacks-1; ++i)
21810447Snilay@cs.wisc.edu            {
21910447Snilay@cs.wisc.edu                b[i] = B;
22010447Snilay@cs.wisc.edu                d[i] = s2*(vs[i + 1] - vs[i]) + s1*s2*std::log10(ws[i + 1]/ws[i]);
22110447Snilay@cs.wisc.edu                if(i == ((int)eff_num_stacks - 2))
22210447Snilay@cs.wisc.edu                {
22310447Snilay@cs.wisc.edu                    d[i] -= C*vdd_;
22410447Snilay@cs.wisc.edu                }
22510447Snilay@cs.wisc.edu            }
22610447Snilay@cs.wisc.edu            //----------------------------------------------------------------------
22710447Snilay@cs.wisc.edu
22810447Snilay@cs.wisc.edu            //----------------------------------------------------------------------
22910447Snilay@cs.wisc.edu            //Solve the tri-matrix
23010447Snilay@cs.wisc.edu            //----------------------------------------------------------------------
23110447Snilay@cs.wisc.edu            for(int i = 1; i < (int)eff_num_stacks-1; ++i)
23210447Snilay@cs.wisc.edu            {
23310447Snilay@cs.wisc.edu                double m = a[i]/b[i - 1];
23410447Snilay@cs.wisc.edu                b[i] -= m*c[i - 1];
23510447Snilay@cs.wisc.edu                d[i] -= m*d[i - 1];
23610447Snilay@cs.wisc.edu            }
23710447Snilay@cs.wisc.edu
23810447Snilay@cs.wisc.edu            v[eff_num_stacks - 1] = d[eff_num_stacks - 2]/b[eff_num_stacks - 2];
23910447Snilay@cs.wisc.edu            for(int i = eff_num_stacks - 3; i >= 0; --i)
24010447Snilay@cs.wisc.edu            {
24110447Snilay@cs.wisc.edu                v[i + 1] = (d[i] - c[i]*v[i + 2])/b[i];
24210447Snilay@cs.wisc.edu            }
24310447Snilay@cs.wisc.edu            //----------------------------------------------------------------------
24410447Snilay@cs.wisc.edu
24510447Snilay@cs.wisc.edu            //Check if the internal voltages are in increasing order
24610447Snilay@cs.wisc.edu            is_found_valid_v = true;
24710447Snilay@cs.wisc.edu            for(int i = 1; i <= (int)eff_num_stacks; ++i)
24810447Snilay@cs.wisc.edu            {
24910447Snilay@cs.wisc.edu                //If the ith internal voltage is not in increasing order
25010447Snilay@cs.wisc.edu                //(i-1)th transistor is in triode region
25110447Snilay@cs.wisc.edu                //Remove the transistors in triode region as it does not exist
25210447Snilay@cs.wisc.edu                if(v[i] < v[i - 1])
25310447Snilay@cs.wisc.edu                {
25410447Snilay@cs.wisc.edu                    is_found_valid_v = false;
25510447Snilay@cs.wisc.edu                    eff_num_stacks--;
25610447Snilay@cs.wisc.edu                    vs.erase(vs.begin() + i - 1);
25710447Snilay@cs.wisc.edu                    ws.erase(ws.begin() + i - 1);
25810447Snilay@cs.wisc.edu                    break;
25910447Snilay@cs.wisc.edu                }
26010447Snilay@cs.wisc.edu            }
26110447Snilay@cs.wisc.edu        } while(!is_found_valid_v);
26210447Snilay@cs.wisc.edu
26310447Snilay@cs.wisc.edu        //Calculate the leakage current of the bottom transistor (first not in triode region)
26410447Snilay@cs.wisc.edu        double vgs = vs[0] - v[0];
26510447Snilay@cs.wisc.edu        double vds = v[1] - v[0];
26610447Snilay@cs.wisc.edu        double leakage_current_factor = vgs/s1 + (vds - vdd_)/s2;
26710447Snilay@cs.wisc.edu        //TODO - Check if the leakage current calculate for other transistors is identical
26810447Snilay@cs.wisc.edu
26910447Snilay@cs.wisc.edu        return leakage_current_factor;
27010447Snilay@cs.wisc.edu    }
27110447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
27210447Snilay@cs.wisc.edu
27310447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
27410447Snilay@cs.wisc.edu    // Wire Related Functions
27510447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
27610447Snilay@cs.wisc.edu    bool TechModel::isWireLayerExist(const String& layer_name_) const
27710447Snilay@cs.wisc.edu    {
27810447Snilay@cs.wisc.edu        std::set<String>::const_iterator it;
27910447Snilay@cs.wisc.edu        it = m_available_wire_layers_->find(layer_name_);
28010447Snilay@cs.wisc.edu        return (it != m_available_wire_layers_->end());
28110447Snilay@cs.wisc.edu    }
28210447Snilay@cs.wisc.edu
28310447Snilay@cs.wisc.edu    const std::set<String>* TechModel::getAvailableWireLayers() const
28410447Snilay@cs.wisc.edu    {
28510447Snilay@cs.wisc.edu        return m_available_wire_layers_;
28610447Snilay@cs.wisc.edu    }
28710447Snilay@cs.wisc.edu
28810447Snilay@cs.wisc.edu    double TechModel::calculateWireCapacitance(const String& layer_name_, double width_, double spacing_, double length_) const
28910447Snilay@cs.wisc.edu    {
29010447Snilay@cs.wisc.edu        // Get technology parameter
29110447Snilay@cs.wisc.edu        double min_width = get("Wire->" + layer_name_ + "->MinWidth").toDouble();
29210447Snilay@cs.wisc.edu        double min_spacing = get("Wire->" + layer_name_ + "->MinSpacing").toDouble();
29310447Snilay@cs.wisc.edu        double metal_thickness = get("Wire->" + layer_name_ + "->MetalThickness").toDouble();
29410447Snilay@cs.wisc.edu        double dielec_thickness = get("Wire->" + layer_name_ + "->DielectricThickness").toDouble();
29510447Snilay@cs.wisc.edu        double dielec_const = get("Wire->" + layer_name_ + "->DielectricConstant").toDouble();
29610447Snilay@cs.wisc.edu
29710447Snilay@cs.wisc.edu        ASSERT(width_ >= min_width, "[Error] Wire width must be >= " + (String) min_width + "!");
29810447Snilay@cs.wisc.edu        ASSERT(spacing_ >= min_spacing, "[Error] Wire spacing must be >= " + (String) min_spacing + "!");
29910447Snilay@cs.wisc.edu        ASSERT(length_ >= 0, "[Error] Wire length must be >= 0!");
30010447Snilay@cs.wisc.edu
30110447Snilay@cs.wisc.edu        double A, B, C;
30210447Snilay@cs.wisc.edu        // Calculate ground capacitance
30310447Snilay@cs.wisc.edu        A = width_ / dielec_thickness;
30410447Snilay@cs.wisc.edu        B = 2.04*std::pow((spacing_ / (spacing_ + 0.54 * dielec_thickness)), 1.77);
30510447Snilay@cs.wisc.edu        C = std::pow((metal_thickness / (metal_thickness + 4.53 * dielec_thickness)), 0.07);
30610447Snilay@cs.wisc.edu        double unit_gnd_cap = dielec_const * 8.85e-12 * (A + B * C);
30710447Snilay@cs.wisc.edu
30810447Snilay@cs.wisc.edu        A = 1.14 * (metal_thickness / spacing_) * std::exp(-4.0 * spacing_ / (spacing_ + 8.01 * dielec_thickness));
30910447Snilay@cs.wisc.edu        B = 2.37 * std::pow((width_ / (width_ + 0.31 * spacing_)), 0.28);
31010447Snilay@cs.wisc.edu        C = std::pow((dielec_thickness / (dielec_thickness + 8.96 * spacing_)), 0.76) *
31110447Snilay@cs.wisc.edu                std::exp(-2.0 * spacing_ / (spacing_ + 6.0 * dielec_thickness));
31210447Snilay@cs.wisc.edu        double unit_coupling_cap = dielec_const * 8.85e-12 * (A + B * C);
31310447Snilay@cs.wisc.edu
31410447Snilay@cs.wisc.edu        double total_cap = 2 * (unit_gnd_cap + unit_coupling_cap) * length_;
31510447Snilay@cs.wisc.edu        return total_cap;
31610447Snilay@cs.wisc.edu    }
31710447Snilay@cs.wisc.edu
31810447Snilay@cs.wisc.edu    double TechModel::calculateWireResistance(const String& layer_name_, double width_, double length_) const
31910447Snilay@cs.wisc.edu    {
32010447Snilay@cs.wisc.edu        // Get technology parameter
32110447Snilay@cs.wisc.edu        double min_width = get("Wire->" + layer_name_ + "->MinWidth");
32210447Snilay@cs.wisc.edu        //double barrier_thickness = get("Wire->" + layer_name_ + "->BarrierThickness");
32310447Snilay@cs.wisc.edu        double resistivity = get("Wire->" + layer_name_ + "->Resistivity");
32410447Snilay@cs.wisc.edu        double metal_thickness = get("Wire->" + layer_name_ + "->MetalThickness");
32510447Snilay@cs.wisc.edu
32610447Snilay@cs.wisc.edu        ASSERT(width_ >= min_width, "[Error] Wire width must be >= " + (String) min_width + "!");
32710447Snilay@cs.wisc.edu        ASSERT(length_ >= 0, "[Error] Wire length must be >= 0!");
32810447Snilay@cs.wisc.edu
32910447Snilay@cs.wisc.edu        // Calculate Rho
33010447Snilay@cs.wisc.edu        // double rho = 2.202e-8 + (1.030e-15 / (width_ - 2.0 * barrier_thickness));
33110447Snilay@cs.wisc.edu
33210447Snilay@cs.wisc.edu        double unit_res = resistivity / (width_ * metal_thickness);
33310447Snilay@cs.wisc.edu        //double unit_res = rho / ((width_ - 2.0 * barrier_thickness) * (metal_thickness - barrier_thickness));
33410447Snilay@cs.wisc.edu
33510447Snilay@cs.wisc.edu        double total_res = unit_res * length_;
33610447Snilay@cs.wisc.edu        return total_res;
33710447Snilay@cs.wisc.edu    }
33810447Snilay@cs.wisc.edu    //-------------------------------------------------------------------------
33910447Snilay@cs.wisc.edu
34010447Snilay@cs.wisc.edu    TechModel::TechModel(const TechModel& tech_model_)
34110448Snilay@cs.wisc.edu        : m_std_cell_lib_(tech_model_.m_std_cell_lib_),
34210448Snilay@cs.wisc.edu          params(tech_model_.params)
34310447Snilay@cs.wisc.edu    {}
34410447Snilay@cs.wisc.edu} // namespace DSENT
345