| /***************************************************************************** |
| * McPAT |
| * SOFTWARE LICENSE AGREEMENT |
| * Copyright 2012 Hewlett-Packard Development Company, L.P. |
| * Copyright (c) 2010-2013 Advanced Micro Devices, Inc. |
| * All Rights Reserved |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| ***************************************************************************/ |
| #include <algorithm> |
| #include <cassert> |
| #include <cmath> |
| #include <iostream> |
| #include <string> |
| |
| #include "basic_circuit.h" |
| #include "common.h" |
| #include "const.h" |
| #include "io.h" |
| #include "iocontrollers.h" |
| #include "logic.h" |
| |
| /* |
| SUN Niagara 2 I/O power analysis: |
| total signal bits: 711 |
| Total FBDIMM bits: (14+10)*2*8= 384 |
| PCIe bits: (8 + 8)*2 = 32 |
| 10Gb NIC: (4*2+4*2)*2 = 32 |
| Debug I/Os: 168 |
| Other I/Os: 711- 32-32 - 384 - 168 = 95 |
| |
| According to "Implementation of an 8-Core, 64-Thread, Power-Efficient SPARC Server on a Chip" |
| 90% of I/Os are SerDers (the calucaltion is 384+64/(711-168)=83% about the same as the 90% reported in the paper) |
| --> around 80Pins are common I/Os. |
| Common I/Os consumes 71mW/Gb/s according to Cadence ChipEstimate @65nm |
| Niagara 2 I/O clock is 1/4 of core clock. --> 87pin (<--((711-168)*17%)) * 71mW/Gb/s *0.25*1.4Ghz = 2.17W |
| |
| Total dynamic power of FBDIMM, NIC, PCIe = 84*0.132 + 84*0.049*0.132 = 11.14 - 2.17 = 8.98 |
| Further, 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 |
| */ |
| |
| /* |
| * A bug in Cadence ChipEstimator: After update the clock rate in the clock tab, a user |
| * need to re-select the IP clock (the same clk) and then click Estimate. if not reselect |
| * the new clock rate may not be propogate into the IPs. |
| * |
| */ |
| |
| NIUController::NIUController(XMLNode* _xml_data,InputParameter* interface_ip_) |
| : McPATComponent(_xml_data, interface_ip_) { |
| name = "NIU"; |
| set_niu_param(); |
| } |
| |
| void NIUController::computeArea() { |
| double mac_area; |
| double frontend_area; |
| double SerDer_area; |
| |
| if (niup.type == 0) { //high performance NIU |
| //Area estimation based on average of die photo from Niagara 2 and |
| //Cadence ChipEstimate using 65nm. |
| mac_area = (1.53 + 0.3) / 2 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065); |
| //Area estimation based on average of die photo from Niagara 2, ISSCC |
| //"An 800mW 10Gb Ethernet Transceiver in 0.13μm CMOS" |
| //and"A 1.2-V-Only 900-mW 10 Gb Ethernet Transceiver and XAUI Interface |
| //With Robust VCO Tuning Technique" Frontend is PCS |
| frontend_area = (9.8 + (6 + 18) * 65 / 130 * 65 / 130) / 3 * |
| (interface_ip.F_sz_um / 0.065) * (interface_ip.F_sz_um / 0.065); |
| //Area estimation based on average of die photo from Niagara 2 and |
| //Cadence ChipEstimate hard IP @65nm. |
| //SerDer is very hard to scale |
| SerDer_area = (1.39 + 0.36) * (interface_ip.F_sz_um / |
| 0.065);//* (interface_ip.F_sz_um/0.065); |
| } else { |
| //Low power implementations are mostly from Cadence ChipEstimator; |
| //Ignore the multiple IP effect |
| // ---When there are multiple IP (same kind or not) selected, Cadence |
| //ChipEstimator results are not a simple summation of all IPs. |
| //Ignore this effect |
| mac_area = 0.24 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065); |
| frontend_area = 0.1 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065);//Frontend is the PCS layer |
| SerDer_area = 0.35 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um/0.065); |
| //Compare 130um implementation in "A 1.2-V-Only 900-mW 10 Gb Ethernet |
| //Transceiver and XAUI Interface With Robust VCO Tuning Technique" |
| //and the ChipEstimator XAUI PHY hard IP, confirm that even PHY can |
| //scale perfectly with the technology |
| } |
| |
| //total area |
| output_data.area = (mac_area + frontend_area + SerDer_area) * 1e6; |
| } |
| |
| void NIUController::computeEnergy() { |
| double mac_dyn; |
| double frontend_dyn; |
| double SerDer_dyn; |
| double frontend_gates; |
| double mac_gates; |
| double SerDer_gates; |
| double NMOS_sizing; |
| double PMOS_sizing; |
| double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio(); |
| |
| if (niup.type == 0) { //high performance NIU |
| //Power |
| //Cadence ChipEstimate using 65nm (mac, front_end are all energy. |
| //E=P*T = P/F = 1.37/1Ghz = 1.37e-9); |
| //2.19W@1GHz fully active according to Cadence ChipEstimate @65nm |
| mac_dyn = 2.19e-9 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd / |
| 1.1 * (interface_ip.F_sz_nm / 65.0);//niup.clockRate; |
| //Cadence ChipEstimate using 65nm soft IP; |
| frontend_dyn = 0.27e-9 * g_tp.peri_global.Vdd / 1.1 * |
| g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0); |
| //according to "A 100mW 9.6Gb/s Transceiver in 90nm CMOS..." ISSCC 2006 |
| //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm |
| SerDer_dyn = 0.01 * 10 * sqrt(interface_ip.F_sz_um / 0.09) * |
| g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2; |
| |
| //Cadence ChipEstimate using 65nm |
| mac_gates = 111700; |
| frontend_gates = 320000; |
| SerDer_gates = 200000; |
| NMOS_sizing = 5 * g_tp.min_w_nmos_; |
| PMOS_sizing = 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; |
| } else { |
| //Power |
| //Cadence ChipEstimate using 65nm (mac, front_end are all energy. |
| ///E=P*T = P/F = 1.37/1Ghz = 1.37e-9); |
| //2.19W@1GHz fully active according to Cadence ChipEstimate @65nm |
| mac_dyn = 1.257e-9 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd |
| / 1.1 * (interface_ip.F_sz_nm / 65.0);//niup.clockRate; |
| //Cadence ChipEstimate using 65nm soft IP; |
| frontend_dyn = 0.6e-9 * g_tp.peri_global.Vdd / 1.1 * |
| g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0); |
| //SerDer_dyn is power not energy, scaling from 216mw/10Gb/s @130nm |
| SerDer_dyn = 0.0216 * 10 * (interface_ip.F_sz_um / 0.13) * |
| g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2; |
| |
| mac_gates = 111700; |
| frontend_gates = 52000; |
| SerDer_gates = 199260; |
| NMOS_sizing = g_tp.min_w_nmos_; |
| PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; |
| } |
| |
| //covert to energy per clock cycle of whole NIU |
| SerDer_dyn /= niup.clockRate; |
| |
| power.readOp.dynamic = mac_dyn + frontend_dyn + SerDer_dyn; |
| power.readOp.leakage = (mac_gates + frontend_gates + frontend_gates) * |
| cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * |
| g_tp.peri_global.Vdd;//unit W |
| double long_channel_device_reduction = |
| longer_channel_device_reduction(Uncore_device); |
| power.readOp.longer_channel_leakage = |
| power.readOp.leakage * long_channel_device_reduction; |
| power.readOp.gate_leakage = (mac_gates + frontend_gates + frontend_gates) * |
| cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * |
| g_tp.peri_global.Vdd;//unit W |
| |
| // Output power |
| output_data.subthreshold_leakage_power = |
| longer_channel_device ? power.readOp.longer_channel_leakage : |
| power.readOp.leakage; |
| output_data.gate_leakage_power = power.readOp.gate_leakage; |
| output_data.peak_dynamic_power = power.readOp.dynamic * nius.duty_cycle; |
| output_data.runtime_dynamic_energy = power.readOp.dynamic * nius.perc_load; |
| } |
| |
| void NIUController::set_niu_param() { |
| int num_children = xml_data->nChildNode("param"); |
| int i; |
| for (i = 0; i < num_children; i++) { |
| XMLNode* paramNode = xml_data->getChildNodePtr("param", &i); |
| XMLCSTR node_name = paramNode->getAttribute("name"); |
| XMLCSTR value = paramNode->getAttribute("value"); |
| |
| if (!node_name) |
| warnMissingParamName(paramNode->getAttribute("id")); |
| |
| ASSIGN_FP_IF("niu_clockRate", niup.clockRate); |
| ASSIGN_INT_IF("num_units", niup.num_units); |
| ASSIGN_INT_IF("type", niup.type); |
| |
| else { |
| warnUnrecognizedParam(node_name); |
| } |
| } |
| |
| // Change from MHz to Hz |
| niup.clockRate *= 1e6; |
| |
| num_children = xml_data->nChildNode("stat"); |
| for (i = 0; i < num_children; i++) { |
| XMLNode* statNode = xml_data->getChildNodePtr("stat", &i); |
| XMLCSTR node_name = statNode->getAttribute("name"); |
| XMLCSTR value = statNode->getAttribute("value"); |
| |
| if (!node_name) |
| warnMissingStatName(statNode->getAttribute("id")); |
| |
| ASSIGN_FP_IF("duty_cycle", nius.duty_cycle); |
| ASSIGN_FP_IF("perc_load", nius.perc_load); |
| |
| else { |
| warnUnrecognizedStat(node_name); |
| } |
| } |
| } |
| |
| PCIeController::PCIeController(XMLNode* _xml_data, |
| InputParameter* interface_ip_) |
| : McPATComponent(_xml_data, interface_ip_) { |
| name = "PCIe"; |
| set_pcie_param(); |
| } |
| |
| void PCIeController::computeArea() { |
| double ctrl_area; |
| double SerDer_area; |
| |
| /* Assuming PCIe is bit-slice based architecture |
| * This is the reason for /8 in both area and power calculation |
| * to get per lane numbers |
| */ |
| |
| if (pciep.type == 0) { //high performance PCIe |
| //Area estimation based on average of die photo from Niagara 2 and |
| //Cadence ChipEstimate @ 65nm. |
| ctrl_area = (5.2 + 0.5) / 2 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065); |
| //Area estimation based on average of die photo from Niagara 2 and |
| //Cadence ChipEstimate hard IP @65nm. |
| //SerDer is very hard to scale |
| SerDer_area = (3.03 + 0.36) * (interface_ip.F_sz_um / |
| 0.065);//* (interface_ip.F_sz_um/0.065); |
| } else { |
| ctrl_area = 0.412 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065); |
| //Area estimation based on average of die photo from Niagara 2, and |
| //Cadence ChipEstimate @ 65nm. |
| SerDer_area = 0.36 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065); |
| } |
| |
| // Total area |
| output_data.area = ((ctrl_area + (pciep.withPHY ? SerDer_area : 0)) / 8 * |
| pciep.num_channels) * 1e6; |
| } |
| |
| void PCIeController::computeEnergy() { |
| double ctrl_dyn; |
| double SerDer_dyn; |
| double ctrl_gates; |
| double SerDer_gates = 0; |
| double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio(); |
| double NMOS_sizing; |
| double PMOS_sizing; |
| |
| /* Assuming PCIe is bit-slice based architecture |
| * This is the reason for /8 in both area and power calculation |
| * to get per lane numbers |
| */ |
| |
| if (pciep.type == 0) { //high performance PCIe |
| //Power |
| //Cadence ChipEstimate using 65nm the controller includes everything: the PHY, the data link and transaction layer |
| ctrl_dyn = 3.75e-9 / 8 * g_tp.peri_global.Vdd / 1.1 * |
| g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0); |
| // //Cadence ChipEstimate using 65nm soft IP; |
| // 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); |
| //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm |
| //PCIe 2.0 max per lane speed is 4Gb/s |
| SerDer_dyn = 0.01 * 4 * (interface_ip.F_sz_um /0.09) * |
| g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd /1.2; |
| |
| //Cadence ChipEstimate using 65nm |
| ctrl_gates = 900000 / 8 * pciep.num_channels; |
| // frontend_gates = 120000/8; |
| // SerDer_gates = 200000/8; |
| NMOS_sizing = 5 * g_tp.min_w_nmos_; |
| PMOS_sizing = 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; |
| } else { |
| //Power |
| //Cadence ChipEstimate using 65nm the controller includes everything: the PHY, the data link and transaction layer |
| ctrl_dyn = 2.21e-9 / 8 * g_tp.peri_global.Vdd / 1.1 * |
| g_tp.peri_global.Vdd / 1.1 * (interface_ip.F_sz_nm / 65.0); |
| // //Cadence ChipEstimate using 65nm soft IP; |
| // 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); |
| //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm |
| //PCIe 2.0 max per lane speed is 4Gb/s |
| SerDer_dyn = 0.01 * 4 * (interface_ip.F_sz_um / 0.09) * |
| g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd /1.2; |
| |
| //Cadence ChipEstimate using 65nm |
| ctrl_gates = 200000 / 8 * pciep.num_channels; |
| // frontend_gates = 120000/8; |
| SerDer_gates = 200000 / 8 * pciep.num_channels; |
| NMOS_sizing = g_tp.min_w_nmos_; |
| PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; |
| |
| } |
| |
| //covert to energy per clock cycle |
| SerDer_dyn /= pciep.clockRate; |
| |
| power.readOp.dynamic = (ctrl_dyn + (pciep.withPHY ? SerDer_dyn : 0)) * |
| pciep.num_channels; |
| power.readOp.leakage = (ctrl_gates + (pciep.withPHY ? SerDer_gates : 0)) * |
| cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * |
| g_tp.peri_global.Vdd;//unit W |
| double long_channel_device_reduction = |
| longer_channel_device_reduction(Uncore_device); |
| power.readOp.longer_channel_leakage = |
| power.readOp.leakage * long_channel_device_reduction; |
| power.readOp.gate_leakage = (ctrl_gates + |
| (pciep.withPHY ? SerDer_gates : 0)) * |
| cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * |
| g_tp.peri_global.Vdd;//unit W |
| |
| // Output power |
| output_data.subthreshold_leakage_power = |
| longer_channel_device ? power.readOp.longer_channel_leakage : |
| power.readOp.leakage; |
| output_data.gate_leakage_power = power.readOp.gate_leakage; |
| output_data.peak_dynamic_power = power.readOp.dynamic * pcies.duty_cycle; |
| output_data.runtime_dynamic_energy = |
| power.readOp.dynamic * pcies.perc_load; |
| } |
| |
| void PCIeController::set_pcie_param() { |
| int num_children = xml_data->nChildNode("param"); |
| int i; |
| for (i = 0; i < num_children; i++) { |
| XMLNode* paramNode = xml_data->getChildNodePtr("param", &i); |
| XMLCSTR node_name = paramNode->getAttribute("name"); |
| XMLCSTR value = paramNode->getAttribute("value"); |
| |
| if (!node_name) |
| warnMissingParamName(paramNode->getAttribute("id")); |
| |
| ASSIGN_FP_IF("pcie_clockRate", pciep.clockRate); |
| ASSIGN_INT_IF("num_units", pciep.num_units); |
| ASSIGN_INT_IF("num_channels", pciep.num_channels); |
| ASSIGN_INT_IF("type", pciep.type); |
| ASSIGN_ENUM_IF("withPHY", pciep.withPHY, bool); |
| |
| else { |
| warnUnrecognizedParam(node_name); |
| } |
| } |
| |
| // Change from MHz to Hz |
| pciep.clockRate *= 1e6; |
| |
| num_children = xml_data->nChildNode("stat"); |
| for (i = 0; i < num_children; i++) { |
| XMLNode* statNode = xml_data->getChildNodePtr("stat", &i); |
| XMLCSTR node_name = statNode->getAttribute("name"); |
| XMLCSTR value = statNode->getAttribute("value"); |
| |
| if (!node_name) |
| warnMissingStatName(statNode->getAttribute("id")); |
| |
| ASSIGN_FP_IF("duty_cycle", pcies.duty_cycle); |
| ASSIGN_FP_IF("perc_load", pcies.perc_load); |
| |
| else { |
| warnUnrecognizedStat(node_name); |
| } |
| } |
| } |
| |
| FlashController::FlashController(XMLNode* _xml_data, |
| InputParameter* interface_ip_) |
| : McPATComponent(_xml_data, interface_ip_) { |
| name = "Flash Controller"; |
| set_fc_param(); |
| } |
| |
| void FlashController::computeArea() { |
| double ctrl_area; |
| double SerDer_area; |
| |
| /* Assuming Flash is bit-slice based architecture |
| * This is the reason for /8 in both area and power calculation |
| * to get per lane numbers |
| */ |
| |
| if (fcp.type == 0) { //high performance flash controller |
| cout << "Current McPAT does not support high performance flash " |
| << "controller since even low power designs are enough for " |
| << "maintain throughput" <<endl; |
| exit(0); |
| } else { |
| ctrl_area = 0.243 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065); |
| //Area estimation based on Cadence ChipEstimate @ 65nm: NANDFLASH-CTRL |
| //from CAST |
| SerDer_area = 0.36 / 8 * (interface_ip.F_sz_um / 0.065) * |
| (interface_ip.F_sz_um / 0.065); |
| } |
| |
| double number_channel = 1 + (fcp.num_channels - 1) * 0.2; |
| output_data.area = (ctrl_area + (fcp.withPHY ? SerDer_area : 0)) * |
| 1e6 * number_channel; |
| } |
| |
| void FlashController::computeEnergy() { |
| double ctrl_dyn; |
| double SerDer_dyn; |
| double ctrl_gates; |
| double SerDer_gates; |
| double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio(); |
| double NMOS_sizing; |
| double PMOS_sizing; |
| |
| /* Assuming Flash is bit-slice based architecture |
| * This is the reason for /8 in both area and power calculation |
| * to get per lane numbers |
| */ |
| |
| if (fcp.type == 0) { //high performance flash controller |
| cout << "Current McPAT does not support high performance flash " |
| << "controller since even low power designs are enough for " |
| << "maintain throughput" <<endl; |
| exit(0); |
| NMOS_sizing = 5 * g_tp.min_w_nmos_; |
| PMOS_sizing = 5 * g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; |
| } else { |
| //based On PCIe PHY TSMC65GP from Cadence ChipEstimate @ 65nm, it |
| //support 8x lanes with each lane speed up to 250MB/s (PCIe1.1x). |
| //This is already saturate the 200MB/s of the flash controller core |
| //above. |
| ctrl_gates = 129267; |
| SerDer_gates = 200000 / 8; |
| NMOS_sizing = g_tp.min_w_nmos_; |
| PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; |
| |
| //Power |
| //Cadence ChipEstimate using 65nm the controller 125mW for every |
| //200MB/s This is power not energy! |
| ctrl_dyn = 0.125 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd / |
| 1.1 * (interface_ip.F_sz_nm / 65.0); |
| //SerDer_dyn is power not energy, scaling from 10mw/Gb/s @90nm |
| SerDer_dyn = 0.01 * 1.6 * (interface_ip.F_sz_um / 0.09) * |
| g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2; |
| //max Per controller speed is 1.6Gb/s (200MB/s) |
| } |
| |
| double number_channel = 1 + (fcp.num_channels - 1) * 0.2; |
| power.readOp.dynamic = (ctrl_dyn + (fcp.withPHY ? SerDer_dyn : 0)) * |
| number_channel; |
| power.readOp.leakage = ((ctrl_gates + (fcp.withPHY ? SerDer_gates : 0)) * |
| number_channel) * |
| cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * |
| g_tp.peri_global.Vdd;//unit W |
| double long_channel_device_reduction = |
| longer_channel_device_reduction(Uncore_device); |
| power.readOp.longer_channel_leakage = |
| power.readOp.leakage * long_channel_device_reduction; |
| power.readOp.gate_leakage = |
| ((ctrl_gates + (fcp.withPHY ? SerDer_gates : 0)) * number_channel) * |
| cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * |
| g_tp.peri_global.Vdd;//unit W |
| |
| // Output power |
| output_data.subthreshold_leakage_power = |
| longer_channel_device ? power.readOp.longer_channel_leakage : |
| power.readOp.leakage; |
| output_data.gate_leakage_power = power.readOp.gate_leakage; |
| output_data.peak_dynamic_power = power.readOp.dynamic * fcs.duty_cycle; |
| output_data.runtime_dynamic_energy = power.readOp.dynamic * fcs.perc_load; |
| } |
| |
| void FlashController::set_fc_param() |
| { |
| int num_children = xml_data->nChildNode("param"); |
| int i; |
| for (i = 0; i < num_children; i++) { |
| XMLNode* paramNode = xml_data->getChildNodePtr("param", &i); |
| XMLCSTR node_name = paramNode->getAttribute("name"); |
| XMLCSTR value = paramNode->getAttribute("value"); |
| |
| if (!node_name) |
| warnMissingParamName(paramNode->getAttribute("id")); |
| |
| ASSIGN_INT_IF("num_channels", fcp.num_channels); |
| ASSIGN_INT_IF("type", fcp.type); |
| ASSIGN_ENUM_IF("withPHY", fcp.withPHY, bool); |
| |
| else { |
| warnUnrecognizedParam(node_name); |
| } |
| } |
| |
| num_children = xml_data->nChildNode("stat"); |
| for (i = 0; i < num_children; i++) { |
| XMLNode* statNode = xml_data->getChildNodePtr("stat", &i); |
| XMLCSTR node_name = statNode->getAttribute("name"); |
| XMLCSTR value = statNode->getAttribute("value"); |
| |
| if (!node_name) |
| warnMissingStatName(statNode->getAttribute("id")); |
| |
| ASSIGN_FP_IF("duty_cycle", fcs.duty_cycle); |
| ASSIGN_FP_IF("perc_load", fcs.perc_load); |
| |
| else { |
| warnUnrecognizedStat(node_name); |
| } |
| } |
| } |