CellMacros.cc revision 10447
1#include "model/std_cells/CellMacros.h"
2
3#include <cmath>
4#include <vector>
5
6#include "model/std_cells/StdCell.h"
7#include "model/timing_graph/ElectricalNet.h"
8#include "model/timing_graph/ElectricalDriver.h"
9#include "model/timing_graph/ElectricalLoad.h"
10
11namespace DSENT
12{
13    //-------------------------------------------------------------------------
14    // NOR2 Macro (TODO: Generalize to N-input macro once leakage calc is done)
15    //-------------------------------------------------------------------------
16    void CellMacros::addNor2(StdCell* cell_, const String& name_,
17        bool sizable_, bool a1_to_zn_path_, bool a2_to_zn_path_,
18        const String& a1_net_, const String& a2_net_, const String& zn_net_)
19    {
20        //Create electrical timing model for the nand
21        // Construct loads and drivers
22        cell_->createLoad(name_ + "_CgA1");
23        cell_->createLoad(name_ + "_CgA2");
24        cell_->createLoad(name_ + "_CdZN");
25        cell_->createDriver(name_ + "_RonZN", sizable_);
26
27        //Get references to loads and drivers
28        ElectricalLoad* gate_a1_load = cell_->getLoad(name_ + "_CgA1");
29        ElectricalLoad* gate_a2_load = cell_->getLoad(name_ + "_CgA2");
30        ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN");
31        ElectricalDriver* zn_drive = cell_->getDriver(name_ + "_RonZN");
32        ElectricalNet* a1_net = cell_->getNet(a1_net_);
33        ElectricalNet* a2_net = cell_->getNet(a2_net_);
34        ElectricalNet* zn_net = cell_->getNet(zn_net_);
35
36        //Add loads and drivers to the specified nets
37        a1_net->addDownstreamNode(gate_a1_load);
38        a2_net->addDownstreamNode(gate_a2_load);
39        zn_net->addDownstreamNode(drain_load);
40        if (a1_to_zn_path_) gate_a1_load->addDownstreamNode(zn_drive);
41        if (a2_to_zn_path_) gate_a2_load->addDownstreamNode(zn_drive);
42        zn_drive->addDownstreamNode(zn_net);
43
44        return;
45    }
46
47    void CellMacros::updateNor2(StdCell* cell_, const String& name_, double normalized_size_)
48    {
49        ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() +
50            " -> Cannot update a macro with a negative normalized size!");
51
52        //Grab pointer to tech model
53        const TechModel* tech = cell_->getTechModel();
54
55        // Get technology parameters
56        double vdd = tech->get("Vdd");
57        double gate_cap = tech->get("Gate->CapPerWidth");
58        double drain_cap = tech->get("Drain->CapPerWidth");
59        double nmos_eff_res = tech->get("Nmos->EffResWidth");
60        double pmos_eff_res = tech->get("Pmos->EffResWidth");
61        double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio");
62        double gate_pitch_contacted = tech->get("Gate->PitchContacted");
63        double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth");
64
65        //Calculate number of folds and gate pitches needed
66        unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_);
67        cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds);
68
69        //Calculate widths, making sure they are above the minimum width
70        double nmos_width = std::max(calculateNmosWidth(cell_, 1, 2, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
71        double pmos_width = std::max(calculatePmosWidth(cell_, 1, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
72
73        //Calculate leakage power for each given input state
74        double leakage_power_00 = vdd * folds * 2 * tech->calculateNmosLeakageCurrent(1, nmos_width, 0x0);
75        double leakage_power_01 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x1);
76        double leakage_power_10 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x2);
77        double leakage_power_11 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x3);
78        cell_->getGenProperties()->set(name_ + "_LeakagePower_00", leakage_power_00);
79        cell_->getGenProperties()->set(name_ + "_LeakagePower_01", leakage_power_01);
80        cell_->getGenProperties()->set(name_ + "_LeakagePower_10", leakage_power_10);
81        cell_->getGenProperties()->set(name_ + "_LeakagePower_11", leakage_power_11);
82
83        //Calculate R_on and capacitances
84        double pmos_stack2_balance = 1.0 + pmos_eff_res_stack_ratio;
85        double c_g = (nmos_width + pmos_width) * gate_cap * folds;
86        double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds;
87        double r_on = (nmos_eff_res / nmos_width + pmos_stack2_balance * pmos_eff_res / pmos_width) / (folds * 2.0);
88
89        // Estimate the wire cap and add them all at the output
90        double cell_height = cell_->getTotalHeight();
91        double wire_width = metal1_wire_min_width;
92        double wire_spacing = gate_pitch_contacted - metal1_wire_min_width;
93        double wire_length = 2.0 * folds * cell_height;
94        double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length);
95
96        // Construct equivalent load and drive strength
97        cell_->getLoad(name_ + "_CgA1")->setLoadCap(c_g);
98        cell_->getLoad(name_ + "_CgA2")->setLoadCap(c_g);
99        cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap);
100        cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on);
101
102        // Calculate flip energies
103        double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd;
104        double a1_flip_energy = 0.5 * c_g * vdd * vdd;
105        double a2_flip_energy = 0.5 * c_g * vdd * vdd;
106        cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy);
107        cell_->getGenProperties()->set(name_ + "_A1_Flip", a1_flip_energy);
108        cell_->getGenProperties()->set(name_ + "_A2_Flip", a2_flip_energy);
109    }
110    //-------------------------------------------------------------------------
111
112    //-------------------------------------------------------------------------
113    // NAND2 Macro (TODO: Generalize to N-input macro once leakage calc is done)
114    //-------------------------------------------------------------------------
115    //Adds a NAND2 to the standard cell, normalized to some size
116    void CellMacros::addNand2(StdCell* cell_, const String& name_,
117        bool sizable_, bool a1_to_zn_path_, bool a2_to_zn_path_,
118        const String& a1_net_, const String& a2_net_, const String& zn_net_)
119    {
120        //Create electrical timing model for the nor
121        // Construct loads and drivers
122        cell_->createLoad(name_ + "_CgA1");
123        cell_->createLoad(name_ + "_CgA2");
124        cell_->createLoad(name_ + "_CdZN");
125        cell_->createDriver(name_ + "_RonZN", sizable_);
126
127        //Get references to loads and drivers
128        ElectricalLoad* gate_a1_load = cell_->getLoad(name_ + "_CgA1");
129        ElectricalLoad* gate_a2_load = cell_->getLoad(name_ + "_CgA2");
130        ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN");
131        ElectricalDriver* zn_drive = cell_->getDriver(name_ + "_RonZN");
132        ElectricalNet* a1_net = cell_->getNet(a1_net_);
133        ElectricalNet* a2_net = cell_->getNet(a2_net_);
134        ElectricalNet* zn_net = cell_->getNet(zn_net_);
135
136        a1_net->addDownstreamNode(gate_a1_load);
137        a2_net->addDownstreamNode(gate_a2_load);
138        zn_net->addDownstreamNode(drain_load);
139        if (a1_to_zn_path_) gate_a1_load->addDownstreamNode(zn_drive);
140        if (a2_to_zn_path_) gate_a2_load->addDownstreamNode(zn_drive);
141        zn_drive->addDownstreamNode(zn_net);
142
143        return;
144    }
145
146    //Updates a NAND2 to to the standard cell, normalized to some size
147    void CellMacros::updateNand2(StdCell* cell_, const String& name_, double normalized_size_)
148    {
149        ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() +
150            " -> Cannot update a macro with a negative normalized size!");
151
152        //Grab pointer to tech model
153        const TechModel* tech = cell_->getTechModel();
154
155        // Get technology parameters
156        double vdd = tech->get("Vdd");
157        double gate_cap = tech->get("Gate->CapPerWidth");
158        double drain_cap = tech->get("Drain->CapPerWidth");
159        double nmos_eff_res = tech->get("Nmos->EffResWidth");
160        double pmos_eff_res = tech->get("Pmos->EffResWidth");
161        double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio");
162        double gate_pitch_contacted = tech->get("Gate->PitchContacted");
163        double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth");
164
165        //Calculate number of folds needed
166        unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_);
167        cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds);
168
169        //Calculate widths, making sure they are above the minimum width
170        double nmos_width = std::max(calculateNmosWidth(cell_, 2, 1, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
171        double pmos_width = std::max(calculatePmosWidth(cell_, 2, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
172
173        // Leakage power calculation
174        double leakage_power_00 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x0);
175        double leakage_power_01 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x1);
176        double leakage_power_10 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x2);
177        double leakage_power_11 = vdd * folds * 2 * tech->calculatePmosLeakageCurrent(1, pmos_width, ~0x3);
178        cell_->getGenProperties()->set(name_ + "_LeakagePower_00", leakage_power_00);
179        cell_->getGenProperties()->set(name_ + "_LeakagePower_01", leakage_power_01);
180        cell_->getGenProperties()->set(name_ + "_LeakagePower_10", leakage_power_10);
181        cell_->getGenProperties()->set(name_ + "_LeakagePower_11", leakage_power_11);
182
183        // Get input parameters
184        double nmos_stack2_balance = 1.0 + nmos_eff_res_stack_ratio;
185
186        //Calculate caps
187        double c_g = (nmos_width + pmos_width) * gate_cap * folds;
188        double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds;
189        double r_on = (nmos_stack2_balance * nmos_eff_res / nmos_width + pmos_eff_res / pmos_width) / (folds * 2.0);
190
191        // Estimate the wire cap and add them all at the output
192        double cell_height = cell_->getTotalHeight();
193        double wire_width = metal1_wire_min_width;
194        double wire_spacing = gate_pitch_contacted - metal1_wire_min_width;
195        double wire_length = 2.0 * folds * cell_height;
196        double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length);
197
198        // Construct equivalent load and drive strength
199        cell_->getLoad(name_ + "_CgA1")->setLoadCap(c_g);
200        cell_->getLoad(name_ + "_CgA2")->setLoadCap(c_g);
201        cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap);
202        cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on);
203
204        // Calculate flip energies
205        double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd;
206        double a1_flip_energy = 0.5 * c_g * vdd * vdd;
207        double a2_flip_energy = 0.5 * c_g * vdd * vdd;
208        cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy);
209        cell_->getGenProperties()->set(name_ + "_A1_Flip", a1_flip_energy);
210        cell_->getGenProperties()->set(name_ + "_A2_Flip", a2_flip_energy);
211    }
212    //-------------------------------------------------------------------------
213
214    //-------------------------------------------------------------------------
215    // INV Macro
216    //-------------------------------------------------------------------------
217    //Adds an inverter to the model, normalized to some size
218    void CellMacros::addInverter(StdCell* cell_, const String& name_,
219        bool sizable_, bool a_to_zn_path_,
220        const String& a_net_, const String& zn_net_)
221    {
222        //Create electrical timing model for the inverter
223        // Construct loads and drivers
224        cell_->createLoad(name_ + "_CgA");
225        cell_->createLoad(name_ + "_CdZN");
226        cell_->createDriver(name_ + "_RonZN", sizable_);
227
228        //Get references to loads and drivers
229        ElectricalLoad* gate_load = cell_->getLoad(name_ + "_CgA");
230        ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN");
231        ElectricalDriver* out_drive = cell_->getDriver(name_ + "_RonZN");
232        ElectricalNet* a_net = cell_->getNet(a_net_);
233        ElectricalNet* zn_net = cell_->getNet(zn_net_);
234
235        // Setup connectivity of loads and drivers
236        a_net->addDownstreamNode(gate_load);
237        if (a_to_zn_path_) gate_load->addDownstreamNode(out_drive);
238        zn_net->addDownstreamNode(drain_load);
239        out_drive->addDownstreamNode(zn_net);
240
241        return;
242    }
243
244    //Updates the numbers of an inverter for some normalized size
245    void CellMacros::updateInverter(StdCell* cell_, const String& name_, double normalized_size_)
246    {
247        ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() +
248            " -> Cannot update a macro with a negative normalized size!");
249
250        //Grab pointer to tech model
251        const TechModel* tech = cell_->getTechModel();
252
253        //Get values from technology library
254        double vdd = tech->get("Vdd");
255        double gate_cap = tech->get("Gate->CapPerWidth");
256        double drain_cap = tech->get("Drain->CapPerWidth");
257        double nmos_eff_res = tech->get("Nmos->EffResWidth");
258        double pmos_eff_res = tech->get("Pmos->EffResWidth");
259        double gate_pitch_contacted = tech->get("Gate->PitchContacted");
260        double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth");
261
262        //Calculate number of folds needed
263        unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_);
264        cell_->getGenProperties()->set(name_ + "_GatePitches", folds);
265
266        //Calculate widths, making sure they are above the minimum width
267        double nmos_width = std::max(calculateNmosWidth(cell_, 1, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
268        double pmos_width = std::max(calculatePmosWidth(cell_, 1, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
269
270        //Calculate leakage power for each given input state
271        double leakage_power_0 = vdd * folds * tech->calculateNmosLeakageCurrent(1, nmos_width, 0x0);
272        double leakage_power_1 = vdd * folds * tech->calculatePmosLeakageCurrent(1, pmos_width, ~0x1);
273        cell_->getGenProperties()->set(name_ + "_LeakagePower_0", leakage_power_0);
274        cell_->getGenProperties()->set(name_ + "_LeakagePower_1", leakage_power_1);
275
276        //Calculate caps
277        double c_g = (nmos_width + pmos_width) * gate_cap * folds;
278        double c_d = (pmos_width + nmos_width) * drain_cap * folds;
279        double r_on = (nmos_eff_res / nmos_width + pmos_eff_res / pmos_width) / (folds * 2.0);
280
281        // Estimate the wire cap and add them all at the output
282        double cell_height = cell_->getTotalHeight();
283        double wire_width = metal1_wire_min_width;
284        double wire_spacing = gate_pitch_contacted - metal1_wire_min_width;
285        double wire_length = folds * cell_height;
286        double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length);
287
288        // Construct equivalent load and drive strength
289        cell_->getLoad(name_ + "_CgA")->setLoadCap(c_g);
290        cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap);
291        cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on);
292
293        // Calculate flip energy (output flip)
294        // Calculate flip energies
295        double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd;
296        double a_flip_energy = 0.5 * c_g * vdd * vdd;
297        cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy);
298        cell_->getGenProperties()->set(name_ + "_A_Flip", a_flip_energy);
299
300        return;
301    }
302    //-------------------------------------------------------------------------
303
304    //-------------------------------------------------------------------------
305    // INVZ Macro
306    //-------------------------------------------------------------------------
307    //Adds a tristated inverter to the model, normalized to some size
308    void CellMacros::addTristate(StdCell* cell_, const String& name_,
309        bool sizable_, bool a_to_zn_path_, bool oe_to_zn_path_, bool oen_to_zn_path_,
310        const String& a_net_, const String& oe_net_, const String& oen_net_, const String& zn_net_)
311    {
312        // Construct loads and drivers
313        cell_->createLoad(name_ + "_CgA");
314        cell_->createLoad(name_ + "_CgOE");
315        cell_->createLoad(name_ + "_CgOEN");
316        cell_->createLoad(name_ + "_CdZN");
317        cell_->createDriver(name_ + "_RonZN", sizable_);
318
319        // Get references to loads, nets and drivers
320        ElectricalLoad* gate_a_load = cell_->getLoad(name_ + "_CgA");
321        ElectricalLoad* gate_oe_load = cell_->getLoad(name_ + "_CgOE");
322        ElectricalLoad* gate_oen_load = cell_->getLoad(name_ + "_CgOEN");
323        ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN");
324        ElectricalDriver* out_drive = cell_->getDriver(name_ + "_RonZN");
325        ElectricalNet* a_net = cell_->getNet(a_net_);
326        ElectricalNet* oe_net = cell_->getNet(oe_net_);
327        ElectricalNet* oen_net = cell_->getNet(oen_net_);
328        ElectricalNet* zn_net = cell_->getNet(zn_net_);
329
330        // Setup connectivity of loads and drivers
331        a_net->addDownstreamNode(gate_a_load);
332        oe_net->addDownstreamNode(gate_oe_load);
333        oen_net->addDownstreamNode(gate_oen_load);
334        if (a_to_zn_path_) gate_a_load->addDownstreamNode(out_drive);
335        if (oe_to_zn_path_) gate_oe_load->addDownstreamNode(out_drive);
336        if (oen_to_zn_path_) gate_oen_load->addDownstreamNode(out_drive);
337        zn_net->addDownstreamNode(drain_load);
338        out_drive->addDownstreamNode(zn_net);
339
340        return;
341    }
342
343    //Updates the numbers of an inverter for some normalized size
344    void CellMacros::updateTristate(StdCell* cell_, const String& name_, double normalized_size_)
345    {
346        ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() +
347            " -> Cannot update a macro with a negative normalized size!");
348
349        //Grab pointer to tech model
350        const TechModel* tech = cell_->getTechModel();
351
352        //Get values from technology library
353        double vdd = tech->get("Vdd");
354        double gate_cap = tech->get("Gate->CapPerWidth");
355        double drain_cap = tech->get("Drain->CapPerWidth");
356        double nmos_eff_res = tech->get("Nmos->EffResWidth");
357        double pmos_eff_res = tech->get("Pmos->EffResWidth");
358        double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio");
359        double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio");
360        double gate_pitch_contacted = tech->get("Gate->PitchContacted");
361        double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth");
362
363        //Calculate number of folds and gate pitches needed
364        unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_);
365        cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds);
366
367        //Calculate widths, making sure they are above the minimum width
368        double nmos_width = std::max(calculateNmosWidth(cell_, 2, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
369        double pmos_width = std::max(calculatePmosWidth(cell_, 2, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth"));
370
371        //Calculate leakage power for each given input state
372        //if output_enable = 0, then it is possible that the PMOS may leak (if output = 0),
373        //or the NMOS will leak (if output = 1)
374
375        //OE OEN A _ ZN
376        double leakage_power_010_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x2);
377        double leakage_power_010_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x0);
378        double leakage_power_011_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x3);
379        double leakage_power_011_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x1);
380        double leakage_power_100_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x2);
381        double leakage_power_101_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x1);
382        cell_->getGenProperties()->set(name_ + "_LeakagePower_010_0", leakage_power_010_0);
383        cell_->getGenProperties()->set(name_ + "_LeakagePower_010_1", leakage_power_010_1);
384        cell_->getGenProperties()->set(name_ + "_LeakagePower_011_0", leakage_power_011_0);
385        cell_->getGenProperties()->set(name_ + "_LeakagePower_011_1", leakage_power_011_1);
386        cell_->getGenProperties()->set(name_ + "_LeakagePower_100_1", leakage_power_100_1);
387        cell_->getGenProperties()->set(name_ + "_LeakagePower_101_0", leakage_power_101_0);
388
389        //Caculate stack balance
390        double pmos_stack2_balance = 1.0 + pmos_eff_res_stack_ratio;
391        double nmos_stack2_balance = 1.0 + nmos_eff_res_stack_ratio;
392
393        //Calculate caps
394        double c_g_a = (nmos_width + pmos_width) * gate_cap * folds;
395        double c_g_oe = nmos_width * gate_cap * folds;
396        double c_g_oen = pmos_width * gate_cap * folds;
397        double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds;
398        double r_on = (nmos_stack2_balance * nmos_eff_res / nmos_width + pmos_stack2_balance * pmos_eff_res / pmos_width) / (folds * 2.0);
399
400        // Estimate the wire cap and add them all at the output
401        double cell_height = cell_->getTotalHeight();
402        double wire_width = metal1_wire_min_width;
403        double wire_spacing = gate_pitch_contacted - metal1_wire_min_width;
404        double wire_length = 2.0 * folds * cell_height;
405        double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length);
406
407        // Construct equivalent load and drive strength
408        cell_->getLoad(name_ + "_CgA")->setLoadCap(c_g_a);
409        cell_->getLoad(name_ + "_CgOE")->setLoadCap(c_g_oe);
410        cell_->getLoad(name_ + "_CgOEN")->setLoadCap(c_g_oen);
411        cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap);
412        cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on);
413
414        // Calculate flip energy (output flip)
415        double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd;
416        double a_flip_energy = 0.5 * c_g_a * vdd * vdd;
417        double oe_flip_energy = 0.5 * c_g_oe * vdd * vdd;
418        double oen_flip_energy = 0.5 * c_g_oen * vdd * vdd;
419        cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy);
420        cell_->getGenProperties()->set(name_ + "_A_Flip", a_flip_energy);
421        cell_->getGenProperties()->set(name_ + "_OE_Flip", oe_flip_energy);
422        cell_->getGenProperties()->set(name_ + "_OEN_Flip", oen_flip_energy);
423        return;
424    }
425    //-------------------------------------------------------------------------
426
427
428    //-------------------------------------------------------------------------
429    // Helper Functions
430    //-------------------------------------------------------------------------
431    //Returns the width of NMOS transistors, given the NMOS and PMOS stacking
432    double CellMacros::calculateNmosWidth(const StdCell* cell_, unsigned int max_stacked_nmos_, unsigned int max_stacked_pmos_, unsigned int current_stacked_nmos_)
433    {
434        //Grab pointer to tech model
435        const TechModel* tech = cell_->getTechModel();
436
437        double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio");
438        double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio");
439
440        double nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (max_stacked_nmos_ - 1);
441        double pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (max_stacked_pmos_ - 1);
442        double current_nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (current_stacked_nmos_ - 1);
443
444        double pn_ratio = cell_->getPToNRatio();
445        double active_height = cell_->getActiveHeight();
446
447        //Calculate the width of the current device
448        double nmos_width = active_height * current_nmos_stack_balance / (nmos_stack_balance + pn_ratio * pmos_stack_balance);
449
450        return nmos_width;
451    }
452
453    //Returns the width of PMOS transistors, given the NMOS and PMOS stacking
454    double CellMacros::calculatePmosWidth(const StdCell* cell_, unsigned int max_stacked_nmos_, unsigned int max_stacked_pmos_, unsigned int current_stacked_pmos_)
455    {
456        //Grab pointer to tech model
457        const TechModel* tech = cell_->getTechModel();
458
459        double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio");
460        double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio");
461
462        double nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (max_stacked_nmos_ - 1);
463        double pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (max_stacked_pmos_ - 1);
464        double current_pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (current_stacked_pmos_ - 1);
465
466        double pn_ratio = cell_->getPToNRatio();
467        double active_height = cell_->getActiveHeight();
468
469        //Calculate the width of the current device
470        double pmos_width = active_height * current_pmos_stack_balance * pn_ratio / (nmos_stack_balance + pn_ratio * pmos_stack_balance);
471
472        return pmos_width;
473    }
474    //-------------------------------------------------------------------------
475
476} // namespace DSENT
477
478