/***************************************************************************** * McPAT * SOFTWARE LICENSE AGREEMENT * Copyright 2012 Hewlett-Packard Development Company, L.P. * 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.” * ***************************************************************************/ /******************************************************************** * Modified by: ** Jingwen Leng, Univeristy of Texas, Austin * Syed Gilani, *University of Wisconsin–Madison * Tayler Hetherington, *University of British Columbia * Ahmed ElTantawy, University of *British Columbia * ********************************************************************/ // clang-format off #include "io.h" #include "parameter.h" #include "const.h" #include "logic.h" #include "cacti/basic_circuit.h" #include #include #include "XML_Parse.h" #include #include #include #include "memoryctrl.h" #include "basic_components.h" // clang-format on /* overview of MC models: * McPAT memory controllers are modeled according to large number of industrial * data points. The Basic memory controller architecture is base on the Synopsis * designs (DesignWare DDR2/DDR3-Lite memory controllers and DDR2/DDR3-Lite * protocol controllers) as in Cadence ChipEstimator Tool * * An MC has 3 parts as shown in this design. McPAT models both high performance * MC based on Niagara processor designs and curving and low power MC based on * data points in Cadence ChipEstimator Tool. * * The frontend is modeled analytically, the backend is modeled empirically * according to DDR2/DDR3-Lite protocol controllers in Cadence ChipEstimator * Tool The PHY is modeled based on "A 100mW 9.6Gb/s Transceiver in 90nm CMOS * for next-generation memory interfaces ," ISSCC 2006, and A 14mW 6.25Gb/s * Transceiver in 90nm CMOS for Serial Chip-to-Chip Communication," ISSCC 2007 * * In Cadence ChipEstimator Tool there are two types of memory controllers: the * full memory controllers that includes the frontend as the DesignWare * DDR2/DDR3-Lite memory controllers and the backend only memory controllers as * the DDR2/DDR3-Lite protocol controllers (except DesignWare DDR2/DDR3-Lite * memory controllers, all memory controller IP in Cadence ChipEstimator Tool * are backend memory controllers such as DDRC 1600A and DDRC 800A). Thus,to * some extend the area and power difference between DesignWare DDR2/DDR3-Lite * memory controllers and DDR2/DDR3-Lite protocol controllers can be an * estimation to the frontend power and area, which is very close the * analitically modeled results of the frontend for Niagara2@65nm * */ MCBackend::MCBackend(InputParameter* interface_ip_, const MCParam& mcp_, enum MemoryCtrl_type mc_type_) : l_ip(*interface_ip_), mc_type(mc_type_), mcp(mcp_) { local_result = init_interface(&l_ip); compute(); } void MCBackend::compute() { // double max_row_addr_width = 20.0;//Current address 12~18bits double C_MCB, mc_power, backend_dyn, backend_gates; //, refresh_period,refresh_freq;//Equivalent per bit Cap // for backend, double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio(); double NMOS_sizing, PMOS_sizing; if (mc_type == MC) { if (mcp.type == 0) { // area = // (2.2927*log(peakDataTransferRate)-14.504)*memDataWidth/144.0*(l_ip.F_sz_um/0.09); area.set_area((2.7927 * log(mcp.peakDataTransferRate * 2) - 19.862) / 2.0 * mcp.dataBusWidth / 128.0 * (l_ip.F_sz_um / 0.09) * mcp.num_channels * 1e6); // um^2 // assuming the approximately same scaling factor as seen in processors. // C_MCB=0.2/1.3/1.3/266/64/0.09*g_ip.F_sz_um;//based on AMD Geode // processor which has a very basic mc on chip. C_MCB // = 1.6/200/1e6/144/1.2/1.2*g_ip.F_sz_um/0.19;//Based on Niagara power // numbers.The base power (W) is divided by device frequency and vdd and // scale to target process. mc_power = 0.0291*2;//29.1mW@200MHz @130nm // From Power Analysis of SystemLevel OnChip Communication Architectures // by Lahiri et mc_power = 4.32 * 0.1; // 4.32W@1GhzMHz @65nm Cadence ChipEstimator 10% for backend C_MCB = mc_power / 1e9 / 72 / 1.1 / 1.1 * l_ip.F_sz_um / 0.065; power_t.readOp.dynamic = C_MCB * g_tp.peri_global.Vdd * g_tp.peri_global.Vdd * (mcp.dataBusWidth /*+mcp.addressBusWidth*/); // per access energy in // memory controller power_t.readOp.leakage = area.get_area() / 2 * (g_tp.scaling_factor.core_tx_density) * cmos_Isub_leakage(g_tp.min_w_nmos_, g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r, 1, inv) * g_tp.peri_global.Vdd; // unit W power_t.readOp.gate_leakage = area.get_area() / 2 * (g_tp.scaling_factor.core_tx_density) * cmos_Ig_leakage(g_tp.min_w_nmos_, g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r, 1, inv) * g_tp.peri_global.Vdd; // unit W } else { NMOS_sizing = g_tp.min_w_nmos_; PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; area.set_area(0.15 * mcp.dataBusWidth / 72.0 * (l_ip.F_sz_um / 0.065) * (l_ip.F_sz_um / 0.065) * mcp.num_channels * 1e6); // um^2 backend_dyn = 0.9e-9 / 800e6 * mcp.clockRate / 12800 * mcp.peakDataTransferRate * mcp.dataBusWidth / 72.0 * g_tp.peri_global.Vdd / 1.1 * g_tp.peri_global.Vdd / 1.1 * (l_ip.F_sz_nm / 65.0); // Average on DDR2/3 protocol controller and // DDRC 1600/800A in Cadence ChipEstimate // Scaling to technology and DIMM feature. The base IP support // DDR3-1600(PC3 12800) backend_gates = 50000 * mcp.dataBusWidth / 64.0; // 5000 is from Cadence ChipEstimator power_t.readOp.dynamic = backend_dyn; power_t.readOp.leakage = (backend_gates)*cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * g_tp.peri_global.Vdd; // unit W power_t.readOp.gate_leakage = (backend_gates)*cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * g_tp.peri_global.Vdd; // unit W } } else { // skip old model cout << "Unknown memory controllers" << endl; exit(0); area.set_area(0.243 * mcp.dataBusWidth / 8); // area based on Cadence ChipEstimator for 8bit bus // mc_power = 4.32*0.1;//4.32W@1GhzMHz @65nm Cadence ChipEstimator 10% for // backend C_MCB = mc_power / 1e9 / 72 / 1.1 / 1.1 * l_ip.F_sz_um / 0.065; power_t.readOp.leakage = area.get_area() / 2 * (g_tp.scaling_factor.core_tx_density) * cmos_Isub_leakage(g_tp.min_w_nmos_, g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r, 1, inv) * g_tp.peri_global.Vdd; // unit W power_t.readOp.gate_leakage = area.get_area() / 2 * (g_tp.scaling_factor.core_tx_density) * cmos_Ig_leakage(g_tp.min_w_nmos_, g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r, 1, inv) * g_tp.peri_global.Vdd; // unit W power_t.readOp.dynamic *= 1.2; power_t.readOp.leakage *= 1.2; power_t.readOp.gate_leakage *= 1.2; // flash controller has about 20% more backend power since BCH ECC in flash // is complex and power hungry } double long_channel_device_reduction = longer_channel_device_reduction(Uncore_device); power_t.readOp.longer_channel_leakage = power_t.readOp.leakage * long_channel_device_reduction; } void MCBackend::computeEnergy(bool is_tdp) { // backend uses internal data buswidth if (is_tdp) { power.reset(); // Jingwen // init stats for Peak stats_t.readAc.access = 0.5 * mcp.num_channels; stats_t.writeAc.access = 0.5 * mcp.num_channels; tdp_stats = stats_t; } else { rt_power.reset(); // Jingwen // init stats for runtime power (RTP) // Jingwen: should use stats from XML object, modified in // MemoryController::computeEnergy stats_t.readAc.access = mcp.reads; stats_t.writeAc.access = mcp.writes; tdp_stats = stats_t; } if (is_tdp) { power = power_t; power.readOp.dynamic = (stats_t.readAc.access + stats_t.writeAc.access) * power_t.readOp.dynamic; } else { rt_power.readOp.dynamic = (stats_t.readAc.access + stats_t.writeAc.access) * mcp.llcBlockSize * 8.0 / mcp.dataBusWidth * power_t.readOp.dynamic; rt_power = rt_power + power_t * pppm_lkg; rt_power.readOp.dynamic = rt_power.readOp.dynamic + power.readOp.dynamic * 0.1 * mcp.clockRate * mcp.num_mcs * mcp.executionTime; // Assume 10% of peak power is consumed by routine job including memory // refreshing and scrubbing } } MCPHY::MCPHY(InputParameter* interface_ip_, const MCParam& mcp_, enum MemoryCtrl_type mc_type_) : l_ip(*interface_ip_), mc_type(mc_type_), mcp(mcp_) { local_result = init_interface(&l_ip); compute(); } void MCPHY::compute() { // PHY uses internal data buswidth but the actuall off-chip datawidth is // 64bits + ecc double pmos_to_nmos_sizing_r = pmos_to_nmos_sz_ratio(); /* * according to "A 100mW 9.6Gb/s Transceiver in 90nm CMOS for next-generation * memory interfaces ," ISSCC 2006; From Cadence ChipEstimator for normal I/O * around 0.4~0.8 mW/Gb/s */ double power_per_gb_per_s, phy_gates, NMOS_sizing, PMOS_sizing; if (mc_type == MC) { if (mcp.type == 0) { power_per_gb_per_s = mcp.LVDS ? 0.01 : 0.04; // Based on die photos from Niagara 1 and 2. // TODO merge this into undifferentiated core.PHY only achieves square // root of the ideal scaling. area = // (6.4323*log(peakDataTransferRate)-34.76)*memDataWidth/128.0*(l_ip.F_sz_um/0.09); area.set_area((6.4323 * log(mcp.peakDataTransferRate * 2) - 48.134) * mcp.dataBusWidth / 128.0 * (l_ip.F_sz_um / 0.09) * mcp.num_channels * 1e6 / 2); // TODO:/2 // This is from curve fitting based on Niagara 1 and 2's PHY die photo. // This is power not energy, 10mw/Gb/s @90nm for each channel and scaling // down power.readOp.dynamic = 0.02*memAccesses*llcBlocksize*8;//change // from Bytes to bits. power_t.readOp.dynamic = power_per_gb_per_s * sqrt(l_ip.F_sz_um / 0.09) * g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2; power_t.readOp.leakage = area.get_area() / 2 * (g_tp.scaling_factor.core_tx_density) * cmos_Isub_leakage(g_tp.min_w_nmos_, g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r, 1, inv) * g_tp.peri_global.Vdd; // unit W power_t.readOp.gate_leakage = area.get_area() / 2 * (g_tp.scaling_factor.core_tx_density) * cmos_Ig_leakage(g_tp.min_w_nmos_, g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r, 1, inv) * g_tp.peri_global.Vdd; // unit W } else { NMOS_sizing = g_tp.min_w_nmos_; PMOS_sizing = g_tp.min_w_nmos_ * pmos_to_nmos_sizing_r; // Designware/synopsis 16bit DDR3 PHY is 1.3mm (WITH IOs) at 40nm for upto // DDR3 2133 (PC3 17066) double non_IO_percentage = 0.2; area.set_area(1.3 * non_IO_percentage / 2133.0e6 * mcp.clockRate / 17066 * mcp.peakDataTransferRate * mcp.dataBusWidth / 16.0 * (l_ip.F_sz_um / 0.040) * (l_ip.F_sz_um / 0.040) * mcp.num_channels * 1e6); // um^2 phy_gates = 200000 * mcp.dataBusWidth / 64.0; power_per_gb_per_s = 0.01; // This is power not energy, 10mw/Gb/s @90nm for each channel and scaling // down power_t.readOp.dynamic = power_per_gb_per_s * (l_ip.F_sz_um / 0.09) * g_tp.peri_global.Vdd / 1.2 * g_tp.peri_global.Vdd / 1.2; power_t.readOp.leakage = (mcp.withPHY ? phy_gates : 0) * cmos_Isub_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * g_tp.peri_global.Vdd; // unit W power_t.readOp.gate_leakage = (mcp.withPHY ? phy_gates : 0) * cmos_Ig_leakage(NMOS_sizing, PMOS_sizing, 2, nand) * g_tp.peri_global.Vdd; // unit W } } else { area.set_area(0.4e6 / 2 * mcp.dataBusWidth / 8); // area based on Cadence ChipEstimator for 8bit bus } // double phy_factor = (int)ceil(mcp.dataBusWidth/72.0);//Previous phy power // numbers are based on 72 bit DIMM interface power_t.readOp.dynamic *= // phy_factor; power_t.readOp.leakage *= phy_factor; // power_t.readOp.gate_leakage *= phy_factor; double long_channel_device_reduction = longer_channel_device_reduction(Uncore_device); power_t.readOp.longer_channel_leakage = power_t.readOp.leakage * long_channel_device_reduction; } void MCPHY::computeEnergy(bool is_tdp) { if (is_tdp) { power.reset(); // Jingwen // init stats for Peak stats_t.readAc.access = 0.5 * mcp.num_channels; // time share on buses stats_t.writeAc.access = 0.5 * mcp.num_channels; tdp_stats = stats_t; } else { rt_power.reset(); // Jingwen // init stats for runtime power (RTP) // Jingwen: should use stats from XML object, modified in // MemoryController::computeEnergy stats_t.readAc.access = mcp.reads; stats_t.writeAc.access = mcp.writes; tdp_stats = stats_t; } if (is_tdp) { double data_transfer_unit = (mc_type == MC) ? 72 : 16; /*DIMM data width*/ power = power_t; power.readOp.dynamic = power.readOp.dynamic * (mcp.peakDataTransferRate * 8 * 1e6 / 1e9 /*change to Gbs*/) * mcp.dataBusWidth / data_transfer_unit * mcp.num_channels / mcp.clockRate; // divide by clock rate is for match the final computation where *clock is // used //(stats_t.readAc.access*power_t.readOp.dynamic+ // stats_t.writeAc.access*power_t.readOp.dynamic); } else { rt_power = power_t; // rt_power.readOp.dynamic = // (stats_t.readAc.access*power_t.readOp.dynamic+ // stats_t.writeAc.access*power_t.readOp.dynamic); rt_power.readOp.dynamic = power_t.readOp.dynamic * (stats_t.readAc.access + stats_t.writeAc.access) * (mcp.llcBlockSize) * 8 / 1e9 / mcp.executionTime * (mcp.executionTime); rt_power.readOp.dynamic = rt_power.readOp.dynamic + power.readOp.dynamic * 0.1 * mcp.clockRate * mcp.num_mcs * mcp.executionTime; } } MCFrontEnd::MCFrontEnd(ParseXML* XML_interface, InputParameter* interface_ip_, const MCParam& mcp_, enum MemoryCtrl_type mc_type_) : XML(XML_interface), interface_ip(*interface_ip_), mc_type(mc_type_), mcp(mcp_), MC_arb(0), frontendBuffer(0), readBuffer(0), writeBuffer(0), coalesce_scale(1.0) { /* All computations are for a single MC * */ int tag, data; bool is_default = true; // indication for default setup /* MC frontend engine channels share the same engines but logically * partitioned For all hardware inside MC. different channels do not share * resources. * TODO: add docodeing/mux stage to steer memory requests to different * channels. */ // memory request reorder buffer tag = mcp.addressBusWidth + EXTRA_TAG_BITS + mcp.opcodeW; data = int(ceil((XML->sys.physical_address_width + mcp.opcodeW) / 8.0)); interface_ip.cache_sz = data * XML->sys.mc.req_window_size_per_channel; interface_ip.line_sz = data; interface_ip.assoc = 0; interface_ip.nbanks = 1; interface_ip.out_w = interface_ip.line_sz * 8; interface_ip.specific_tag = 1; interface_ip.tag_w = tag; interface_ip.access_mode = 0; interface_ip.throughput = 1.0 / mcp.clockRate; interface_ip.latency = 1.0 / mcp.clockRate; interface_ip.is_cache = true; interface_ip.pure_cam = false; interface_ip.pure_ram = false; interface_ip.obj_func_dyn_energy = 0; interface_ip.obj_func_dyn_power = 0; interface_ip.obj_func_leak_power = 0; interface_ip.obj_func_cycle_t = 1; interface_ip.num_rw_ports = 0; interface_ip.num_rd_ports = XML->sys.mc.memory_channels_per_mc; interface_ip.num_wr_ports = interface_ip.num_rd_ports; interface_ip.num_se_rd_ports = 0; interface_ip.num_search_ports = XML->sys.mc.memory_channels_per_mc; frontendBuffer = new ArrayST(&interface_ip, "MC ReorderBuffer", Uncore_device); frontendBuffer->area.set_area(frontendBuffer->area.get_area() + frontendBuffer->local_result.area * XML->sys.mc.memory_channels_per_mc); area.set_area(area.get_area() + frontendBuffer->local_result.area * XML->sys.mc.memory_channels_per_mc); // selection and arbitration logic MC_arb = new selection_logic(is_default, XML->sys.mc.req_window_size_per_channel, 1, &interface_ip, Uncore_device); // read buffers. data = (int)ceil(mcp.dataBusWidth / 8.0); // Support key words first operation // //8 means converting bit to Byte interface_ip.cache_sz = data * XML->sys.mc.IO_buffer_size_per_channel; //*llcBlockSize; interface_ip.line_sz = data; interface_ip.assoc = 1; interface_ip.nbanks = 1; interface_ip.out_w = interface_ip.line_sz * 8; interface_ip.access_mode = 1; interface_ip.throughput = 1.0 / mcp.clockRate; interface_ip.latency = 2.0 / mcp.clockRate; interface_ip.is_cache = false; interface_ip.pure_cam = false; interface_ip.pure_ram = true; interface_ip.obj_func_dyn_energy = 0; interface_ip.obj_func_dyn_power = 0; interface_ip.obj_func_leak_power = 0; interface_ip.obj_func_cycle_t = 1; interface_ip.num_rw_ports = 0; // XML->sys.mc.memory_channels_per_mc*2>2?2:XML->sys.mc.memory_channels_per_mc*2; interface_ip.num_rd_ports = XML->sys.mc.memory_channels_per_mc; interface_ip.num_wr_ports = interface_ip.num_rd_ports; interface_ip.num_se_rd_ports = 0; readBuffer = new ArrayST(&interface_ip, "MC ReadBuffer", Uncore_device); readBuffer->area.set_area(readBuffer->area.get_area() + readBuffer->local_result.area * XML->sys.mc.memory_channels_per_mc); area.set_area(area.get_area() + readBuffer->local_result.area * XML->sys.mc.memory_channels_per_mc); // write buffer data = (int)ceil(mcp.dataBusWidth / 8.0); // Support key words first operation // //8 means converting bit to Byte interface_ip.cache_sz = data * XML->sys.mc.IO_buffer_size_per_channel; //*llcBlockSize; interface_ip.line_sz = data; interface_ip.assoc = 1; interface_ip.nbanks = 1; interface_ip.out_w = interface_ip.line_sz * 8; interface_ip.access_mode = 0; interface_ip.throughput = 1.0 / mcp.clockRate; interface_ip.latency = 2.0 / mcp.clockRate; interface_ip.obj_func_dyn_energy = 0; interface_ip.obj_func_dyn_power = 0; interface_ip.obj_func_leak_power = 0; interface_ip.obj_func_cycle_t = 1; interface_ip.num_rw_ports = 0; interface_ip.num_rd_ports = XML->sys.mc.memory_channels_per_mc; interface_ip.num_wr_ports = interface_ip.num_rd_ports; interface_ip.num_se_rd_ports = 0; writeBuffer = new ArrayST(&interface_ip, "MC writeBuffer", Uncore_device); writeBuffer->area.set_area(writeBuffer->area.get_area() + writeBuffer->local_result.area * XML->sys.mc.memory_channels_per_mc); area.set_area(area.get_area() + writeBuffer->local_result.area * XML->sys.mc.memory_channels_per_mc); // SRAM structures for memory coalescing --Syed Gilani // Pending Request Table (base addresses, offset addresses, threads IDs), // Thread Masks //***PRT // We assume 24 bits of base address and 8 bits of offset address. // THese values are used for coalesing memory requests to the same base // address block. TIDs are assumed to be 8 bits /*Contents of each PRT entry * * Warp ID (6 bits) | Memory address (32 bits) per thread | Request Size * (2-bits) per thread | line size= 6+ 32*16 + 2*16 ~ 64 bytes * * */ data = 64; // Support key words first operation //8 means converting bit to Byte interface_ip.cache_sz = data * XML->sys.mc.PRT_entries; // PRT table; interface_ip.line_sz = data; interface_ip.assoc = 1; interface_ip.nbanks = 1; interface_ip.out_w = interface_ip.line_sz * 8; interface_ip.access_mode = 0; interface_ip.throughput = 1.0 / XML->sys.target_core_clockrate; interface_ip.latency = 2.0 / XML->sys.target_core_clockrate; interface_ip.obj_func_dyn_energy = 0; interface_ip.obj_func_dyn_power = 0; interface_ip.obj_func_leak_power = 0; interface_ip.obj_func_cycle_t = 1; interface_ip.num_rw_ports = 0; interface_ip.num_rd_ports = 1; interface_ip.num_wr_ports = 1; interface_ip.num_se_rd_ports = 0; PRT = new ArrayST(&interface_ip, "MC PRT", Uncore_device); PRT->area.set_area(PRT->area.get_area() + PRT->local_result.area * XML->sys.mc.memory_channels_per_mc); area.set_area(area.get_area() + PRT->local_result.area * XML->sys.mc.memory_channels_per_mc); //***ThreadMasks storage (coalesced threads whose memory requests are // satisfied by each memory access) /* contents of the thread masks Array * 16-bit bit masks for up to 16 memory requests of a warp | Number of * pending memory requests (5 bits) * * 16*PRT_entry thread Mask, each entry has 16 mask bits. * */ data = 2; interface_ip.cache_sz = data * XML->sys.mc.PRT_entries * 16; // PRT table; interface_ip.line_sz = data; interface_ip.assoc = 1; interface_ip.nbanks = 1; interface_ip.out_w = interface_ip.line_sz * 8; interface_ip.access_mode = 0; interface_ip.throughput = 1.0 / XML->sys.target_core_clockrate; interface_ip.latency = 2.0 / XML->sys.target_core_clockrate; interface_ip.obj_func_dyn_energy = 0; interface_ip.obj_func_dyn_power = 0; interface_ip.obj_func_leak_power = 0; interface_ip.obj_func_cycle_t = 1; interface_ip.num_rw_ports = 0; interface_ip.num_rd_ports = 1; interface_ip.num_wr_ports = 1; interface_ip.num_se_rd_ports = 0; threadMasks = new ArrayST(&interface_ip, "MC ThreadMasks", Uncore_device); threadMasks->area.set_area(threadMasks->area.get_area() + threadMasks->local_result.area * XML->sys.mc.memory_channels_per_mc); area.set_area(area.get_area() + threadMasks->local_result.area * XML->sys.mc.memory_channels_per_mc); //***Numer of pending requests per PRT entry /* * 1-byte data, PRT entries deep */ data = 1; interface_ip.cache_sz = data * XML->sys.mc.PRT_entries; // PRT table; interface_ip.line_sz = data; interface_ip.assoc = 1; interface_ip.nbanks = 1; interface_ip.out_w = interface_ip.line_sz * 8; interface_ip.access_mode = 0; interface_ip.throughput = 1.0 / XML->sys.target_core_clockrate; interface_ip.latency = 2.0 / XML->sys.target_core_clockrate; interface_ip.obj_func_dyn_energy = 0; interface_ip.obj_func_dyn_power = 0; interface_ip.obj_func_leak_power = 0; interface_ip.obj_func_cycle_t = 1; interface_ip.num_rw_ports = 0; interface_ip.num_rd_ports = 1; interface_ip.num_wr_ports = 1; interface_ip.num_se_rd_ports = 0; PRC = new ArrayST(&interface_ip, "MC PendingRequestCount", Uncore_device); PRC->area.set_area(PRC->area.get_area() + PRC->local_result.area * XML->sys.mc.memory_channels_per_mc); area.set_area(area.get_area() + PRC->local_result.area * XML->sys.mc.memory_channels_per_mc); } void DRAM::computeEnergy(bool is_tdp) { if (is_tdp) { power.reset(); return; /// not supporting TDP calculation for DRAM } rt_power.reset(); dramp.executionTime = XML->sys.total_cycles / (XML->sys.target_core_clockrate * 1e6); power_t.reset(); power_t.readOp.dynamic += XML->sys.mc.memory_reads * dramp.rd_coeff; power_t.readOp.dynamic += XML->sys.mc.memory_writes * dramp.wr_coeff; power_t.readOp.dynamic += XML->sys.mc.dram_pre * dramp.pre_coeff; rt_power = rt_power + power_t; } void MCFrontEnd::computeEnergy(bool is_tdp) { if (is_tdp) { power.reset(); // init stats for Peak frontendBuffer->stats_t.readAc.access = frontendBuffer->l_ip.num_search_ports; frontendBuffer->stats_t.writeAc.access = frontendBuffer->l_ip.num_wr_ports; frontendBuffer->tdp_stats = frontendBuffer->stats_t; readBuffer->stats_t.readAc.access = readBuffer->l_ip.num_rd_ports * mcp.frontend_duty_cycle; readBuffer->stats_t.writeAc.access = readBuffer->l_ip.num_wr_ports * mcp.frontend_duty_cycle; readBuffer->tdp_stats = readBuffer->stats_t; writeBuffer->stats_t.readAc.access = writeBuffer->l_ip.num_rd_ports * mcp.frontend_duty_cycle; writeBuffer->stats_t.writeAc.access = writeBuffer->l_ip.num_wr_ports * mcp.frontend_duty_cycle; writeBuffer->tdp_stats = writeBuffer->stats_t; PRT->stats_t.readAc.access = PRT->l_ip.num_rd_ports * mcp.frontend_duty_cycle; PRT->stats_t.writeAc.access = PRT->l_ip.num_wr_ports * mcp.frontend_duty_cycle; PRT->tdp_stats = PRT->stats_t; threadMasks->stats_t.readAc.access = threadMasks->l_ip.num_rd_ports * mcp.frontend_duty_cycle; threadMasks->stats_t.writeAc.access = threadMasks->l_ip.num_wr_ports * mcp.frontend_duty_cycle; threadMasks->tdp_stats = threadMasks->stats_t; PRC->stats_t.readAc.access = threadMasks->l_ip.num_rd_ports * mcp.frontend_duty_cycle; PRC->stats_t.writeAc.access = threadMasks->l_ip.num_wr_ports * mcp.frontend_duty_cycle; PRC->tdp_stats = threadMasks->stats_t; } else { rt_power.reset(); // Jingwen // init stats for runtime power (RTP) frontendBuffer->stats_t.readAc.access = XML->sys.mc.memory_reads * mcp.llcBlockSize * 8.0 / mcp.dataBusWidth * mcp.dataBusWidth / 72; // For each channel, each memory word need to check the address data to // achieve best scheduling results. and this need to be done on all physical // DIMMs in each logical memory DIMM *mcp.dataBusWidth/72 frontendBuffer->stats_t.writeAc.access = XML->sys.mc.memory_writes * mcp.llcBlockSize * 8.0 / mcp.dataBusWidth * mcp.dataBusWidth / 72; frontendBuffer->rtp_stats = frontendBuffer->stats_t; readBuffer->stats_t.readAc.access = XML->sys.mc.memory_reads * mcp.llcBlockSize * 8.0 / mcp.dataBusWidth; // support key word first readBuffer->stats_t.writeAc.access = XML->sys.mc.memory_reads * mcp.llcBlockSize * 8.0 / mcp.dataBusWidth; // support key word first readBuffer->rtp_stats = readBuffer->stats_t; writeBuffer->stats_t.readAc.access = XML->sys.mc.memory_writes * mcp.llcBlockSize * 8.0 / mcp.dataBusWidth; writeBuffer->stats_t.writeAc.access = XML->sys.mc.memory_writes * mcp.llcBlockSize * 8.0 / mcp.dataBusWidth; writeBuffer->rtp_stats = writeBuffer->stats_t; // Pending request table // Co-alesce all misses in caches and add an entry for them in PRT // TODO: Change 0 to ithCore and move to LSU (Syed) // TODO: Do these accesses represent coalesced accesses? PRT->stats_t.readAc.access = XML->sys.core[0].dcache.read_accesses + XML->sys.core[0].ccache.read_accesses + XML->sys.core[0].tcache.read_accesses; PRT->stats_t.writeAc.access = XML->sys.core[0].dcache.write_accesses + XML->sys.core[0].ccache.write_accesses + XML->sys.core[0].tcache.write_accesses; PRT->rtp_stats = PRT->stats_t; threadMasks->stats_t.readAc.access = XML->sys.core[0].dcache.read_accesses + XML->sys.core[0].ccache.read_accesses + XML->sys.core[0].tcache.read_accesses; threadMasks->stats_t.writeAc.access = XML->sys.core[0].dcache.write_accesses + XML->sys.core[0].ccache.write_accesses + XML->sys.core[0].tcache.write_accesses; threadMasks->rtp_stats = threadMasks->stats_t; PRC->stats_t.readAc.access = XML->sys.core[0].dcache.read_accesses + XML->sys.core[0].ccache.read_accesses + XML->sys.core[0].tcache.read_accesses; PRC->stats_t.writeAc.access = XML->sys.core[0].dcache.write_accesses + XML->sys.core[0].ccache.write_accesses + XML->sys.core[0].tcache.write_accesses; PRC->rtp_stats = threadMasks->stats_t; } frontendBuffer->power_t.reset(); readBuffer->power_t.reset(); writeBuffer->power_t.reset(); threadMasks->power_t.reset(); PRT->power_t.reset(); PRC->power_t.reset(); // frontendBuffer->power_t.readOp.dynamic += //(frontendBuffer->stats_t.readAc.access* // (frontendBuffer->local_result.power.searchOp.dynamic+frontendBuffer->local_result.power.readOp.dynamic)+ // frontendBuffer->stats_t.writeAc.access*frontendBuffer->local_result.power.writeOp.dynamic); frontendBuffer->power_t.readOp.dynamic += (frontendBuffer->stats_t.readAc.access + frontendBuffer->stats_t.writeAc.access) * frontendBuffer->local_result.power.searchOp.dynamic + frontendBuffer->stats_t.readAc.access * frontendBuffer->local_result.power.readOp.dynamic + frontendBuffer->stats_t.writeAc.access * frontendBuffer->local_result.power.writeOp.dynamic; readBuffer->power_t.readOp.dynamic += (readBuffer->stats_t.readAc.access * readBuffer->local_result.power.readOp.dynamic + readBuffer->stats_t.writeAc.access * readBuffer->local_result.power.writeOp.dynamic); writeBuffer->power_t.readOp.dynamic += (writeBuffer->stats_t.readAc.access * writeBuffer->local_result.power.readOp.dynamic + writeBuffer->stats_t.writeAc.access * writeBuffer->local_result.power.writeOp.dynamic); PRT->power_t.readOp.dynamic += (PRT->stats_t.readAc.access * PRT->local_result.power.readOp.dynamic + PRT->stats_t.writeAc.access * PRT->local_result.power.writeOp.dynamic); threadMasks->power_t.readOp.dynamic += (threadMasks->stats_t.readAc.access * threadMasks->local_result.power.readOp.dynamic + threadMasks->stats_t.writeAc.access * threadMasks->local_result.power.writeOp.dynamic); PRC->power_t.readOp.dynamic += (PRC->stats_t.readAc.access * PRC->local_result.power.readOp.dynamic + PRC->stats_t.writeAc.access * PRC->local_result.power.writeOp.dynamic); // Add coalescing logic power (Estimated from Verilog HDL description and // Synopsys PowerCompiler)--Syed #define COALESCE_SCALE 1 double perAccessCoalescingEnergy = coalesce_scale * ((0.443e-3) * (0.5e-9) * g_tp.peri_global.Vdd * g_tp.peri_global.Vdd) / (1 * 1); threadMasks->power_t.readOp.dynamic += (threadMasks->stats_t.readAc.access + threadMasks->stats_t.writeAc.access) * perAccessCoalescingEnergy; // printf("***PRT: %10.30f, threadMasks: %10.30f, PRC: // %10.30f\n",PRT->power_t.readOp.dynamic,threadMasks->power_t.readOp.dynamic,PRC->power_t.readOp.dynamic); // printf("***Accesses: read:%lf // write:%lf\n",threadMasks->stats_t.readAc.access, // threadMasks->stats_t.writeAc.access); if (is_tdp) { power = power + frontendBuffer->power_t + readBuffer->power_t + writeBuffer->power_t + PRT->power_t + threadMasks->power_t + PRC->power_t + (frontendBuffer->local_result.power + readBuffer->local_result.power + writeBuffer->local_result.power + PRT->local_result.power + threadMasks->local_result.power + PRC->local_result.power) * pppm_lkg; } else { rt_power = rt_power + frontendBuffer->power_t + readBuffer->power_t + writeBuffer->power_t + PRT->power_t + threadMasks->power_t + PRC->power_t + (frontendBuffer->local_result.power + readBuffer->local_result.power + writeBuffer->local_result.power + PRT->local_result.power + threadMasks->local_result.power + PRC->local_result.power) * pppm_lkg; rt_power.readOp.dynamic = rt_power.readOp.dynamic + power.readOp.dynamic * 0.1 * mcp.clockRate * mcp.num_mcs * mcp.executionTime; } } void MCFrontEnd::displayEnergy(uint32_t indent, int plevel, bool is_tdp) { string indent_str(indent, ' '); string indent_str_next(indent + 2, ' '); if (is_tdp) { cout << indent_str << "Front End ROB:" << endl; cout << indent_str_next << "Area = " << frontendBuffer->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << frontendBuffer->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << frontendBuffer->power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << frontendBuffer->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << frontendBuffer->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; cout << indent_str << "Read Buffer:" << endl; cout << indent_str_next << "Area = " << readBuffer->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << readBuffer->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << readBuffer->power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << readBuffer->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << readBuffer->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; cout << indent_str << "Write Buffer:" << endl; cout << indent_str_next << "Area = " << writeBuffer->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << writeBuffer->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << writeBuffer->power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << writeBuffer->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << writeBuffer->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; cout << indent_str << "PRT:" << endl; cout << indent_str_next << "Area = " << PRT->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << PRT->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << PRT->power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << PRT->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << PRT->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; cout << indent_str << "Thread Masks and coalescing logic:" << endl; cout << indent_str_next << "Area = " << threadMasks->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << threadMasks->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << threadMasks->power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << threadMasks->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << threadMasks->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; } else { cout << indent_str << "Front End ROB:" << endl; cout << indent_str_next << "Area = " << frontendBuffer->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << frontendBuffer->rt_power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << frontendBuffer->rt_power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << frontendBuffer->rt_power.readOp.gate_leakage << " W" << endl; cout << endl; cout << indent_str << "Read Buffer:" << endl; cout << indent_str_next << "Area = " << readBuffer->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << readBuffer->rt_power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << readBuffer->rt_power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << readBuffer->rt_power.readOp.gate_leakage << " W" << endl; cout << endl; cout << indent_str << "Write Buffer:" << endl; cout << indent_str_next << "Area = " << writeBuffer->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << writeBuffer->rt_power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << writeBuffer->rt_power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << writeBuffer->rt_power.readOp.gate_leakage << " W" << endl; cout << endl; cout << indent_str << "PRT:" << endl; cout << indent_str_next << "Area = " << PRT->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << PRT->rt_power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << PRT->rt_power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << PRT->rt_power.readOp.gate_leakage << " W" << endl; cout << endl; cout << indent_str << "Thread masks and coalescing logic:" << endl; cout << indent_str_next << "Area = " << threadMasks->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << threadMasks->rt_power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << threadMasks->rt_power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << threadMasks->rt_power.readOp.gate_leakage << " W" << endl; } } DRAM::DRAM(ParseXML* XML_interface, InputParameter* interface_ip_, enum Dram_type dram_type_) : XML(XML_interface), interface_ip(*interface_ip_), dram_type(dram_type_) { set_dram_param(); } MemoryController::MemoryController(ParseXML* XML_interface, InputParameter* interface_ip_, enum MemoryCtrl_type mc_type_, enum Dram_type dram_type_) : XML(XML_interface), interface_ip(*interface_ip_), mc_type(mc_type_), frontend(0), transecEngine(0), PHY(0), pipeLogic(0) { /* All computations are for a single MC * */ interface_ip.wire_is_mat_type = 2; interface_ip.wire_os_mat_type = 2; interface_ip.wt = Global; set_mc_param(); frontend = new MCFrontEnd(XML, &interface_ip, mcp, mc_type); dram = new DRAM(XML, &interface_ip, dram_type_); area.set_area(area.get_area() + frontend->area.get_area()); transecEngine = new MCBackend(&interface_ip, mcp, mc_type); area.set_area(area.get_area() + transecEngine->area.get_area()); if (mcp.type == 0 || (mcp.type == 1 && mcp.withPHY)) { PHY = new MCPHY(&interface_ip, mcp, mc_type); area.set_area(area.get_area() + PHY->area.get_area()); } //+++++++++Transaction engine +++++++++++++++++ ////TODO needs better numbers, // Run the RTL code from OpenSparc. // transecEngine.initialize(&interface_ip); // transecEngine.peakDataTransferRate = XML->sys.mem.peak_transfer_rate; // transecEngine.memDataWidth = dataBusWidth; // transecEngine.memRank = XML->sys.mem.number_ranks; // //transecEngine.memAccesses=XML->sys.mc.memory_accesses; // //transecEngine.llcBlocksize=llcBlockSize; // transecEngine.compute(); // transecEngine.area.set_area(XML->sys.mc.memory_channels_per_mc*transecEngine.area.get_area()) // ; area.set_area(area.get_area()+ transecEngine.area.get_area()); // ///cout<<"area="<sys.mem.peak_transfer_rate; // PHY.memDataWidth = dataBusWidth; // //PHY.memAccesses=PHY.peakDataTransferRate;//this is the max power // //PHY.llcBlocksize=llcBlockSize; // PHY.compute(); // PHY.area.set_area(XML->sys.mc.memory_channels_per_mc*PHY.area.get_area()) // ; area.set_area(area.get_area()+ PHY.area.get_area()); /// cout<<"area="<sys.core[0].opcode_width + dataBusWidth; pipeLogic = new // pipeline(is_default, &interface_ip); // //pipeLogic.init_pipeline(is_default, &interface_ip); // pipeLogic->compute_pipeline(); // area.set_area(area.get_area()+ pipeLogic->area.get_area()*1e-6); // area.set_area((area.get_area()+mc_area*1e-6)*1.1);//placement and routing // overhead // // //// //clock //// clockNetwork.init_wire_external(is_default, &interface_ip); //// clockNetwork.clk_area =area*1.1;//10% of placement overhead. /// rule of thumb / clockNetwork.end_wiring_level =5;//toplevel metal / /// clockNetwork.start_wiring_level =5;//toplevel metal / /// clockNetwork.num_regs = pipeLogic.tot_stage_vector; / /// clockNetwork.optimize_wire(); } void MemoryController::computeEnergy(bool is_tdp) { rt_power.reset(); // Jingwen frontend->rt_power.reset(); transecEngine->rt_power.reset(); dram->rt_power.reset(); mcp.executionTime = XML->sys.total_cycles / (XML->sys.target_core_clockrate * 1e6); // Jingwen frontend->mcp.executionTime = XML->sys.total_cycles / (XML->sys.target_core_clockrate * 1e6); // Jingwen transecEngine->mcp.executionTime = XML->sys.total_cycles / (XML->sys.target_core_clockrate * 1e6); // Jingwen /*Jingwen: give stats for backend and phy */ transecEngine->mcp.reads = XML->sys.mc.memory_reads; transecEngine->mcp.writes = XML->sys.mc.memory_writes; // set_mc_param(); frontend->computeEnergy(is_tdp); transecEngine->computeEnergy(is_tdp); dram->computeEnergy(is_tdp); if (mcp.type == 0 || (mcp.type == 1 && mcp.withPHY)) { if (!is_tdp) PHY->rt_power.reset(); // Jingwen PHY->mcp.reads = XML->sys.mc.memory_reads; PHY->mcp.writes = XML->sys.mc.memory_writes; PHY->mcp.executionTime = XML->sys.total_cycles / (XML->sys.target_core_clockrate * 1e6); // Jingwen PHY->computeEnergy(is_tdp); } if (is_tdp) { power = power + frontend->power + transecEngine->power; if (mcp.type == 0 || (mcp.type == 1 && mcp.withPHY)) { power = power + PHY->power; } } else { rt_power = rt_power + frontend->rt_power + transecEngine->rt_power + dram->rt_power; if (mcp.type == 0 || (mcp.type == 1 && mcp.withPHY)) { rt_power = rt_power + PHY->rt_power; } } } void MemoryController::displayEnergy(uint32_t indent, int plevel, bool is_tdp) { string indent_str(indent, ' '); string indent_str_next(indent + 2, ' '); bool long_channel = XML->sys.longer_channel_device; if (is_tdp) { cout << "Memory Controller:" << endl; cout << indent_str << "Area = " << area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str << "Peak Dynamic = " << power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str << "Subthreshold Leakage = " << (long_channel ? power.readOp.longer_channel_leakage : power.readOp.leakage) << " W" << endl; // cout << indent_str<< "Subthreshold Leakage = " << // power.readOp.longer_channel_leakage <<" W" << endl; cout << indent_str << "Gate Leakage = " << power.readOp.gate_leakage << " W" << endl; cout << indent_str << "Runtime Dynamic = " << rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; cout << indent_str << "Front End Engine:" << endl; cout << indent_str_next << "Area = " << frontend->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << frontend->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << (long_channel ? frontend->power.readOp.longer_channel_leakage : frontend->power.readOp.leakage) << " W" << endl; cout << indent_str_next << "Gate Leakage = " << frontend->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << frontend->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; // if (plevel >2){ frontend->displayEnergy(indent + 4, is_tdp); //} cout << indent_str << "Transaction Engine:" << endl; cout << indent_str_next << "Area = " << transecEngine->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << transecEngine->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << (long_channel ? transecEngine->power.readOp.longer_channel_leakage : transecEngine->power.readOp.leakage) << " W" << endl; cout << indent_str_next << "Gate Leakage = " << transecEngine->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << transecEngine->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; if (mcp.type == 0 || (mcp.type == 1 && mcp.withPHY)) { cout << indent_str << "PHY:" << endl; cout << indent_str_next << "Area = " << PHY->area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << PHY->power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << (long_channel ? PHY->power.readOp.longer_channel_leakage : PHY->power.readOp.leakage) << " W" << endl; cout << indent_str_next << "Gate Leakage = " << PHY->power.readOp.gate_leakage << " W" << endl; cout << indent_str_next << "Runtime Dynamic = " << PHY->rt_power.readOp.dynamic / mcp.executionTime << " W" << endl; cout << endl; } } else { cout << "Memory Controller:" << endl; cout << indent_str_next << "Area = " << area.get_area() * 1e-6 << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic = " << power.readOp.dynamic * mcp.clockRate << " W" << endl; cout << indent_str_next << "Subthreshold Leakage = " << power.readOp.leakage << " W" << endl; cout << indent_str_next << "Gate Leakage = " << power.readOp.gate_leakage << " W" << endl; cout << endl; } } void DRAM::set_dram_param() { dramp.cmd_coeff = XML->sys.mc.dram_rd_coeff; dramp.act_coeff = XML->sys.mc.dram_act_coeff; dramp.nop_coeff = XML->sys.mc.dram_nop_coeff; dramp.activity_coeff = XML->sys.mc.dram_activity_coeff; dramp.pre_coeff = XML->sys.mc.dram_pre_coeff; dramp.rd_coeff = XML->sys.mc.dram_rd_coeff; dramp.wr_coeff = XML->sys.mc.dram_wr_coeff; dramp.req_coeff = XML->sys.mc.dram_req_coeff; dramp.const_coeff = XML->sys.mc.dram_const_coeff; } void MemoryController::set_mc_param() { if (mc_type == MC) { mcp.clockRate = XML->sys.mc.mc_clock * 2; // DDR double pumped mcp.clockRate *= 1e6; mcp.executionTime = XML->sys.total_cycles / (XML->sys.target_core_clockrate * 1e6); mcp.llcBlockSize = int(ceil(XML->sys.mc.llc_line_length / 8.0)) + XML->sys.mc.llc_line_length; // ecc overhead mcp.dataBusWidth = int(ceil(XML->sys.mc.databus_width / 8.0)) + XML->sys.mc.databus_width; mcp.addressBusWidth = int(ceil( XML->sys.mc.addressbus_width)); // XML->sys.physical_address_width; mcp.opcodeW = 16; mcp.num_mcs = XML->sys.mc.number_mcs; mcp.num_channels = XML->sys.mc.memory_channels_per_mc; mcp.reads = XML->sys.mc.memory_reads; mcp.writes = XML->sys.mc.memory_writes; //+++++++++Transaction engine +++++++++++++++++ ////TODO needs better // numbers, Run the RTL code from OpenSparc. mcp.peakDataTransferRate = XML->sys.mc.peak_transfer_rate; mcp.memRank = XML->sys.mc.number_ranks; //++++++++++++++PHY ++++++++++++++++++++++++++ //TODO needs better numbers // PHY.memAccesses=PHY.peakDataTransferRate;//this is the max power // PHY.llcBlocksize=llcBlockSize; mcp.frontend_duty_cycle = 0.5; // for max power, the actual off-chip links // is bidirectional but time shared mcp.LVDS = XML->sys.mc.LVDS; mcp.type = XML->sys.mc.type; mcp.withPHY = XML->sys.mc.withPHY; } // else if (mc_type==FLASHC) // { // mcp.clockRate =XML->sys.flashc.mc_clock*2;//DDR double // pumped mcp.clockRate *= 1e6; mcp.executionTime = // XML->sys.total_cycles/(XML->sys.target_core_clockrate*1e6); // // mcp.llcBlockSize //=int(ceil(XML->sys.flashc.llc_line_length/8.0))+XML->sys.flashc.llc_line_length;//ecc // overhead mcp.dataBusWidth // =int(ceil(XML->sys.flashc.databus_width/8.0)) + // XML->sys.flashc.databus_width; mcp.addressBusWidth //=int(ceil(XML->sys.flashc.addressbus_width));//XML->sys.physical_address_width; // mcp.opcodeW =16; // mcp.num_mcs = XML->sys.flashc.number_mcs; // mcp.num_channels = XML->sys.flashc.memory_channels_per_mc; // mcp.reads = XML->sys.flashc.memory_reads; // mcp.writes = XML->sys.flashc.memory_writes; // //+++++++++Transaction engine +++++++++++++++++ ////TODO needs // better numbers, Run the RTL code from OpenSparc. // mcp.peakDataTransferRate = // XML->sys.flashc.peak_transfer_rate; mcp.memRank = // XML->sys.flashc.number_ranks; // //++++++++++++++PHY ++++++++++++++++++++++++++ //TODO needs // better numbers // //PHY.memAccesses=PHY.peakDataTransferRate;//this is the max // power // //PHY.llcBlocksize=llcBlockSize; // mcp.frontend_duty_cycle = 0.5;//for max power, the actual // off-chip links is bidirectional but time shared mcp.LVDS = // XML->sys.flashc.LVDS; mcp.type = XML->sys.flashc.type; // } else { cout << "Unknown memory controller type: neither DRAM controller nor Flash " "controller" << endl; exit(0); } } MCFrontEnd ::~MCFrontEnd() { if (MC_arb) { delete MC_arb; MC_arb = 0; } if (frontendBuffer) { delete frontendBuffer; frontendBuffer = 0; } if (readBuffer) { delete readBuffer; readBuffer = 0; } if (writeBuffer) { delete writeBuffer; writeBuffer = 0; } } MemoryController ::~MemoryController() { if (frontend) { delete frontend; frontend = 0; } if (transecEngine) { delete transecEngine; transecEngine = 0; } if (PHY) { delete PHY; PHY = 0; } if (pipeLogic) { delete pipeLogic; pipeLogic = 0; } }