1 /* Copyright (c) 2012 Massachusetts Institute of Technology
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 #include "model/std_cells/CellMacros.h"
27 #include "model/std_cells/StdCell.h"
28 #include "model/timing_graph/ElectricalNet.h"
29 #include "model/timing_graph/ElectricalDriver.h"
30 #include "model/timing_graph/ElectricalLoad.h"
34 //-------------------------------------------------------------------------
35 // NOR2 Macro (TODO: Generalize to N-input macro once leakage calc is done)
36 //-------------------------------------------------------------------------
37 void CellMacros::addNor2(StdCell
* cell_
, const String
& name_
,
38 bool sizable_
, bool a1_to_zn_path_
, bool a2_to_zn_path_
,
39 const String
& a1_net_
, const String
& a2_net_
, const String
& zn_net_
)
41 //Create electrical timing model for the nand
42 // Construct loads and drivers
43 cell_
->createLoad(name_
+ "_CgA1");
44 cell_
->createLoad(name_
+ "_CgA2");
45 cell_
->createLoad(name_
+ "_CdZN");
46 cell_
->createDriver(name_
+ "_RonZN", sizable_
);
48 //Get references to loads and drivers
49 ElectricalLoad
* gate_a1_load
= cell_
->getLoad(name_
+ "_CgA1");
50 ElectricalLoad
* gate_a2_load
= cell_
->getLoad(name_
+ "_CgA2");
51 ElectricalLoad
* drain_load
= cell_
->getLoad(name_
+ "_CdZN");
52 ElectricalDriver
* zn_drive
= cell_
->getDriver(name_
+ "_RonZN");
53 ElectricalNet
* a1_net
= cell_
->getNet(a1_net_
);
54 ElectricalNet
* a2_net
= cell_
->getNet(a2_net_
);
55 ElectricalNet
* zn_net
= cell_
->getNet(zn_net_
);
57 //Add loads and drivers to the specified nets
58 a1_net
->addDownstreamNode(gate_a1_load
);
59 a2_net
->addDownstreamNode(gate_a2_load
);
60 zn_net
->addDownstreamNode(drain_load
);
61 if (a1_to_zn_path_
) gate_a1_load
->addDownstreamNode(zn_drive
);
62 if (a2_to_zn_path_
) gate_a2_load
->addDownstreamNode(zn_drive
);
63 zn_drive
->addDownstreamNode(zn_net
);
68 void CellMacros::updateNor2(StdCell
* cell_
, const String
& name_
, double normalized_size_
)
70 ASSERT(normalized_size_
>= 0.0, "[Error] " + cell_
->getInstanceName() +
71 " -> Cannot update a macro with a negative normalized size!");
73 //Grab pointer to tech model
74 const TechModel
* tech
= cell_
->getTechModel();
76 // Get technology parameters
77 double vdd
= tech
->get("Vdd");
78 double gate_cap
= tech
->get("Gate->CapPerWidth");
79 double drain_cap
= tech
->get("Drain->CapPerWidth");
80 double nmos_eff_res
= tech
->get("Nmos->EffResWidth");
81 double pmos_eff_res
= tech
->get("Pmos->EffResWidth");
82 double pmos_eff_res_stack_ratio
= tech
->get("Pmos->EffResStackRatio");
83 double gate_pitch_contacted
= tech
->get("Gate->PitchContacted");
84 double metal1_wire_min_width
= tech
->get("Wire->Metal1->MinWidth");
86 //Calculate number of folds and gate pitches needed
87 unsigned int folds
= (normalized_size_
< 1.0) ? 1 : (unsigned int)ceil(normalized_size_
);
88 cell_
->getGenProperties()->set(name_
+ "_GatePitches", 2 * folds
);
90 //Calculate widths, making sure they are above the minimum width
91 double nmos_width
= std::max(calculateNmosWidth(cell_
, 1, 2, 1) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
92 double pmos_width
= std::max(calculatePmosWidth(cell_
, 1, 2, 2) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
94 //Calculate leakage power for each given input state
95 double leakage_power_00
= vdd
* folds
* 2 * tech
->calculateNmosLeakageCurrent(1, nmos_width
, 0x0);
96 double leakage_power_01
= vdd
* folds
* tech
->calculatePmosLeakageCurrent(2, pmos_width
, ~0x1);
97 double leakage_power_10
= vdd
* folds
* tech
->calculatePmosLeakageCurrent(2, pmos_width
, ~0x2);
98 double leakage_power_11
= vdd
* folds
* tech
->calculatePmosLeakageCurrent(2, pmos_width
, ~0x3);
99 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_00", leakage_power_00
);
100 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_01", leakage_power_01
);
101 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_10", leakage_power_10
);
102 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_11", leakage_power_11
);
104 //Calculate R_on and capacitances
105 double pmos_stack2_balance
= 1.0 + pmos_eff_res_stack_ratio
;
106 double c_g
= (nmos_width
+ pmos_width
) * gate_cap
* folds
;
107 double c_d
= (2 * pmos_width
+ 2 * nmos_width
) * drain_cap
* folds
;
108 double r_on
= (nmos_eff_res
/ nmos_width
+ pmos_stack2_balance
* pmos_eff_res
/ pmos_width
) / (folds
* 2.0);
110 // Estimate the wire cap and add them all at the output
111 double cell_height
= cell_
->getTotalHeight();
112 double wire_width
= metal1_wire_min_width
;
113 double wire_spacing
= gate_pitch_contacted
- metal1_wire_min_width
;
114 double wire_length
= 2.0 * folds
* cell_height
;
115 double wire_cap
= tech
->calculateWireCapacitance("Metal1", wire_width
, wire_spacing
, wire_length
);
117 // Construct equivalent load and drive strength
118 cell_
->getLoad(name_
+ "_CgA1")->setLoadCap(c_g
);
119 cell_
->getLoad(name_
+ "_CgA2")->setLoadCap(c_g
);
120 cell_
->getLoad(name_
+ "_CdZN")->setLoadCap(c_d
+ wire_cap
);
121 cell_
->getDriver(name_
+ "_RonZN")->setOutputRes(r_on
);
123 // Calculate flip energies
124 double zn_flip_energy
= 0.5 * (c_d
+ wire_cap
) * vdd
* vdd
;
125 double a1_flip_energy
= 0.5 * c_g
* vdd
* vdd
;
126 double a2_flip_energy
= 0.5 * c_g
* vdd
* vdd
;
127 cell_
->getGenProperties()->set(name_
+ "_ZN_Flip", zn_flip_energy
);
128 cell_
->getGenProperties()->set(name_
+ "_A1_Flip", a1_flip_energy
);
129 cell_
->getGenProperties()->set(name_
+ "_A2_Flip", a2_flip_energy
);
131 //-------------------------------------------------------------------------
133 //-------------------------------------------------------------------------
134 // NAND2 Macro (TODO: Generalize to N-input macro once leakage calc is done)
135 //-------------------------------------------------------------------------
136 //Adds a NAND2 to the standard cell, normalized to some size
137 void CellMacros::addNand2(StdCell
* cell_
, const String
& name_
,
138 bool sizable_
, bool a1_to_zn_path_
, bool a2_to_zn_path_
,
139 const String
& a1_net_
, const String
& a2_net_
, const String
& zn_net_
)
141 //Create electrical timing model for the nor
142 // Construct loads and drivers
143 cell_
->createLoad(name_
+ "_CgA1");
144 cell_
->createLoad(name_
+ "_CgA2");
145 cell_
->createLoad(name_
+ "_CdZN");
146 cell_
->createDriver(name_
+ "_RonZN", sizable_
);
148 //Get references to loads and drivers
149 ElectricalLoad
* gate_a1_load
= cell_
->getLoad(name_
+ "_CgA1");
150 ElectricalLoad
* gate_a2_load
= cell_
->getLoad(name_
+ "_CgA2");
151 ElectricalLoad
* drain_load
= cell_
->getLoad(name_
+ "_CdZN");
152 ElectricalDriver
* zn_drive
= cell_
->getDriver(name_
+ "_RonZN");
153 ElectricalNet
* a1_net
= cell_
->getNet(a1_net_
);
154 ElectricalNet
* a2_net
= cell_
->getNet(a2_net_
);
155 ElectricalNet
* zn_net
= cell_
->getNet(zn_net_
);
157 a1_net
->addDownstreamNode(gate_a1_load
);
158 a2_net
->addDownstreamNode(gate_a2_load
);
159 zn_net
->addDownstreamNode(drain_load
);
160 if (a1_to_zn_path_
) gate_a1_load
->addDownstreamNode(zn_drive
);
161 if (a2_to_zn_path_
) gate_a2_load
->addDownstreamNode(zn_drive
);
162 zn_drive
->addDownstreamNode(zn_net
);
167 //Updates a NAND2 to to the standard cell, normalized to some size
168 void CellMacros::updateNand2(StdCell
* cell_
, const String
& name_
, double normalized_size_
)
170 ASSERT(normalized_size_
>= 0.0, "[Error] " + cell_
->getInstanceName() +
171 " -> Cannot update a macro with a negative normalized size!");
173 //Grab pointer to tech model
174 const TechModel
* tech
= cell_
->getTechModel();
176 // Get technology parameters
177 double vdd
= tech
->get("Vdd");
178 double gate_cap
= tech
->get("Gate->CapPerWidth");
179 double drain_cap
= tech
->get("Drain->CapPerWidth");
180 double nmos_eff_res
= tech
->get("Nmos->EffResWidth");
181 double pmos_eff_res
= tech
->get("Pmos->EffResWidth");
182 double nmos_eff_res_stack_ratio
= tech
->get("Nmos->EffResStackRatio");
183 double gate_pitch_contacted
= tech
->get("Gate->PitchContacted");
184 double metal1_wire_min_width
= tech
->get("Wire->Metal1->MinWidth");
186 //Calculate number of folds needed
187 unsigned int folds
= (normalized_size_
< 1.0) ? 1 : (unsigned int)ceil(normalized_size_
);
188 cell_
->getGenProperties()->set(name_
+ "_GatePitches", 2 * folds
);
190 //Calculate widths, making sure they are above the minimum width
191 double nmos_width
= std::max(calculateNmosWidth(cell_
, 2, 1, 2) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
192 double pmos_width
= std::max(calculatePmosWidth(cell_
, 2, 1, 1) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
194 // Leakage power calculation
195 double leakage_power_00
= vdd
* folds
* tech
->calculateNmosLeakageCurrent(2, nmos_width
, 0x0);
196 double leakage_power_01
= vdd
* folds
* tech
->calculateNmosLeakageCurrent(2, nmos_width
, 0x1);
197 double leakage_power_10
= vdd
* folds
* tech
->calculateNmosLeakageCurrent(2, nmos_width
, 0x2);
198 double leakage_power_11
= vdd
* folds
* 2 * tech
->calculatePmosLeakageCurrent(1, pmos_width
, ~0x3);
199 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_00", leakage_power_00
);
200 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_01", leakage_power_01
);
201 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_10", leakage_power_10
);
202 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_11", leakage_power_11
);
204 // Get input parameters
205 double nmos_stack2_balance
= 1.0 + nmos_eff_res_stack_ratio
;
208 double c_g
= (nmos_width
+ pmos_width
) * gate_cap
* folds
;
209 double c_d
= (2 * pmos_width
+ 2 * nmos_width
) * drain_cap
* folds
;
210 double r_on
= (nmos_stack2_balance
* nmos_eff_res
/ nmos_width
+ pmos_eff_res
/ pmos_width
) / (folds
* 2.0);
212 // Estimate the wire cap and add them all at the output
213 double cell_height
= cell_
->getTotalHeight();
214 double wire_width
= metal1_wire_min_width
;
215 double wire_spacing
= gate_pitch_contacted
- metal1_wire_min_width
;
216 double wire_length
= 2.0 * folds
* cell_height
;
217 double wire_cap
= tech
->calculateWireCapacitance("Metal1", wire_width
, wire_spacing
, wire_length
);
219 // Construct equivalent load and drive strength
220 cell_
->getLoad(name_
+ "_CgA1")->setLoadCap(c_g
);
221 cell_
->getLoad(name_
+ "_CgA2")->setLoadCap(c_g
);
222 cell_
->getLoad(name_
+ "_CdZN")->setLoadCap(c_d
+ wire_cap
);
223 cell_
->getDriver(name_
+ "_RonZN")->setOutputRes(r_on
);
225 // Calculate flip energies
226 double zn_flip_energy
= 0.5 * (c_d
+ wire_cap
) * vdd
* vdd
;
227 double a1_flip_energy
= 0.5 * c_g
* vdd
* vdd
;
228 double a2_flip_energy
= 0.5 * c_g
* vdd
* vdd
;
229 cell_
->getGenProperties()->set(name_
+ "_ZN_Flip", zn_flip_energy
);
230 cell_
->getGenProperties()->set(name_
+ "_A1_Flip", a1_flip_energy
);
231 cell_
->getGenProperties()->set(name_
+ "_A2_Flip", a2_flip_energy
);
233 //-------------------------------------------------------------------------
235 //-------------------------------------------------------------------------
237 //-------------------------------------------------------------------------
238 //Adds an inverter to the model, normalized to some size
239 void CellMacros::addInverter(StdCell
* cell_
, const String
& name_
,
240 bool sizable_
, bool a_to_zn_path_
,
241 const String
& a_net_
, const String
& zn_net_
)
243 //Create electrical timing model for the inverter
244 // Construct loads and drivers
245 cell_
->createLoad(name_
+ "_CgA");
246 cell_
->createLoad(name_
+ "_CdZN");
247 cell_
->createDriver(name_
+ "_RonZN", sizable_
);
249 //Get references to loads and drivers
250 ElectricalLoad
* gate_load
= cell_
->getLoad(name_
+ "_CgA");
251 ElectricalLoad
* drain_load
= cell_
->getLoad(name_
+ "_CdZN");
252 ElectricalDriver
* out_drive
= cell_
->getDriver(name_
+ "_RonZN");
253 ElectricalNet
* a_net
= cell_
->getNet(a_net_
);
254 ElectricalNet
* zn_net
= cell_
->getNet(zn_net_
);
256 // Setup connectivity of loads and drivers
257 a_net
->addDownstreamNode(gate_load
);
258 if (a_to_zn_path_
) gate_load
->addDownstreamNode(out_drive
);
259 zn_net
->addDownstreamNode(drain_load
);
260 out_drive
->addDownstreamNode(zn_net
);
265 //Updates the numbers of an inverter for some normalized size
266 void CellMacros::updateInverter(StdCell
* cell_
, const String
& name_
, double normalized_size_
)
268 ASSERT(normalized_size_
>= 0.0, "[Error] " + cell_
->getInstanceName() +
269 " -> Cannot update a macro with a negative normalized size!");
271 //Grab pointer to tech model
272 const TechModel
* tech
= cell_
->getTechModel();
274 //Get values from technology library
275 double vdd
= tech
->get("Vdd");
276 double gate_cap
= tech
->get("Gate->CapPerWidth");
277 double drain_cap
= tech
->get("Drain->CapPerWidth");
278 double nmos_eff_res
= tech
->get("Nmos->EffResWidth");
279 double pmos_eff_res
= tech
->get("Pmos->EffResWidth");
280 double gate_pitch_contacted
= tech
->get("Gate->PitchContacted");
281 double metal1_wire_min_width
= tech
->get("Wire->Metal1->MinWidth");
283 //Calculate number of folds needed
284 unsigned int folds
= (normalized_size_
< 1.0) ? 1 : (unsigned int)ceil(normalized_size_
);
285 cell_
->getGenProperties()->set(name_
+ "_GatePitches", folds
);
287 //Calculate widths, making sure they are above the minimum width
288 double nmos_width
= std::max(calculateNmosWidth(cell_
, 1, 1, 1) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
289 double pmos_width
= std::max(calculatePmosWidth(cell_
, 1, 1, 1) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
291 //Calculate leakage power for each given input state
292 double leakage_power_0
= vdd
* folds
* tech
->calculateNmosLeakageCurrent(1, nmos_width
, 0x0);
293 double leakage_power_1
= vdd
* folds
* tech
->calculatePmosLeakageCurrent(1, pmos_width
, ~0x1);
294 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_0", leakage_power_0
);
295 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_1", leakage_power_1
);
298 double c_g
= (nmos_width
+ pmos_width
) * gate_cap
* folds
;
299 double c_d
= (pmos_width
+ nmos_width
) * drain_cap
* folds
;
300 double r_on
= (nmos_eff_res
/ nmos_width
+ pmos_eff_res
/ pmos_width
) / (folds
* 2.0);
302 // Estimate the wire cap and add them all at the output
303 double cell_height
= cell_
->getTotalHeight();
304 double wire_width
= metal1_wire_min_width
;
305 double wire_spacing
= gate_pitch_contacted
- metal1_wire_min_width
;
306 double wire_length
= folds
* cell_height
;
307 double wire_cap
= tech
->calculateWireCapacitance("Metal1", wire_width
, wire_spacing
, wire_length
);
309 // Construct equivalent load and drive strength
310 cell_
->getLoad(name_
+ "_CgA")->setLoadCap(c_g
);
311 cell_
->getLoad(name_
+ "_CdZN")->setLoadCap(c_d
+ wire_cap
);
312 cell_
->getDriver(name_
+ "_RonZN")->setOutputRes(r_on
);
314 // Calculate flip energy (output flip)
315 // Calculate flip energies
316 double zn_flip_energy
= 0.5 * (c_d
+ wire_cap
) * vdd
* vdd
;
317 double a_flip_energy
= 0.5 * c_g
* vdd
* vdd
;
318 cell_
->getGenProperties()->set(name_
+ "_ZN_Flip", zn_flip_energy
);
319 cell_
->getGenProperties()->set(name_
+ "_A_Flip", a_flip_energy
);
323 //-------------------------------------------------------------------------
325 //-------------------------------------------------------------------------
327 //-------------------------------------------------------------------------
328 //Adds a tristated inverter to the model, normalized to some size
329 void CellMacros::addTristate(StdCell
* cell_
, const String
& name_
,
330 bool sizable_
, bool a_to_zn_path_
, bool oe_to_zn_path_
, bool oen_to_zn_path_
,
331 const String
& a_net_
, const String
& oe_net_
, const String
& oen_net_
, const String
& zn_net_
)
333 // Construct loads and drivers
334 cell_
->createLoad(name_
+ "_CgA");
335 cell_
->createLoad(name_
+ "_CgOE");
336 cell_
->createLoad(name_
+ "_CgOEN");
337 cell_
->createLoad(name_
+ "_CdZN");
338 cell_
->createDriver(name_
+ "_RonZN", sizable_
);
340 // Get references to loads, nets and drivers
341 ElectricalLoad
* gate_a_load
= cell_
->getLoad(name_
+ "_CgA");
342 ElectricalLoad
* gate_oe_load
= cell_
->getLoad(name_
+ "_CgOE");
343 ElectricalLoad
* gate_oen_load
= cell_
->getLoad(name_
+ "_CgOEN");
344 ElectricalLoad
* drain_load
= cell_
->getLoad(name_
+ "_CdZN");
345 ElectricalDriver
* out_drive
= cell_
->getDriver(name_
+ "_RonZN");
346 ElectricalNet
* a_net
= cell_
->getNet(a_net_
);
347 ElectricalNet
* oe_net
= cell_
->getNet(oe_net_
);
348 ElectricalNet
* oen_net
= cell_
->getNet(oen_net_
);
349 ElectricalNet
* zn_net
= cell_
->getNet(zn_net_
);
351 // Setup connectivity of loads and drivers
352 a_net
->addDownstreamNode(gate_a_load
);
353 oe_net
->addDownstreamNode(gate_oe_load
);
354 oen_net
->addDownstreamNode(gate_oen_load
);
355 if (a_to_zn_path_
) gate_a_load
->addDownstreamNode(out_drive
);
356 if (oe_to_zn_path_
) gate_oe_load
->addDownstreamNode(out_drive
);
357 if (oen_to_zn_path_
) gate_oen_load
->addDownstreamNode(out_drive
);
358 zn_net
->addDownstreamNode(drain_load
);
359 out_drive
->addDownstreamNode(zn_net
);
364 //Updates the numbers of an inverter for some normalized size
365 void CellMacros::updateTristate(StdCell
* cell_
, const String
& name_
, double normalized_size_
)
367 ASSERT(normalized_size_
>= 0.0, "[Error] " + cell_
->getInstanceName() +
368 " -> Cannot update a macro with a negative normalized size!");
370 //Grab pointer to tech model
371 const TechModel
* tech
= cell_
->getTechModel();
373 //Get values from technology library
374 double vdd
= tech
->get("Vdd");
375 double gate_cap
= tech
->get("Gate->CapPerWidth");
376 double drain_cap
= tech
->get("Drain->CapPerWidth");
377 double nmos_eff_res
= tech
->get("Nmos->EffResWidth");
378 double pmos_eff_res
= tech
->get("Pmos->EffResWidth");
379 double pmos_eff_res_stack_ratio
= tech
->get("Pmos->EffResStackRatio");
380 double nmos_eff_res_stack_ratio
= tech
->get("Nmos->EffResStackRatio");
381 double gate_pitch_contacted
= tech
->get("Gate->PitchContacted");
382 double metal1_wire_min_width
= tech
->get("Wire->Metal1->MinWidth");
384 //Calculate number of folds and gate pitches needed
385 unsigned int folds
= (normalized_size_
< 1.0) ? 1 : (unsigned int)ceil(normalized_size_
);
386 cell_
->getGenProperties()->set(name_
+ "_GatePitches", 2 * folds
);
388 //Calculate widths, making sure they are above the minimum width
389 double nmos_width
= std::max(calculateNmosWidth(cell_
, 2, 2, 2) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
390 double pmos_width
= std::max(calculatePmosWidth(cell_
, 2, 2, 2) * normalized_size_
/ folds
, (double) tech
->get("Gate->MinWidth"));
392 //Calculate leakage power for each given input state
393 //if output_enable = 0, then it is possible that the PMOS may leak (if output = 0),
394 //or the NMOS will leak (if output = 1)
397 double leakage_power_010_0
= vdd
* folds
* tech
->calculatePmosLeakageCurrent(2, pmos_width
, ~0x2);
398 double leakage_power_010_1
= vdd
* folds
* tech
->calculateNmosLeakageCurrent(2, nmos_width
, 0x0);
399 double leakage_power_011_0
= vdd
* folds
* tech
->calculatePmosLeakageCurrent(2, pmos_width
, ~0x3);
400 double leakage_power_011_1
= vdd
* folds
* tech
->calculateNmosLeakageCurrent(2, nmos_width
, 0x1);
401 double leakage_power_100_1
= vdd
* folds
* tech
->calculateNmosLeakageCurrent(2, nmos_width
, 0x2);
402 double leakage_power_101_0
= vdd
* folds
* tech
->calculatePmosLeakageCurrent(2, pmos_width
, ~0x1);
403 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_010_0", leakage_power_010_0
);
404 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_010_1", leakage_power_010_1
);
405 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_011_0", leakage_power_011_0
);
406 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_011_1", leakage_power_011_1
);
407 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_100_1", leakage_power_100_1
);
408 cell_
->getGenProperties()->set(name_
+ "_LeakagePower_101_0", leakage_power_101_0
);
410 //Caculate stack balance
411 double pmos_stack2_balance
= 1.0 + pmos_eff_res_stack_ratio
;
412 double nmos_stack2_balance
= 1.0 + nmos_eff_res_stack_ratio
;
415 double c_g_a
= (nmos_width
+ pmos_width
) * gate_cap
* folds
;
416 double c_g_oe
= nmos_width
* gate_cap
* folds
;
417 double c_g_oen
= pmos_width
* gate_cap
* folds
;
418 double c_d
= (2 * pmos_width
+ 2 * nmos_width
) * drain_cap
* folds
;
419 double r_on
= (nmos_stack2_balance
* nmos_eff_res
/ nmos_width
+ pmos_stack2_balance
* pmos_eff_res
/ pmos_width
) / (folds
* 2.0);
421 // Estimate the wire cap and add them all at the output
422 double cell_height
= cell_
->getTotalHeight();
423 double wire_width
= metal1_wire_min_width
;
424 double wire_spacing
= gate_pitch_contacted
- metal1_wire_min_width
;
425 double wire_length
= 2.0 * folds
* cell_height
;
426 double wire_cap
= tech
->calculateWireCapacitance("Metal1", wire_width
, wire_spacing
, wire_length
);
428 // Construct equivalent load and drive strength
429 cell_
->getLoad(name_
+ "_CgA")->setLoadCap(c_g_a
);
430 cell_
->getLoad(name_
+ "_CgOE")->setLoadCap(c_g_oe
);
431 cell_
->getLoad(name_
+ "_CgOEN")->setLoadCap(c_g_oen
);
432 cell_
->getLoad(name_
+ "_CdZN")->setLoadCap(c_d
+ wire_cap
);
433 cell_
->getDriver(name_
+ "_RonZN")->setOutputRes(r_on
);
435 // Calculate flip energy (output flip)
436 double zn_flip_energy
= 0.5 * (c_d
+ wire_cap
) * vdd
* vdd
;
437 double a_flip_energy
= 0.5 * c_g_a
* vdd
* vdd
;
438 double oe_flip_energy
= 0.5 * c_g_oe
* vdd
* vdd
;
439 double oen_flip_energy
= 0.5 * c_g_oen
* vdd
* vdd
;
440 cell_
->getGenProperties()->set(name_
+ "_ZN_Flip", zn_flip_energy
);
441 cell_
->getGenProperties()->set(name_
+ "_A_Flip", a_flip_energy
);
442 cell_
->getGenProperties()->set(name_
+ "_OE_Flip", oe_flip_energy
);
443 cell_
->getGenProperties()->set(name_
+ "_OEN_Flip", oen_flip_energy
);
446 //-------------------------------------------------------------------------
449 //-------------------------------------------------------------------------
451 //-------------------------------------------------------------------------
452 //Returns the width of NMOS transistors, given the NMOS and PMOS stacking
453 double CellMacros::calculateNmosWidth(const StdCell
* cell_
, unsigned int max_stacked_nmos_
, unsigned int max_stacked_pmos_
, unsigned int current_stacked_nmos_
)
455 //Grab pointer to tech model
456 const TechModel
* tech
= cell_
->getTechModel();
458 double nmos_eff_res_stack_ratio
= tech
->get("Nmos->EffResStackRatio");
459 double pmos_eff_res_stack_ratio
= tech
->get("Pmos->EffResStackRatio");
461 double nmos_stack_balance
= 1.0 + nmos_eff_res_stack_ratio
* (double) (max_stacked_nmos_
- 1);
462 double pmos_stack_balance
= 1.0 + pmos_eff_res_stack_ratio
* (double) (max_stacked_pmos_
- 1);
463 double current_nmos_stack_balance
= 1.0 + nmos_eff_res_stack_ratio
* (double) (current_stacked_nmos_
- 1);
465 double pn_ratio
= cell_
->getPToNRatio();
466 double active_height
= cell_
->getActiveHeight();
468 //Calculate the width of the current device
469 double nmos_width
= active_height
* current_nmos_stack_balance
/ (nmos_stack_balance
+ pn_ratio
* pmos_stack_balance
);
474 //Returns the width of PMOS transistors, given the NMOS and PMOS stacking
475 double CellMacros::calculatePmosWidth(const StdCell
* cell_
, unsigned int max_stacked_nmos_
, unsigned int max_stacked_pmos_
, unsigned int current_stacked_pmos_
)
477 //Grab pointer to tech model
478 const TechModel
* tech
= cell_
->getTechModel();
480 double nmos_eff_res_stack_ratio
= tech
->get("Nmos->EffResStackRatio");
481 double pmos_eff_res_stack_ratio
= tech
->get("Pmos->EffResStackRatio");
483 double nmos_stack_balance
= 1.0 + nmos_eff_res_stack_ratio
* (double) (max_stacked_nmos_
- 1);
484 double pmos_stack_balance
= 1.0 + pmos_eff_res_stack_ratio
* (double) (max_stacked_pmos_
- 1);
485 double current_pmos_stack_balance
= 1.0 + pmos_eff_res_stack_ratio
* (double) (current_stacked_pmos_
- 1);
487 double pn_ratio
= cell_
->getPToNRatio();
488 double active_height
= cell_
->getActiveHeight();
490 //Calculate the width of the current device
491 double pmos_width
= active_height
* current_pmos_stack_balance
* pn_ratio
/ (nmos_stack_balance
+ pn_ratio
* pmos_stack_balance
);
495 //-------------------------------------------------------------------------