LATQ.cc revision 10447:a465576671d4
1#include "model/std_cells/LATQ.h"
2
3#include <cmath>
4
5#include "model/PortInfo.h"
6#include "model/TransitionInfo.h"
7#include "model/EventInfo.h"
8#include "model/std_cells/StdCellLib.h"
9#include "model/std_cells/CellMacros.h"
10#include "model/timing_graph/ElectricalNet.h"
11#include "model/timing_graph/ElectricalDriver.h"
12#include "model/timing_graph/ElectricalLoad.h"
13#include "model/timing_graph/ElectricalDelay.h"
14
15namespace DSENT
16{
17    using std::ceil;
18    using std::max;
19    using std::min;
20
21    LATQ::LATQ(const String& instance_name_, const TechModel* tech_model_)
22        : StdCell(instance_name_, tech_model_)
23    {
24        initProperties();
25    }
26
27    LATQ::~LATQ()
28    {}
29
30    void LATQ::initProperties()
31    {
32        return;
33    }
34
35    void LATQ::constructModel()
36    {
37        // All constructModel should do is create Area/NDDPower/Energy Results as
38        // well as instantiate any sub-instances using only the hard parameters
39
40        createInputPort("D");
41        createInputPort("G");
42        createOutputPort("Q");
43
44        createLoad("D_Cap");
45        createLoad("G_Cap");
46        createDelay("D_to_Q_delay");
47        createDelay("G_to_Q_delay");
48        createDriver("Q_Ron", true);
49
50        ElectricalLoad* d_cap = getLoad("D_Cap");
51        ElectricalLoad* g_cap = getLoad("G_Cap");
52        ElectricalDelay* d_to_q_delay = getDelay("D_to_Q_delay");
53        ElectricalDelay* g_to_q_delay = getDelay("G_to_Q_delay");
54        ElectricalDriver* q_ron = getDriver("Q_Ron");
55
56        getNet("D")->addDownstreamNode(d_cap);
57        getNet("G")->addDownstreamNode(g_cap);
58        d_cap->addDownstreamNode(d_to_q_delay);
59        g_cap->addDownstreamNode(g_to_q_delay);
60        g_to_q_delay->addDownstreamNode(q_ron);
61        q_ron->addDownstreamNode(getNet("Q"));
62
63        // Create Area result
64        // Create NDD Power result
65        createElectricalAtomicResults();
66        // Create G Event Energy Result
67        createElectricalEventAtomicResult("G");
68        // Create DFF Event Energy Result
69        createElectricalEventAtomicResult("LATD");
70        createElectricalEventAtomicResult("LATQ");
71        // Create Idle event for leakage
72        // G pin is assumed to be on all the time
73        //createElectricalEventAtomicResult("Idle");
74        getEventInfo("Idle")->setStaticTransitionInfos();
75        return;
76    }
77
78    void LATQ::updateModel()
79    {
80        // Get parameters
81        double drive_strength = getDrivingStrength();
82        Map<double>* cache = getTechModel()->getStdCellLib()->getStdCellCache();
83
84        // Standard cell cache string
85        String cell_name = "LATQ_X" + (String) drive_strength;
86
87        // Get timing parameters
88        getLoad("D_Cap")->setLoadCap(cache->get(cell_name + "->Cap->D"));
89        getLoad("G_Cap")->setLoadCap(cache->get(cell_name + "->Cap->G"));
90        getDriver("Q_Ron")->setOutputRes(cache->get(cell_name + "->DriveRes->Q"));
91        getDelay("G_to_Q_delay")->setDelay(cache->get(cell_name + "->Delay->G_to_Q"));
92        getDelay("D_to_Q_delay")->setDelay(cache->get(cell_name + "->Delay->D_to_Q"));
93
94        // Set the cell area
95        getAreaResult("Active")->setValue(cache->get(cell_name + "->Area->Active"));
96        getAreaResult("Metal1Wire")->setValue(cache->get(cell_name + "->Area->Metal1Wire"));
97
98        return;
99    }
100
101    void LATQ::evaluateModel()
102    {
103        return;
104    }
105
106    void LATQ::useModel()
107    {
108        // Get parameters
109        double drive_strength = getDrivingStrength();
110        Map<double>* cache = getTechModel()->getStdCellLib()->getStdCellCache();
111
112        // Standard cell cache string
113        String cell_name = "LATQ_X" + (String) drive_strength;
114
115        // Propagate the transition info and get P_D, P_M, and P_Q
116        propagateTransitionInfo();
117        double P_D = getInputPort("D")->getTransitionInfo().getProbability1();
118        double P_G = getInputPort("G")->getTransitionInfo().getProbability1();
119        double P_Q = getOutputPort("Q")->getTransitionInfo().getProbability1();
120        double G_num_trans_01 = getInputPort("G")->getTransitionInfo().getNumberTransitions01();
121        double D_num_trans_01 = getInputPort("D")->getTransitionInfo().getNumberTransitions01();
122        double Q_num_trans_01 = getOutputPort("Q")->getTransitionInfo().getNumberTransitions01();
123
124        // Calculate leakage
125        double leakage = 0;
126        leakage += cache->get(cell_name + "->Leakage->!D!G!Q") * (1 - P_D) * (1 - P_G) * (1 - P_Q);
127        leakage += cache->get(cell_name + "->Leakage->!D!GQ") * (1 - P_D) * (1 - P_G) * P_Q;
128        leakage += cache->get(cell_name + "->Leakage->!DG!Q") * (1 - P_D) * P_G * (1 - P_Q);
129        leakage += cache->get(cell_name + "->Leakage->D!G!Q") * P_D * (1 - P_G) * (1 - P_Q);
130        leakage += cache->get(cell_name + "->Leakage->D!GQ") * P_D * (1 - P_G) * P_Q;
131        leakage += cache->get(cell_name + "->Leakage->DGQ") * P_D * P_G * P_Q;
132        getNddPowerResult("Leakage")->setValue(leakage);
133
134        // Get VDD
135        double vdd = getTechModel()->get("Vdd");
136
137        // Get capacitances
138        double g_b_cap = cache->get(cell_name + "->Cap->G_b");
139        double d_b_cap = cache->get(cell_name + "->Cap->D_b");
140        double q_i_cap = cache->get(cell_name + "->Cap->Q_i");
141        double q_b_cap = cache->get(cell_name + "->Cap->Q_b");
142        double q_cap = cache->get(cell_name + "->Cap->Q");
143        double q_load_cap = getNet("Q")->getTotalDownstreamCap();
144
145        // Calculate G Event energy
146        double g_event_energy = 0.0;
147        g_event_energy += (g_b_cap) * G_num_trans_01;
148        g_event_energy *= vdd * vdd;
149        getEventResult("G")->setValue(g_event_energy);
150        // Calculate LATD Event energy
151        double latd_event_energy = 0.0;
152        latd_event_energy += (d_b_cap) * D_num_trans_01;
153        latd_event_energy *= vdd * vdd;
154        getEventResult("LATD")->setValue(latd_event_energy);
155        // Calculate LATQ Event energy
156        double latq_event_energy = 0.0;
157        latq_event_energy += (q_i_cap + q_b_cap + q_cap + q_load_cap) * Q_num_trans_01;
158        latq_event_energy *= vdd * vdd;
159        getEventResult("LATQ")->setValue(latq_event_energy);
160
161        return;
162    }
163
164    void LATQ::propagateTransitionInfo()
165    {
166        const TransitionInfo& trans_G = getInputPort("G")->getTransitionInfo();
167        const TransitionInfo& trans_D = getInputPort("D")->getTransitionInfo();
168
169        double G_num_trans_01 = trans_G.getNumberTransitions01();
170        double G_num_trans_10 = G_num_trans_01;
171        double G_num_trans_00 = trans_G.getNumberTransitions00();
172        double D_freq_mult = trans_D.getFrequencyMultiplier();
173
174        // If the latch is sampling just as fast or faster than input data signal
175        // Then it can capture all transitions (though it should be normalized to clock)
176        if((G_num_trans_10 + G_num_trans_00) >= D_freq_mult)
177        {
178            const TransitionInfo& trans_Q = trans_D.scaleFrequencyMultiplier(G_num_trans_10 + G_num_trans_00);
179            getOutputPort("Q")->setTransitionInfo(trans_Q);
180        }
181        // If the latch is sampling slower than the input data signal, then input
182        // will look like they transition more
183        else
184        {
185            // Calculate scale ratio
186            double scale_ratio = (G_num_trans_10 + G_num_trans_00) / D_freq_mult;
187            // 00 and 11 transitions become fewer
188            double D_scaled_diff = 0.5 * (1 - scale_ratio) * (trans_D.getNumberTransitions00() + trans_D.getNumberTransitions11());
189            double D_scaled_num_trans_00 = trans_D.getNumberTransitions00() * scale_ratio;
190            double D_scaled_num_trans_11 = trans_D.getNumberTransitions11() * scale_ratio;
191            // 01 and 10 transitions become more frequent
192            double D_scaled_num_trans_10 = trans_D.getNumberTransitions01() + D_scaled_diff;
193
194            // Create final transition info, remembering to apply scaling ratio to normalize to G
195            const TransitionInfo trans_Q(   D_scaled_num_trans_00 * scale_ratio,
196                                            D_scaled_num_trans_10 * scale_ratio,
197                                            D_scaled_num_trans_11 * scale_ratio);
198            getOutputPort("Q")->setTransitionInfo(trans_Q);
199        }
200
201        return;
202    }
203
204    // Creates the standard cell, characterizes and abstracts away the details
205    void LATQ::cacheStdCell(StdCellLib* cell_lib_, double drive_strength_)
206    {
207        // Get parameters
208        double gate_pitch = cell_lib_->getTechModel()->get("Gate->PitchContacted");
209        Map<double>* cache = cell_lib_->getStdCellCache();
210
211        // Standard cell cache string
212        String cell_name = "LATQ_X" + (String) drive_strength_;
213
214        Log::printLine("=== " + cell_name + " ===");
215
216
217        // Now actually build the full standard cell model
218        createInputPort("D");
219        createInputPort("G");
220        createOutputPort("Q");
221
222        createNet("D_b");
223        createNet("Q_i");
224        createNet("Q_b");
225        createNet("G_b");
226
227        // Adds macros
228        CellMacros::addInverter(this, "INV1", false, true, "D", "D_b");
229        CellMacros::addInverter(this, "INV2", false, true, "Q_i", "Q_b");
230        CellMacros::addInverter(this, "INV3", false, true, "Q_b", "Q");
231        CellMacros::addInverter(this, "INV4", false, true, "G", "G_b");
232        CellMacros::addTristate(this, "INVZ1", false, true, false, false, "D_b", "G", "G_b", "Q_i");        //trace timing through A->ZN path only
233        CellMacros::addTristate(this, "INVZ2", false, false, false, false, "Q_b", "G_b", "G", "Q_i");       //don't trace timing through the feedback path
234
235        // Update macros
236        CellMacros::updateInverter(this, "INV1", drive_strength_ * 0.125);
237        CellMacros::updateInverter(this, "INV2", drive_strength_ * 0.5);
238        CellMacros::updateInverter(this, "INV3", drive_strength_ * 1.0);
239        CellMacros::updateInverter(this, "INV4", drive_strength_ * 0.125);
240        CellMacros::updateTristate(this, "INVZ1", drive_strength_ * 0.5);
241        CellMacros::updateTristate(this, "INVZ2", drive_strength_ * 0.0625);
242
243        // Cache area result
244        double area = 0.0;
245        area += gate_pitch * getTotalHeight() * 1;
246        area += gate_pitch * getTotalHeight() * getGenProperties()->get("INV1_GatePitches").toDouble();
247        area += gate_pitch * getTotalHeight() * getGenProperties()->get("INV2_GatePitches").toDouble();
248        area += gate_pitch * getTotalHeight() * getGenProperties()->get("INV3_GatePitches").toDouble();
249        area += gate_pitch * getTotalHeight() * getGenProperties()->get("INV4_GatePitches").toDouble();
250        area += gate_pitch * getTotalHeight() * getGenProperties()->get("INVZ1_GatePitches").toDouble();
251        area += gate_pitch * getTotalHeight() * getGenProperties()->get("INVZ2_GatePitches").toDouble();
252        cache->set(cell_name + "->Area->Active", area);
253        cache->set(cell_name + "->Area->Metal1Wire", area);     //Cover-block m1 area
254        Log::printLine(cell_name + "->Area->Active=" + (String) area);
255        Log::printLine(cell_name + "->Area->Metal1Wire=" + (String) area);
256
257        // --------------------------------------------------------------------
258        // Leakage Model Calculation
259        // --------------------------------------------------------------------
260        // Cache leakage power results (for every single signal combination)
261        double leakage_000 = 0;         //!D, !G, !Q
262        double leakage_001 = 0;         //!D, !G, Q
263        double leakage_010 = 0;         //!D, G, !Q
264        double leakage_100 = 0;         //D, !G, !Q
265        double leakage_101 = 0;         //D, !G, Q
266        double leakage_111 = 0;         //D, G, Q
267
268        //This is so painful...
269        leakage_000 += getGenProperties()->get("INV1_LeakagePower_0").toDouble();
270        leakage_000 += getGenProperties()->get("INV2_LeakagePower_0").toDouble();
271        leakage_000 += getGenProperties()->get("INV3_LeakagePower_1").toDouble();
272        leakage_000 += getGenProperties()->get("INV4_LeakagePower_0").toDouble();
273        leakage_000 += getGenProperties()->get("INVZ1_LeakagePower_011_0").toDouble();
274        leakage_000 += getGenProperties()->get("INVZ2_LeakagePower_101_0").toDouble();
275
276        leakage_001 += getGenProperties()->get("INV1_LeakagePower_0").toDouble();
277        leakage_001 += getGenProperties()->get("INV2_LeakagePower_0").toDouble();
278        leakage_001 += getGenProperties()->get("INV3_LeakagePower_0").toDouble();
279        leakage_001 += getGenProperties()->get("INV4_LeakagePower_0").toDouble();
280        leakage_001 += getGenProperties()->get("INVZ1_LeakagePower_011_1").toDouble();
281        leakage_001 += getGenProperties()->get("INVZ2_LeakagePower_100_1").toDouble();
282
283        leakage_010 += getGenProperties()->get("INV1_LeakagePower_0").toDouble();
284        leakage_010 += getGenProperties()->get("INV2_LeakagePower_0").toDouble();
285        leakage_010 += getGenProperties()->get("INV3_LeakagePower_1").toDouble();
286        leakage_010 += getGenProperties()->get("INV4_LeakagePower_1").toDouble();
287        leakage_010 += getGenProperties()->get("INVZ1_LeakagePower_101_0").toDouble();
288        leakage_010 += getGenProperties()->get("INVZ2_LeakagePower_011_0").toDouble();
289
290        leakage_100 += getGenProperties()->get("INV1_LeakagePower_1").toDouble();
291        leakage_100 += getGenProperties()->get("INV2_LeakagePower_1").toDouble();
292        leakage_100 += getGenProperties()->get("INV3_LeakagePower_1").toDouble();
293        leakage_100 += getGenProperties()->get("INV4_LeakagePower_0").toDouble();
294        leakage_100 += getGenProperties()->get("INVZ1_LeakagePower_010_0").toDouble();
295        leakage_100 += getGenProperties()->get("INVZ2_LeakagePower_101_0").toDouble();
296
297        leakage_101 += getGenProperties()->get("INV1_LeakagePower_1").toDouble();
298        leakage_101 += getGenProperties()->get("INV2_LeakagePower_1").toDouble();
299        leakage_101 += getGenProperties()->get("INV3_LeakagePower_0").toDouble();
300        leakage_101 += getGenProperties()->get("INV4_LeakagePower_0").toDouble();
301        leakage_101 += getGenProperties()->get("INVZ1_LeakagePower_010_1").toDouble();
302        leakage_101 += getGenProperties()->get("INVZ2_LeakagePower_100_1").toDouble();
303
304        leakage_111 += getGenProperties()->get("INV1_LeakagePower_1").toDouble();
305        leakage_111 += getGenProperties()->get("INV2_LeakagePower_1").toDouble();
306        leakage_111 += getGenProperties()->get("INV3_LeakagePower_0").toDouble();
307        leakage_111 += getGenProperties()->get("INV4_LeakagePower_1").toDouble();
308        leakage_111 += getGenProperties()->get("INVZ1_LeakagePower_100_1").toDouble();
309        leakage_111 += getGenProperties()->get("INVZ2_LeakagePower_010_1").toDouble();
310
311        cache->set(cell_name + "->Leakage->!D!G!Q", leakage_000);
312        cache->set(cell_name + "->Leakage->!D!GQ", leakage_001);
313        cache->set(cell_name + "->Leakage->!DG!Q", leakage_010);
314        cache->set(cell_name + "->Leakage->D!G!Q", leakage_100);
315        cache->set(cell_name + "->Leakage->D!GQ", leakage_101);
316        cache->set(cell_name + "->Leakage->DGQ", leakage_111);
317        Log::printLine(cell_name + "->Leakage->!D!G!Q=" + (String) leakage_000);
318        Log::printLine(cell_name + "->Leakage->!D!GQ=" + (String) leakage_001);
319        Log::printLine(cell_name + "->Leakage->!DG!Q=" + (String) leakage_010);
320        Log::printLine(cell_name + "->Leakage->D!G!Q=" + (String) leakage_100);
321        Log::printLine(cell_name + "->Leakage->D!GQ=" + (String) leakage_101);
322        Log::printLine(cell_name + "->Leakage->DGQ=" + (String) leakage_111);
323        // --------------------------------------------------------------------
324
325        // --------------------------------------------------------------------
326        // Get Node Capacitances
327        // --------------------------------------------------------------------
328        double d_cap = getNet("D")->getTotalDownstreamCap();
329        double d_b_cap = getNet("D_b")->getTotalDownstreamCap();
330        double q_i_cap = getNet("Q_i")->getTotalDownstreamCap();
331        double q_b_cap = getNet("Q_b")->getTotalDownstreamCap();
332        double q_cap = getNet("Q")->getTotalDownstreamCap();
333        double g_cap = getNet("G")->getTotalDownstreamCap();
334        double g_b_cap = getNet("G_b")->getTotalDownstreamCap();
335
336        cache->set(cell_name + "->Cap->D", d_cap);
337        cache->set(cell_name + "->Cap->D_b", d_b_cap);
338        cache->set(cell_name + "->Cap->Q_i", q_i_cap);
339        cache->set(cell_name + "->Cap->Q_b", q_b_cap);
340        cache->set(cell_name + "->Cap->Q", q_cap);
341        cache->set(cell_name + "->Cap->G", g_cap);
342        cache->set(cell_name + "->Cap->G_b", g_b_cap);
343
344        Log::printLine(cell_name + "->Cap->D=" + (String) d_cap);
345        Log::printLine(cell_name + "->Cap->D_b=" + (String) d_b_cap);
346        Log::printLine(cell_name + "->Cap->Q_i=" + (String) q_i_cap);
347        Log::printLine(cell_name + "->Cap->Q_b=" + (String) q_b_cap);
348        Log::printLine(cell_name + "->Cap->Q=" + (String) q_cap);
349        Log::printLine(cell_name + "->Cap->G=" + (String) g_cap);
350        Log::printLine(cell_name + "->Cap->G_b=" + (String) g_b_cap);
351        // --------------------------------------------------------------------
352
353        // --------------------------------------------------------------------
354        // Build Internal Delay Model
355        // --------------------------------------------------------------------
356        double q_ron = getDriver("INV3_RonZN")->getOutputRes();
357
358        double d_to_q_delay = getDriver("INV1_RonZN")->calculateDelay() +
359                                getDriver("INVZ1_RonZN")->calculateDelay() +
360                                getDriver("INV2_RonZN")->calculateDelay() +
361                                getDriver("INV3_RonZN")->calculateDelay();
362        double g_to_q_delay = getDriver("INV4_RonZN")->calculateDelay() +
363                                getDriver("INVZ1_RonZN")->calculateDelay() +
364                                getDriver("INV2_RonZN")->calculateDelay() +
365                                getDriver("INV3_RonZN")->calculateDelay();
366
367        cache->set(cell_name + "->DriveRes->Q", q_ron);
368        cache->set(cell_name + "->Delay->D_to_Q", d_to_q_delay);
369        cache->set(cell_name + "->Delay->G_to_Q", g_to_q_delay);
370        Log::printLine(cell_name + "->DriveRes->Q=" + (String) q_ron);
371        Log::printLine(cell_name + "->Delay->D_to_Q=" + (String) d_to_q_delay);
372        Log::printLine(cell_name + "->Delay->G_to_Q=" + (String) g_to_q_delay);
373
374        return;
375        // --------------------------------------------------------------------
376
377    }
378
379} // namespace DSENT
380
381