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/OR2.h"
26 #include "model/PortInfo.h"
27 #include "model/TransitionInfo.h"
28 #include "model/EventInfo.h"
29 #include "model/std_cells/StdCellLib.h"
30 #include "model/std_cells/CellMacros.h"
31 #include "model/timing_graph/ElectricalNet.h"
32 #include "model/timing_graph/ElectricalDriver.h"
33 #include "model/timing_graph/ElectricalLoad.h"
34 #include "model/timing_graph/ElectricalDelay.h"
40 OR2::OR2(const String
& instance_name_
, const TechModel
* tech_model_
)
41 : StdCell(instance_name_
, tech_model_
)
49 void OR2::initProperties()
54 void OR2::constructModel()
58 createOutputPort("Y");
62 createDelay("A_to_Y_delay");
63 createDelay("B_to_Y_delay");
64 createDriver("Y_Ron", true);
66 ElectricalLoad
* a_cap
= getLoad("A_Cap");
67 ElectricalLoad
* b_cap
= getLoad("B_Cap");
68 ElectricalDelay
* a_to_y_delay
= getDelay("A_to_Y_delay");
69 ElectricalDelay
* b_to_y_delay
= getDelay("B_to_Y_delay");
70 ElectricalDriver
* y_ron
= getDriver("Y_Ron");
72 getNet("A")->addDownstreamNode(a_cap
);
73 getNet("B")->addDownstreamNode(b_cap
);
74 a_cap
->addDownstreamNode(a_to_y_delay
);
75 b_cap
->addDownstreamNode(b_to_y_delay
);
76 a_to_y_delay
->addDownstreamNode(y_ron
);
77 b_to_y_delay
->addDownstreamNode(y_ron
);
78 y_ron
->addDownstreamNode(getNet("Y"));
81 // Create NDD Power result
82 createElectricalAtomicResults();
83 // Create OR Event Energy Result
84 createElectricalEventAtomicResult("OR2");
86 getEventInfo("Idle")->setStaticTransitionInfos();
91 void OR2::updateModel()
94 double drive_strength
= getDrivingStrength();
95 Map
<double>* cache
= getTechModel()->getStdCellLib()->getStdCellCache();
97 // Standard cell cache string
98 const String
& cell_name
= "OR2_X" + (String
) drive_strength
;
100 // Get timing parameters
101 getLoad("A_Cap")->setLoadCap(cache
->get(cell_name
+ "->Cap->A"));
102 getLoad("B_Cap")->setLoadCap(cache
->get(cell_name
+ "->Cap->B"));
103 getDelay("A_to_Y_delay")->setDelay(cache
->get(cell_name
+ "->Delay->A_to_Y"));
104 getDelay("B_to_Y_delay")->setDelay(cache
->get(cell_name
+ "->Delay->B_to_Y"));
105 getDriver("Y_Ron")->setOutputRes(cache
->get(cell_name
+ "->DriveRes->Y"));
108 getAreaResult("Active")->setValue(cache
->get(cell_name
+ "->ActiveArea"));
109 getAreaResult("Metal1Wire")->setValue(cache
->get(cell_name
+ "->ActiveArea"));
114 void OR2::evaluateModel()
122 double drive_strength
= getDrivingStrength();
123 Map
<double>* cache
= getTechModel()->getStdCellLib()->getStdCellCache();
125 // Stadard cell cache string
126 const String
& cell_name
= "OR2_X" + (String
) drive_strength
;
128 // Propagate the transition info and get the 0->1 transtion count
129 propagateTransitionInfo();
130 double P_A
= getInputPort("A")->getTransitionInfo().getProbability1();
131 double P_B
= getInputPort("B")->getTransitionInfo().getProbability1();
132 double Y_num_trans_01
= getOutputPort("Y")->getTransitionInfo().getNumberTransitions01();
136 leakage
+= cache
->get(cell_name
+ "->Leakage->!A!B") * (1 - P_A
) * (1 - P_B
);
137 leakage
+= cache
->get(cell_name
+ "->Leakage->!AB") * (1 - P_A
) * P_B
;
138 leakage
+= cache
->get(cell_name
+ "->Leakage->A!B") * P_A
* (1 - P_B
);
139 leakage
+= cache
->get(cell_name
+ "->Leakage->AB") * P_A
* P_B
;
140 getNddPowerResult("Leakage")->setValue(leakage
);
143 double vdd
= getTechModel()->get("Vdd");
146 double y_b_cap
= cache
->get(cell_name
+ "->Cap->Y_b");
147 double y_cap
= cache
->get(cell_name
+ "->Cap->Y");
148 double y_load_cap
= getNet("Y")->getTotalDownstreamCap();
150 // Calculate OR2Event energy
151 double energy_per_trans_01
= (y_b_cap
+ y_cap
+ y_load_cap
) * vdd
* vdd
;
152 getEventResult("OR2")->setValue(energy_per_trans_01
* Y_num_trans_01
);
157 void OR2::propagateTransitionInfo()
159 // Get input signal transition info
160 const TransitionInfo
& trans_A
= getInputPort("A")->getTransitionInfo();
161 const TransitionInfo
& trans_B
= getInputPort("B")->getTransitionInfo();
163 double max_freq_mult
= max(trans_A
.getFrequencyMultiplier(), trans_B
.getFrequencyMultiplier());
164 const TransitionInfo
& scaled_trans_A
= trans_A
.scaleFrequencyMultiplier(max_freq_mult
);
165 const TransitionInfo
& scaled_trans_B
= trans_B
.scaleFrequencyMultiplier(max_freq_mult
);
167 double A_prob_00
= scaled_trans_A
.getNumberTransitions00() / max_freq_mult
;
168 double A_prob_01
= scaled_trans_A
.getNumberTransitions01() / max_freq_mult
;
169 double A_prob_10
= A_prob_01
;
170 double A_prob_11
= scaled_trans_A
.getNumberTransitions11() / max_freq_mult
;
171 double B_prob_00
= scaled_trans_B
.getNumberTransitions00() / max_freq_mult
;
172 double B_prob_01
= scaled_trans_B
.getNumberTransitions01() / max_freq_mult
;
173 double B_prob_10
= B_prob_01
;
174 double B_prob_11
= scaled_trans_B
.getNumberTransitions11() / max_freq_mult
;
176 // Set output transition info
177 double Y_prob_00
= A_prob_00
* B_prob_00
;
178 double Y_prob_01
= A_prob_00
* B_prob_01
+
179 A_prob_01
* (B_prob_00
+ B_prob_01
);
180 double Y_prob_11
= A_prob_00
* B_prob_11
+
181 A_prob_01
* (B_prob_10
+ B_prob_11
) +
182 A_prob_10
* (B_prob_01
+ B_prob_11
) +
185 // Check that probabilities add up to 1.0 with some finite tolerance
186 ASSERT(LibUtil::Math::isEqual((Y_prob_00
+ Y_prob_01
+ Y_prob_01
+ Y_prob_11
), 1.0), "[Error] " + getInstanceName() +
187 "Output transition probabilities must add up to 1 (" + (String
) Y_prob_00
+ ", " +
188 (String
) Y_prob_01
+ ", " + (String
) Y_prob_11
+ ")!");
190 // Turn probability of transitions per cycle into number of transitions per time unit
191 TransitionInfo
trans_Y(Y_prob_00
* max_freq_mult
, Y_prob_01
* max_freq_mult
, Y_prob_11
* max_freq_mult
);
192 getOutputPort("Y")->setTransitionInfo(trans_Y
);
196 // Creates the standard cell, characterizes and abstracts away the details
197 void OR2::cacheStdCell(StdCellLib
* cell_lib_
, double drive_strength_
)
200 double gate_pitch
= cell_lib_
->getTechModel()->get("Gate->PitchContacted");
201 Map
<double>* cache
= cell_lib_
->getStdCellCache();
203 // Stadard cell cache string
204 const String
& cell_name
= "OR2_X" + (String
) drive_strength_
;
206 Log::printLine("=== " + cell_name
+ " ===");
208 // Now actually build the full standard cell model
209 createInputPort("A");
210 createInputPort("B");
211 createOutputPort("Y");
216 CellMacros::addNor2(this, "NOR2", false, true, true, "A", "B", "Y_b");
217 CellMacros::addInverter(this, "INV", false, true, "Y_b", "Y");
220 CellMacros::updateNor2(this, "NOR2", drive_strength_
* 0.66);
221 CellMacros::updateInverter(this, "INV", drive_strength_
* 1.0);
225 area
+= gate_pitch
* getTotalHeight() * 1;
226 area
+= gate_pitch
* getTotalHeight() * getGenProperties()->get("NOR2_GatePitches").toDouble();
227 area
+= gate_pitch
* getTotalHeight() * getGenProperties()->get("INV_GatePitches").toDouble();
228 cache
->set(cell_name
+ "->ActiveArea", area
);
229 Log::printLine(cell_name
+ "->ActiveArea=" + (String
)area
);
231 // --------------------------------------------------------------------
232 // Leakage Model Calculation
233 // --------------------------------------------------------------------
234 // Cache leakage power results (for every single signal combination)
235 double leakage_00
= 0.0; // !A, !B
236 double leakage_01
= 0.0; // !A, B
237 double leakage_10
= 0.0; // A, !B
238 double leakage_11
= 0.0; // A, B
240 leakage_00
+= getGenProperties()->get("NOR2_LeakagePower_00").toDouble();
241 leakage_00
+= getGenProperties()->get("INV_LeakagePower_1").toDouble();
243 leakage_01
+= getGenProperties()->get("NOR2_LeakagePower_01").toDouble();
244 leakage_01
+= getGenProperties()->get("INV_LeakagePower_0").toDouble();
246 leakage_10
+= getGenProperties()->get("NOR2_LeakagePower_10").toDouble();
247 leakage_10
+= getGenProperties()->get("INV_LeakagePower_0").toDouble();
249 leakage_11
+= getGenProperties()->get("NOR2_LeakagePower_11").toDouble();
250 leakage_11
+= getGenProperties()->get("INV_LeakagePower_0").toDouble();
252 cache
->set(cell_name
+ "->Leakage->!A!B", leakage_00
);
253 cache
->set(cell_name
+ "->Leakage->!AB", leakage_01
);
254 cache
->set(cell_name
+ "->Leakage->A!B", leakage_10
);
255 cache
->set(cell_name
+ "->Leakage->AB", leakage_11
);
256 Log::printLine(cell_name
+ "->Leakage->!A!B=" + (String
) leakage_00
);
257 Log::printLine(cell_name
+ "->Leakage->!AB=" + (String
) leakage_01
);
258 Log::printLine(cell_name
+ "->Leakage->A!B=" + (String
) leakage_10
);
259 Log::printLine(cell_name
+ "->Leakage->AB=" + (String
) leakage_11
);
260 // --------------------------------------------------------------------
262 // --------------------------------------------------------------------
263 // Get Node Capacitances
264 // --------------------------------------------------------------------
265 double a_cap
= getNet("A")->getTotalDownstreamCap();
266 double b_cap
= getNet("B")->getTotalDownstreamCap();
267 double y_b_cap
= getNet("Y_b")->getTotalDownstreamCap();
268 double y_cap
= getNet("Y")->getTotalDownstreamCap();
270 cache
->set(cell_name
+ "->Cap->A", a_cap
);
271 cache
->set(cell_name
+ "->Cap->B", b_cap
);
272 cache
->set(cell_name
+ "->Cap->Y_b", y_b_cap
);
273 cache
->set(cell_name
+ "->Cap->Y", y_cap
);
274 Log::printLine(cell_name
+ "->Cap->A_Cap=" + (String
) a_cap
);
275 Log::printLine(cell_name
+ "->Cap->B_Cap=" + (String
) b_cap
);
276 Log::printLine(cell_name
+ "->Cap->Y_b_Cap=" + (String
) y_b_cap
);
277 Log::printLine(cell_name
+ "->Cap->Y_Cap=" + (String
) y_cap
);
278 // --------------------------------------------------------------------
280 // --------------------------------------------------------------------
281 // Build Internal Delay Model
282 // --------------------------------------------------------------------
283 double y_ron
= getDriver("INV_RonZN")->getOutputRes();
284 double a_to_y_delay
= getDriver("NOR2_RonZN")->calculateDelay() +
285 getDriver("INV_RonZN")->calculateDelay();
286 double b_to_y_delay
= getDriver("NOR2_RonZN")->calculateDelay() +
287 getDriver("INV_RonZN")->calculateDelay();
289 cache
->set(cell_name
+ "->DriveRes->Y", y_ron
);
290 cache
->set(cell_name
+ "->Delay->A_to_Y", a_to_y_delay
);
291 cache
->set(cell_name
+ "->Delay->B_to_Y", b_to_y_delay
);
292 Log::printLine(cell_name
+ "->DriveRes->Y=" + (String
) y_ron
);
293 Log::printLine(cell_name
+ "->Delay->A_to_Y=" + (String
) a_to_y_delay
);
294 Log::printLine(cell_name
+ "->Delay->B_to_Y=" + (String
) b_to_y_delay
);
295 // --------------------------------------------------------------------