1/*****************************************************************************
2 *                                McPAT
3 *                      SOFTWARE LICENSE AGREEMENT
4 *            Copyright 2012 Hewlett-Packard Development Company, L.P.
5 *            Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
6 *                          All Rights Reserved
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer;
12 * redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution;
15 * neither the name of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ***************************************************************************/
32#include <algorithm>
33#include <cassert>
34#include <cmath>
35#include <iostream>
36#include <string>
37
38#include "basic_circuit.h"
39#include "common.h"
40#include "const.h"
41#include "io.h"
42#include "iocontrollers.h"
43#include "logic.h"
44
45/*
46SUN Niagara 2 I/O power analysis:
47total signal bits: 711
48Total FBDIMM bits: (14+10)*2*8= 384
49PCIe bits:         (8 + 8)*2 = 32
5010Gb NIC:          (4*2+4*2)*2 = 32
51Debug I/Os:        168
52Other I/Os:        711- 32-32 - 384 - 168 = 95
53
54According to "Implementation of an 8-Core, 64-Thread, Power-Efficient SPARC Server on a Chip"
5590% of I/Os are SerDers (the calucaltion is 384+64/(711-168)=83% about the same as the 90% reported in the paper)
56--> around 80Pins are common I/Os.
57Common I/Os consumes 71mW/Gb/s according to Cadence ChipEstimate @65nm
58Niagara 2 I/O clock is 1/4 of core clock. --> 87pin (<--((711-168)*17%)) * 71mW/Gb/s *0.25*1.4Ghz = 2.17W
59
60Total dynamic power of FBDIMM, NIC, PCIe = 84*0.132 + 84*0.049*0.132 = 11.14 - 2.17 = 8.98
61Further, if assuming I/O logic power is about 50% of I/Os then Total energy of FBDIMM, NIC, PCIe = 11.14 - 2.17*1.5 = 7.89
62 */
63
64/*
65 * A bug in Cadence ChipEstimator: After update the clock rate in the clock tab, a user
66 * need to re-select the IP clock (the same clk) and then click Estimate. if not reselect
67 * the new clock rate may not be propogate into the IPs.
68 *
69 */
70
71NIUController::NIUController(XMLNode* _xml_data,InputParameter* interface_ip_)
72    : McPATComponent(_xml_data, interface_ip_) {
73    name = "NIU";
74    set_niu_param();
75}
76
77void NIUController::computeArea() {
78    double mac_area;
79    double frontend_area;
80    double SerDer_area;
81
82    if (niup.type == 0) { //high performance NIU
83        //Area estimation based on average of die photo from Niagara 2 and
84        //Cadence ChipEstimate using 65nm.
85        mac_area = (1.53 + 0.3) / 2 * (interface_ip.F_sz_um / 0.065) *
86            (interface_ip.F_sz_um / 0.065);
87        //Area estimation based on average of die photo from Niagara 2, ISSCC
88        //"An 800mW 10Gb Ethernet Transceiver in 0.13μm CMOS"
89        //and"A 1.2-V-Only 900-mW 10 Gb Ethernet Transceiver and XAUI Interface
90        //With Robust VCO Tuning Technique" Frontend is PCS
91        frontend_area = (9.8 + (6 + 18) * 65 / 130 * 65 / 130) / 3 *
92            (interface_ip.F_sz_um / 0.065) * (interface_ip.F_sz_um / 0.065);
93        //Area estimation based on average of die photo from Niagara 2 and
94        //Cadence ChipEstimate hard IP @65nm.
95        //SerDer is very hard to scale
96        SerDer_area = (1.39 + 0.36) * (interface_ip.F_sz_um /
97                                       0.065);//* (interface_ip.F_sz_um/0.065);
98    } else {
99        //Low power implementations are mostly from Cadence ChipEstimator;
100        //Ignore the multiple IP effect
101        // ---When there are multiple IP (same kind or not) selected, Cadence
102        //ChipEstimator results are not a simple summation of all IPs.
103        //Ignore this effect
104        mac_area = 0.24 * (interface_ip.F_sz_um / 0.065) *
105            (interface_ip.F_sz_um / 0.065);
106        frontend_area = 0.1 * (interface_ip.F_sz_um / 0.065) *
107            (interface_ip.F_sz_um / 0.065);//Frontend is the PCS layer
108        SerDer_area = 0.35 * (interface_ip.F_sz_um / 0.065) *
109            (interface_ip.F_sz_um/0.065);
110        //Compare 130um implementation in "A 1.2-V-Only 900-mW 10 Gb Ethernet
111        //Transceiver and XAUI Interface With Robust VCO Tuning Technique"
112        //and the ChipEstimator XAUI PHY hard IP, confirm that even PHY can
113        //scale perfectly with the technology
114    }
115
116    //total area
117    output_data.area = (mac_area + frontend_area + SerDer_area) * 1e6;
118 }
119
120void NIUController::computeEnergy() {
121    double mac_dyn;
122    double frontend_dyn;
123    double SerDer_dyn;
124    double frontend_gates;
125    double mac_gates;
126    double SerDer_gates;
127    double NMOS_sizing;
128    double PMOS_sizing;
129    double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
130
131    if (niup.type == 0) { //high performance NIU
132        //Power
133        //Cadence ChipEstimate using 65nm (mac, front_end are all energy.
134        //E=P*T = P/F = 1.37/1Ghz = 1.37e-9);
135        //2.19W@1GHz fully active according to Cadence ChipEstimate @65nm
136        mac_dyn = 2.19e-9 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd /
137            1.1 * (interface_ip.F_sz_nm / 65.0);//niup.clockRate;
138        //Cadence ChipEstimate using 65nm soft IP;
139        frontend_dyn = 0.27e-9 * g_tp.peri_global.Vdd / 1.1 *
140            g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
141        //according to "A 100mW 9.6Gb/s Transceiver in 90nm CMOS..." ISSCC 2006
142        //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
143        SerDer_dyn = 0.01 * 10 * sqrt(interface_ip.F_sz_um / 0.09) *
144            g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2;
145
146        //Cadence ChipEstimate using 65nm
147        mac_gates = 111700;
148        frontend_gates = 320000;
149        SerDer_gates = 200000;
150        NMOS_sizing = 5 * g_tp.min_w_nmos_;
151        PMOS_sizing	= 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
152    } else {
153        //Power
154        //Cadence ChipEstimate using 65nm (mac, front_end are all energy.
155        ///E=P*T = P/F = 1.37/1Ghz = 1.37e-9);
156        //2.19W@1GHz fully active according to Cadence ChipEstimate @65nm
157        mac_dyn = 1.257e-9 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd
158            / 1.1 * (interface_ip.F_sz_nm / 65.0);//niup.clockRate;
159        //Cadence ChipEstimate using 65nm soft IP;
160        frontend_dyn = 0.6e-9 * g_tp.peri_global.Vdd / 1.1 *
161            g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
162        //SerDer_dyn is power not energy, scaling from 216mw/10Gb/s @130nm
163        SerDer_dyn = 0.0216 * 10 * (interface_ip.F_sz_um / 0.13) *
164            g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2;
165
166        mac_gates = 111700;
167        frontend_gates = 52000;
168        SerDer_gates = 199260;
169        NMOS_sizing = g_tp.min_w_nmos_;
170        PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
171    }
172
173    //covert to energy per clock cycle of whole NIU
174    SerDer_dyn /= niup.clockRate;
175
176    power.readOp.dynamic = mac_dyn + frontend_dyn + SerDer_dyn;
177    power.readOp.leakage = (mac_gates + frontend_gates + frontend_gates) *
178        cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
179        g_tp.peri_global.Vdd;//unit W
180    double long_channel_device_reduction =
181        longer_channel_device_reduction(Uncore_device);
182    power.readOp.longer_channel_leakage =
183        power.readOp.leakage * long_channel_device_reduction;
184    power.readOp.gate_leakage = (mac_gates + frontend_gates + frontend_gates) *
185        cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
186        g_tp.peri_global.Vdd;//unit W
187
188    // Output power
189    output_data.subthreshold_leakage_power =
190        longer_channel_device ? power.readOp.longer_channel_leakage :
191        power.readOp.leakage;
192    output_data.gate_leakage_power = power.readOp.gate_leakage;
193    output_data.peak_dynamic_power = power.readOp.dynamic * nius.duty_cycle;
194    output_data.runtime_dynamic_energy = power.readOp.dynamic * nius.perc_load;
195}
196
197void NIUController::set_niu_param() {
198    int num_children = xml_data->nChildNode("param");
199    int i;
200    for (i = 0; i < num_children; i++) {
201        XMLNode* paramNode = xml_data->getChildNodePtr("param", &i);
202        XMLCSTR node_name = paramNode->getAttribute("name");
203        XMLCSTR value = paramNode->getAttribute("value");
204
205        if (!node_name)
206            warnMissingParamName(paramNode->getAttribute("id"));
207
208        ASSIGN_FP_IF("niu_clockRate", niup.clockRate);
209        ASSIGN_INT_IF("num_units", niup.num_units);
210        ASSIGN_INT_IF("type", niup.type);
211
212        else {
213            warnUnrecognizedParam(node_name);
214        }
215    }
216
217    // Change from MHz to Hz
218    niup.clockRate *= 1e6;
219
220    num_children = xml_data->nChildNode("stat");
221    for (i = 0; i < num_children; i++) {
222        XMLNode* statNode = xml_data->getChildNodePtr("stat", &i);
223        XMLCSTR node_name = statNode->getAttribute("name");
224        XMLCSTR value = statNode->getAttribute("value");
225
226        if (!node_name)
227            warnMissingStatName(statNode->getAttribute("id"));
228
229        ASSIGN_FP_IF("duty_cycle", nius.duty_cycle);
230        ASSIGN_FP_IF("perc_load", nius.perc_load);
231
232        else {
233            warnUnrecognizedStat(node_name);
234        }
235    }
236}
237
238PCIeController::PCIeController(XMLNode* _xml_data,
239                               InputParameter* interface_ip_)
240    : McPATComponent(_xml_data, interface_ip_) {
241    name = "PCIe";
242    set_pcie_param();
243}
244
245void PCIeController::computeArea() {
246    double ctrl_area;
247    double SerDer_area;
248
249    /* Assuming PCIe is bit-slice based architecture
250     * This is the reason for /8 in both area and power calculation
251     * to get per lane numbers
252     */
253
254    if (pciep.type == 0) { //high performance PCIe
255        //Area estimation based on average of die photo from Niagara 2 and
256        //Cadence ChipEstimate @ 65nm.
257        ctrl_area = (5.2 + 0.5) / 2 * (interface_ip.F_sz_um / 0.065) *
258            (interface_ip.F_sz_um / 0.065);
259        //Area estimation based on average of die photo from Niagara 2 and
260        //Cadence ChipEstimate hard IP @65nm.
261        //SerDer is very hard to scale
262        SerDer_area = (3.03 + 0.36) * (interface_ip.F_sz_um /
263                                       0.065);//* (interface_ip.F_sz_um/0.065);
264    } else {
265        ctrl_area = 0.412 * (interface_ip.F_sz_um / 0.065) *
266            (interface_ip.F_sz_um / 0.065);
267        //Area estimation based on average of die photo from Niagara 2, and
268        //Cadence ChipEstimate @ 65nm.
269        SerDer_area = 0.36 * (interface_ip.F_sz_um / 0.065) *
270            (interface_ip.F_sz_um / 0.065);
271    }
272
273    // Total area
274    output_data.area = ((ctrl_area + (pciep.withPHY ? SerDer_area : 0)) / 8 *
275                        pciep.num_channels) * 1e6;
276}
277
278void PCIeController::computeEnergy() {
279    double ctrl_dyn;
280    double SerDer_dyn;
281    double ctrl_gates;
282    double SerDer_gates = 0;
283    double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
284    double NMOS_sizing;
285    double PMOS_sizing;
286
287    /* Assuming PCIe is bit-slice based architecture
288     * This is the reason for /8 in both area and power calculation
289     * to get per lane numbers
290     */
291
292    if (pciep.type == 0) { //high performance PCIe
293        //Power
294        //Cadence ChipEstimate using 65nm the controller includes everything: the PHY, the data link and transaction layer
295        ctrl_dyn = 3.75e-9 / 8 * g_tp.peri_global.Vdd / 1.1 *
296            g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
297        //	  //Cadence ChipEstimate using 65nm soft IP;
298        //	  frontend_dyn = 0.27e-9/8*g_tp.peri_global.Vdd/1.1*g_tp.peri_global.Vdd/1.1*(interface_ip.F_sz_nm/65.0);
299        //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
300        //PCIe 2.0 max per lane speed is 4Gb/s
301        SerDer_dyn = 0.01 * 4 * (interface_ip.F_sz_um /0.09) *
302            g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd /1.2;
303
304        //Cadence ChipEstimate using 65nm
305        ctrl_gates = 900000 / 8 * pciep.num_channels;
306        //	  frontend_gates   = 120000/8;
307        //	  SerDer_gates     = 200000/8;
308        NMOS_sizing = 5 * g_tp.min_w_nmos_;
309        PMOS_sizing	= 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
310    } else {
311        //Power
312        //Cadence ChipEstimate using 65nm the controller includes everything: the PHY, the data link and transaction layer
313        ctrl_dyn = 2.21e-9 / 8 * g_tp.peri_global.Vdd / 1.1 *
314            g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0);
315        //	  //Cadence ChipEstimate using 65nm soft IP;
316        //	  frontend_dyn = 0.27e-9/8*g_tp.peri_global.Vdd/1.1*g_tp.peri_global.Vdd/1.1*(interface_ip.F_sz_nm/65.0);
317        //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
318        //PCIe 2.0 max per lane speed is 4Gb/s
319        SerDer_dyn = 0.01 * 4 * (interface_ip.F_sz_um / 0.09) *
320            g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd /1.2;
321
322        //Cadence ChipEstimate using 65nm
323        ctrl_gates = 200000 / 8 * pciep.num_channels;
324        //	  frontend_gates   = 120000/8;
325        SerDer_gates = 200000 / 8 * pciep.num_channels;
326        NMOS_sizing = g_tp.min_w_nmos_;
327        PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
328
329    }
330
331    //covert to energy per clock cycle
332    SerDer_dyn /= pciep.clockRate;
333
334    power.readOp.dynamic = (ctrl_dyn + (pciep.withPHY ? SerDer_dyn : 0)) *
335        pciep.num_channels;
336    power.readOp.leakage = (ctrl_gates + (pciep.withPHY ? SerDer_gates : 0)) *
337        cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
338        g_tp.peri_global.Vdd;//unit W
339    double long_channel_device_reduction =
340        longer_channel_device_reduction(Uncore_device);
341    power.readOp.longer_channel_leakage =
342        power.readOp.leakage * long_channel_device_reduction;
343    power.readOp.gate_leakage = (ctrl_gates +
344                                 (pciep.withPHY ? SerDer_gates : 0)) *
345        cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
346        g_tp.peri_global.Vdd;//unit W
347
348    // Output power
349    output_data.subthreshold_leakage_power =
350        longer_channel_device ? power.readOp.longer_channel_leakage :
351        power.readOp.leakage;
352    output_data.gate_leakage_power = power.readOp.gate_leakage;
353    output_data.peak_dynamic_power = power.readOp.dynamic * pcies.duty_cycle;
354    output_data.runtime_dynamic_energy =
355        power.readOp.dynamic * pcies.perc_load;
356}
357
358void PCIeController::set_pcie_param() {
359    int num_children = xml_data->nChildNode("param");
360    int i;
361    for (i = 0; i < num_children; i++) {
362        XMLNode* paramNode = xml_data->getChildNodePtr("param", &i);
363        XMLCSTR node_name = paramNode->getAttribute("name");
364        XMLCSTR value = paramNode->getAttribute("value");
365
366        if (!node_name)
367            warnMissingParamName(paramNode->getAttribute("id"));
368
369        ASSIGN_FP_IF("pcie_clockRate", pciep.clockRate);
370        ASSIGN_INT_IF("num_units", pciep.num_units);
371        ASSIGN_INT_IF("num_channels", pciep.num_channels);
372        ASSIGN_INT_IF("type", pciep.type);
373        ASSIGN_ENUM_IF("withPHY", pciep.withPHY, bool);
374
375        else {
376            warnUnrecognizedParam(node_name);
377        }
378    }
379
380    // Change from MHz to Hz
381    pciep.clockRate *= 1e6;
382
383    num_children = xml_data->nChildNode("stat");
384    for (i = 0; i < num_children; i++) {
385        XMLNode* statNode = xml_data->getChildNodePtr("stat", &i);
386        XMLCSTR node_name = statNode->getAttribute("name");
387        XMLCSTR value = statNode->getAttribute("value");
388
389        if (!node_name)
390            warnMissingStatName(statNode->getAttribute("id"));
391
392        ASSIGN_FP_IF("duty_cycle", pcies.duty_cycle);
393        ASSIGN_FP_IF("perc_load", pcies.perc_load);
394
395        else {
396            warnUnrecognizedStat(node_name);
397        }
398    }
399}
400
401FlashController::FlashController(XMLNode* _xml_data,
402                                 InputParameter* interface_ip_)
403    : McPATComponent(_xml_data, interface_ip_) {
404    name = "Flash Controller";
405    set_fc_param();
406}
407
408void FlashController::computeArea() {
409    double ctrl_area;
410    double SerDer_area;
411
412    /* Assuming Flash is bit-slice based architecture
413     * This is the reason for /8 in both area and power calculation
414     * to get per lane numbers
415     */
416
417    if (fcp.type == 0) { //high performance flash controller
418        cout << "Current McPAT does not support high performance flash "
419             << "controller since even low power designs are enough for "
420             << "maintain throughput" <<endl;
421        exit(0);
422    } else {
423        ctrl_area = 0.243 * (interface_ip.F_sz_um / 0.065) *
424            (interface_ip.F_sz_um / 0.065);
425        //Area estimation based on Cadence ChipEstimate @ 65nm: NANDFLASH-CTRL
426        //from CAST
427        SerDer_area = 0.36 / 8 * (interface_ip.F_sz_um / 0.065) *
428            (interface_ip.F_sz_um / 0.065);
429    }
430
431    double number_channel = 1 + (fcp.num_channels - 1) * 0.2;
432    output_data.area = (ctrl_area + (fcp.withPHY ? SerDer_area : 0)) *
433        1e6 * number_channel;
434}
435
436void FlashController::computeEnergy() {
437    double ctrl_dyn;
438    double SerDer_dyn;
439    double ctrl_gates;
440    double SerDer_gates;
441    double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio();
442    double NMOS_sizing;
443    double PMOS_sizing;
444
445    /* Assuming Flash is bit-slice based architecture
446     * This is the reason for /8 in both area and power calculation
447     * to get per lane numbers
448     */
449
450    if (fcp.type == 0) { //high performance flash controller
451        cout << "Current McPAT does not support high performance flash "
452             << "controller since even low power designs are enough for "
453             << "maintain throughput" <<endl;
454        exit(0);
455        NMOS_sizing = 5 * g_tp.min_w_nmos_;
456        PMOS_sizing = 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
457    } else {
458        //based On PCIe PHY TSMC65GP from Cadence ChipEstimate @ 65nm, it
459        //support 8x lanes with each lane speed up to 250MB/s (PCIe1.1x).
460        //This is already saturate the 200MB/s of the flash controller core
461        //above.
462        ctrl_gates = 129267;
463        SerDer_gates = 200000 / 8;
464        NMOS_sizing = g_tp.min_w_nmos_;
465        PMOS_sizing	= g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r;
466
467        //Power
468        //Cadence ChipEstimate using 65nm the controller 125mW for every
469        //200MB/s This is power not energy!
470        ctrl_dyn = 0.125 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd /
471            1.1 * (interface_ip.F_sz_nm / 65.0);
472        //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm
473        SerDer_dyn = 0.01 * 1.6 * (interface_ip.F_sz_um / 0.09) *
474            g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2;
475        //max  Per controller speed is 1.6Gb/s (200MB/s)
476    }
477
478    double number_channel = 1 + (fcp.num_channels - 1) * 0.2;
479    power.readOp.dynamic = (ctrl_dyn + (fcp.withPHY ? SerDer_dyn : 0)) *
480        number_channel;
481    power.readOp.leakage = ((ctrl_gates + (fcp.withPHY ? SerDer_gates : 0)) *
482                            number_channel) *
483        cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
484        g_tp.peri_global.Vdd;//unit W
485    double long_channel_device_reduction =
486        longer_channel_device_reduction(Uncore_device);
487    power.readOp.longer_channel_leakage =
488        power.readOp.leakage * long_channel_device_reduction;
489    power.readOp.gate_leakage =
490        ((ctrl_gates + (fcp.withPHY ? SerDer_gates : 0)) * number_channel) *
491        cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) *
492        g_tp.peri_global.Vdd;//unit W
493
494    // Output power
495    output_data.subthreshold_leakage_power =
496        longer_channel_device ? power.readOp.longer_channel_leakage :
497        power.readOp.leakage;
498    output_data.gate_leakage_power = power.readOp.gate_leakage;
499    output_data.peak_dynamic_power = power.readOp.dynamic * fcs.duty_cycle;
500    output_data.runtime_dynamic_energy = power.readOp.dynamic * fcs.perc_load;
501}
502
503void FlashController::set_fc_param()
504{
505    int num_children = xml_data->nChildNode("param");
506    int i;
507    for (i = 0; i < num_children; i++) {
508        XMLNode* paramNode = xml_data->getChildNodePtr("param", &i);
509        XMLCSTR node_name = paramNode->getAttribute("name");
510        XMLCSTR value = paramNode->getAttribute("value");
511
512        if (!node_name)
513            warnMissingParamName(paramNode->getAttribute("id"));
514
515        ASSIGN_INT_IF("num_channels", fcp.num_channels);
516        ASSIGN_INT_IF("type", fcp.type);
517        ASSIGN_ENUM_IF("withPHY", fcp.withPHY, bool);
518
519        else {
520            warnUnrecognizedParam(node_name);
521        }
522    }
523
524    num_children = xml_data->nChildNode("stat");
525    for (i = 0; i < num_children; i++) {
526        XMLNode* statNode = xml_data->getChildNodePtr("stat", &i);
527        XMLCSTR node_name = statNode->getAttribute("name");
528        XMLCSTR value = statNode->getAttribute("value");
529
530        if (!node_name)
531            warnMissingStatName(statNode->getAttribute("id"));
532
533        ASSIGN_FP_IF("duty_cycle", fcs.duty_cycle);
534        ASSIGN_FP_IF("perc_load", fcs.perc_load);
535
536        else {
537            warnUnrecognizedStat(node_name);
538        }
539    }
540}
541