TechModel.cc revision 10447:a465576671d4
1#include "tech/TechModel.h"
2
3#include <cmath>
4
5#include "model/std_cells/StdCellLib.h"
6
7namespace DSENT
8{
9    TechModel::TechModel()
10        : Config(), m_std_cell_lib_(NULL), m_available_wire_layers_(NULL)
11    {}
12
13    TechModel::~TechModel()
14    {}
15
16    void TechModel::setStdCellLib(const StdCellLib* std_cell_lib_)
17    {
18        m_std_cell_lib_ = std_cell_lib_;
19        return;
20    }
21
22    const StdCellLib* TechModel::getStdCellLib() const
23    {
24        return m_std_cell_lib_;
25    }
26
27    TechModel* TechModel::clone() const
28    {
29        return new TechModel(*this);
30    }
31
32    void TechModel::readFile(const String& filename_)
33    {
34        // Read the main technology file
35        LibUtil::Config::readFile(filename_);
36
37        // Search for "INCLUDE" to include more technology files
38        StringMap::ConstIterator it;
39        for(it = begin(); it != end(); ++it)
40        {
41            const String& key = it->first;
42            if(key.compare(0, 8, "INCLUDE_") == 0)
43            {
44                const String& include_filename = it->second;
45                LibUtil::Config::readFile(include_filename);
46            }
47        }
48
49        // Set the available wire layers
50        const vector<String>& available_wire_layer_vector = get("Wire->AvailableLayers").split("[,]");
51        m_available_wire_layers_ = new std::set<String>;
52        for(unsigned int i = 0; i < available_wire_layer_vector.size(); ++i)
53        {
54            m_available_wire_layers_->insert(available_wire_layer_vector[i]);
55        }
56        return;
57    }
58
59    //-------------------------------------------------------------------------
60    // Transistor Related Functions
61    //-------------------------------------------------------------------------
62    //Returns the leakage current of NMOS transistors, given the transistor stakcing, transistor widths, and input combination
63    double TechModel::calculateNmosLeakageCurrent(unsigned int num_stacks_, double uni_stacked_mos_width_, unsigned int input_vector_) const
64    {
65        vector<double> stacked_mos_widths_(num_stacks_, uni_stacked_mos_width_);
66        return calculateNmosLeakageCurrent(num_stacks_, stacked_mos_widths_, input_vector_);
67    }
68
69    //Returns the leakage current of NMOS transistors, given the transistor stakcing, transistor widths, and input combination
70    double TechModel::calculateNmosLeakageCurrent(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_) const
71    {
72        // Get technology parameters
73        double vdd = get("Vdd");
74        double temp = get("Temperature");
75        double char_temp = get("Nmos->CharacterizedTemperature");
76        double min_off_current = get("Nmos->MinOffCurrent");
77        double off_current = get("Nmos->OffCurrent");
78        double subthreshold_swing = get("Nmos->SubthresholdSwing");
79        double dibl = get("Nmos->DIBL");
80        double temp_swing = get("Nmos->SubthresholdTempSwing");
81
82        // Map dibl to a swing value for easier calculation
83        double dibl_swing = subthreshold_swing / dibl;
84
85        //Calculate the leakage current factor
86        double leakage_current_factor = calculateLeakageCurrentFactor(num_stacks_, stacked_mos_widths_, input_vector_, vdd, subthreshold_swing, dibl_swing);
87
88        // Calcualte actual leakage current at characterized temperature
89        double leakage_current_char_tmp = stacked_mos_widths_[0] * off_current * std::pow(10.0, leakage_current_factor);
90        leakage_current_char_tmp = std::max(min_off_current, leakage_current_char_tmp);
91
92        // Calculate actual leakage current at temp
93        double leakage_current = leakage_current_char_tmp * std::pow(10.0, (temp - char_temp) / temp_swing);
94
95        return leakage_current;
96    }
97
98    double TechModel::calculatePmosLeakageCurrent(unsigned int num_stacks_, double uni_stacked_mos_width_, unsigned int input_vector_) const
99    {
100        vector<double> stacked_mos_widths_(num_stacks_, uni_stacked_mos_width_);
101        return calculatePmosLeakageCurrent(num_stacks_, stacked_mos_widths_, input_vector_);
102    }
103
104    //Returns the leakage current of PMOS transistors, given the transistor stakcing, transistor widths, and input combination
105    double TechModel::calculatePmosLeakageCurrent(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_) const
106    {
107        // Get technology parameters
108        double vdd = get("Vdd");
109        double temp = get("Temperature");
110        double char_temp = get("Pmos->CharacterizedTemperature");
111        double min_off_current = get("Pmos->MinOffCurrent");
112        double off_current = get("Pmos->OffCurrent");
113        double dibl = get("Pmos->DIBL");
114        double subthreshold_swing = get("Pmos->SubthresholdSwing");
115        double temp_swing = get("Nmos->SubthresholdTempSwing");
116
117        // Map dibl to a swing value for easier calculation
118        double dibl_swing = subthreshold_swing / dibl;
119
120        //Calculate the leakage current factor
121        double leakage_current_factor = calculateLeakageCurrentFactor(num_stacks_, stacked_mos_widths_, input_vector_, vdd, subthreshold_swing, dibl_swing);
122
123        // Calcualte actual leakage current at characterized temperature
124        double leakage_current_char_tmp = stacked_mos_widths_[0] * off_current * std::pow(10.0, leakage_current_factor);
125        leakage_current_char_tmp = std::max(min_off_current, leakage_current_char_tmp);
126
127        // Calculate actual leakage current at temp
128        double leakage_current = leakage_current_char_tmp * std::pow(10.0, (temp - char_temp) / temp_swing);
129
130        return leakage_current;
131    }
132
133    //Returns the leakage current, given the transistor stakcing, transistor widths, input combination,
134    //and technology information (vdd, subthreshold swing, subthreshold dibl swing)
135    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
136    {
137        // check everything is valid
138        ASSERT(num_stacks_ >= 1, "[Error] Number of stacks must be >= 1!");
139        ASSERT(stacked_mos_widths_.size() == num_stacks_, "[Error] Mismatch in number of stacks and the widths specified!");
140
141        //Use short name in this method
142        const double s1 = subthreshold_swing_;
143        const double s2 = dibl_swing_;
144
145        // Decode input combinations from input_vector_
146        std::vector<double> vs(num_stacks_, 0.0);
147        for(int i = 0; i < (int)num_stacks_; ++i)
148        {
149            double current_input = (double(input_vector_ & 0x1))*vdd_;
150            vs[i] = (current_input);
151            input_vector_ >>= 1;
152        }
153        // If the widths pointer is NULL, width is set to 1 by default
154        vector<double> ws = stacked_mos_widths_;
155
156        //Solve voltages at internal nodes of stacked transistors
157        // v[0] = 0
158        // v[num_stacks_] = vdd_
159        // v[i] = (1.0/(2*s1 + s2))*((s1 + s2)*v[i - 1] + s1*v[i + 1]
160        //                 + s2*(vs[i + 1] - vs[i]) + s1*s2*log10(ws[i + 1]/ws[i]))
161        //Use tri-matrix solver to solve the above linear system
162
163        double A = -(s1 + s2);
164        double B = 2*s1 + s2;
165        double C = -s1;
166        std::vector<double> a(num_stacks_ - 1, 0);
167        std::vector<double> b(num_stacks_ - 1, 0);
168        std::vector<double> c(num_stacks_ - 1, 0);
169        std::vector<double> d(num_stacks_ - 1, 0);
170        std::vector<double> v(num_stacks_ + 1, 0);
171        unsigned int eff_num_stacks = num_stacks_;
172        bool is_found_valid_v = false;
173        do
174        {
175            //Set boundary condition
176            v[0] = 0;
177            v[eff_num_stacks] = vdd_;
178
179            //If the effective number of stacks is 1, no matrix needs to be solved
180            if(eff_num_stacks == 1)
181            {
182                break;
183            }
184
185            //----------------------------------------------------------------------
186            //Setup the tri-matrix
187            //----------------------------------------------------------------------
188            for(int i = 0; i < (int)eff_num_stacks-2; ++i)
189            {
190                a[i + 1] = A;
191                c[i] = C;
192            }
193            for(int i = 0; i < (int)eff_num_stacks-1; ++i)
194            {
195                b[i] = B;
196                d[i] = s2*(vs[i + 1] - vs[i]) + s1*s2*std::log10(ws[i + 1]/ws[i]);
197                if(i == ((int)eff_num_stacks - 2))
198                {
199                    d[i] -= C*vdd_;
200                }
201            }
202            //----------------------------------------------------------------------
203
204            //----------------------------------------------------------------------
205            //Solve the tri-matrix
206            //----------------------------------------------------------------------
207            for(int i = 1; i < (int)eff_num_stacks-1; ++i)
208            {
209                double m = a[i]/b[i - 1];
210                b[i] -= m*c[i - 1];
211                d[i] -= m*d[i - 1];
212            }
213
214            v[eff_num_stacks - 1] = d[eff_num_stacks - 2]/b[eff_num_stacks - 2];
215            for(int i = eff_num_stacks - 3; i >= 0; --i)
216            {
217                v[i + 1] = (d[i] - c[i]*v[i + 2])/b[i];
218            }
219            //----------------------------------------------------------------------
220
221            //Check if the internal voltages are in increasing order
222            is_found_valid_v = true;
223            for(int i = 1; i <= (int)eff_num_stacks; ++i)
224            {
225                //If the ith internal voltage is not in increasing order
226                //(i-1)th transistor is in triode region
227                //Remove the transistors in triode region as it does not exist
228                if(v[i] < v[i - 1])
229                {
230                    is_found_valid_v = false;
231                    eff_num_stacks--;
232                    vs.erase(vs.begin() + i - 1);
233                    ws.erase(ws.begin() + i - 1);
234                    break;
235                }
236            }
237        } while(!is_found_valid_v);
238
239        //Calculate the leakage current of the bottom transistor (first not in triode region)
240        double vgs = vs[0] - v[0];
241        double vds = v[1] - v[0];
242        double leakage_current_factor = vgs/s1 + (vds - vdd_)/s2;
243        //TODO - Check if the leakage current calculate for other transistors is identical
244
245        return leakage_current_factor;
246    }
247    //-------------------------------------------------------------------------
248
249    //-------------------------------------------------------------------------
250    // Wire Related Functions
251    //-------------------------------------------------------------------------
252    bool TechModel::isWireLayerExist(const String& layer_name_) const
253    {
254        std::set<String>::const_iterator it;
255        it = m_available_wire_layers_->find(layer_name_);
256        return (it != m_available_wire_layers_->end());
257    }
258
259    const std::set<String>* TechModel::getAvailableWireLayers() const
260    {
261        return m_available_wire_layers_;
262    }
263
264    double TechModel::calculateWireCapacitance(const String& layer_name_, double width_, double spacing_, double length_) const
265    {
266        // Get technology parameter
267        double min_width = get("Wire->" + layer_name_ + "->MinWidth").toDouble();
268        double min_spacing = get("Wire->" + layer_name_ + "->MinSpacing").toDouble();
269        double metal_thickness = get("Wire->" + layer_name_ + "->MetalThickness").toDouble();
270        double dielec_thickness = get("Wire->" + layer_name_ + "->DielectricThickness").toDouble();
271        double dielec_const = get("Wire->" + layer_name_ + "->DielectricConstant").toDouble();
272
273        ASSERT(width_ >= min_width, "[Error] Wire width must be >= " + (String) min_width + "!");
274        ASSERT(spacing_ >= min_spacing, "[Error] Wire spacing must be >= " + (String) min_spacing + "!");
275        ASSERT(length_ >= 0, "[Error] Wire length must be >= 0!");
276
277        double A, B, C;
278        // Calculate ground capacitance
279        A = width_ / dielec_thickness;
280        B = 2.04*std::pow((spacing_ / (spacing_ + 0.54 * dielec_thickness)), 1.77);
281        C = std::pow((metal_thickness / (metal_thickness + 4.53 * dielec_thickness)), 0.07);
282        double unit_gnd_cap = dielec_const * 8.85e-12 * (A + B * C);
283
284        A = 1.14 * (metal_thickness / spacing_) * std::exp(-4.0 * spacing_ / (spacing_ + 8.01 * dielec_thickness));
285        B = 2.37 * std::pow((width_ / (width_ + 0.31 * spacing_)), 0.28);
286        C = std::pow((dielec_thickness / (dielec_thickness + 8.96 * spacing_)), 0.76) *
287                std::exp(-2.0 * spacing_ / (spacing_ + 6.0 * dielec_thickness));
288        double unit_coupling_cap = dielec_const * 8.85e-12 * (A + B * C);
289
290        double total_cap = 2 * (unit_gnd_cap + unit_coupling_cap) * length_;
291        return total_cap;
292    }
293
294    double TechModel::calculateWireResistance(const String& layer_name_, double width_, double length_) const
295    {
296        // Get technology parameter
297        double min_width = get("Wire->" + layer_name_ + "->MinWidth");
298        //double barrier_thickness = get("Wire->" + layer_name_ + "->BarrierThickness");
299        double resistivity = get("Wire->" + layer_name_ + "->Resistivity");
300        double metal_thickness = get("Wire->" + layer_name_ + "->MetalThickness");
301
302        ASSERT(width_ >= min_width, "[Error] Wire width must be >= " + (String) min_width + "!");
303        ASSERT(length_ >= 0, "[Error] Wire length must be >= 0!");
304
305        // Calculate Rho
306        // double rho = 2.202e-8 + (1.030e-15 / (width_ - 2.0 * barrier_thickness));
307
308        double unit_res = resistivity / (width_ * metal_thickness);
309        //double unit_res = rho / ((width_ - 2.0 * barrier_thickness) * (metal_thickness - barrier_thickness));
310
311        double total_res = unit_res * length_;
312        return total_res;
313    }
314    //-------------------------------------------------------------------------
315
316    TechModel::TechModel(const TechModel& tech_model_)
317        : Config(tech_model_), m_std_cell_lib_(tech_model_.m_std_cell_lib_)
318    {}
319} // namespace DSENT
320
321