/***************************************************************************** * 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 #include #include #include "basic_components.h" #include "cacheunit.h" #include "common.h" // Turn this to true to get debugging messages bool McPATComponent::debug = false; bool McPATComponent::opt_for_clk = true; int McPATComponent::longer_channel_device = 0; // Number of cycles per second, 2GHz = 2e9 double McPATComponent::target_core_clockrate = 2e9; double McPATComponent::total_cycles = 0.0f; double McPATComponent::execution_time = 0.0f; int McPATComponent::physical_address_width = 0; int McPATComponent::virtual_address_width = 0; int McPATComponent::virtual_memory_page_size = 0; int McPATComponent::data_path_width = 0; void McPATOutput::reset() { storage = 0.0; area = 0.0; peak_dynamic_power = 0.0; subthreshold_leakage_power = 0.0; gate_leakage_power = 0.0; runtime_dynamic_energy = 0.0; } McPATOutput operator+(const McPATOutput &lhs, const McPATOutput &rhs) { McPATOutput to_return; to_return.storage = lhs.storage + rhs.storage; to_return.area = lhs.area + rhs.area; to_return.peak_dynamic_power = lhs.peak_dynamic_power + rhs.peak_dynamic_power; to_return.subthreshold_leakage_power = lhs.subthreshold_leakage_power + rhs.subthreshold_leakage_power; to_return.gate_leakage_power = lhs.gate_leakage_power + rhs.gate_leakage_power; to_return.runtime_dynamic_energy = lhs.runtime_dynamic_energy + rhs.runtime_dynamic_energy; return to_return; } void McPATOutput::operator+=(const McPATOutput &rhs) { storage += rhs.storage; area += rhs.area; peak_dynamic_power += rhs.peak_dynamic_power; subthreshold_leakage_power += rhs.subthreshold_leakage_power; gate_leakage_power += rhs.gate_leakage_power; runtime_dynamic_energy += rhs.runtime_dynamic_energy; } McPATComponent::McPATComponent() : xml_data(NULL), name("") { } McPATComponent::McPATComponent(XMLNode* _xml_data) : xml_data(_xml_data), name("") { } McPATComponent::McPATComponent(XMLNode* _xml_data, InputParameter* _interface_ip) : xml_data(_xml_data), interface_ip(*_interface_ip), name("") { } McPATComponent::~McPATComponent() { } void McPATComponent::recursiveInstantiate() { if (debug) { fprintf(stderr, "WARNING: Called recursiveInstantiate from %s, with ", "'type' %s\n", name.c_str(), xml_data->getAttribute("type")); } int i; int numChildren = xml_data->nChildNode("component"); for (i = 0; i < numChildren; i++ ) { // For each child node of the system, XMLNode* childXML = xml_data->getChildNodePtr("component", &i); XMLCSTR type = childXML->getAttribute("type"); if (!type) warnMissingComponentType(childXML->getAttribute("id")); STRCMP(type, "Core") warnIncompleteComponentType(type); STRCMP(type, "CacheUnit") children.push_back(new CacheUnit(childXML, &interface_ip)); STRCMP(type, "CacheController") warnIncompleteComponentType(type); STRCMP(type, "MemoryController") warnIncompleteComponentType(type); STRCMP(type, "Memory") warnIncompleteComponentType(type); STRCMP(type, "OnChipNetwork") warnIncompleteComponentType(type); STRCMP(type, "BusInterconnect") warnIncompleteComponentType(type); STRCMP(type, "Directory") warnIncompleteComponentType(type); else warnUnrecognizedComponent(type); } } void McPATComponent::computeArea() { if (debug) { fprintf(stderr, "WARNING: Called computeArea from %s, with 'type' ", "%s\n", name.c_str(), xml_data->getAttribute("type")); } // TODO: This calculation is incorrect and is overwritten by computeEnergy // Fix it up so that the values are available at the correct times int i; int numChildren = children.size(); area.set_area(0.0); output_data.area = 0.0; for (i = 0; i < numChildren; i++) { children[i]->computeArea(); output_data.area += area.get_area(); } } void McPATComponent::computeEnergy() { if (debug) { fprintf(stderr, "WARNING: Called computeEnergy from %s, with 'type' ", "%s\n", name.c_str(), xml_data->getAttribute("type")); } power.reset(); rt_power.reset(); memset(&output_data, 0, sizeof(McPATOutput)); int i; int numChildren = children.size(); for (i = 0; i < numChildren; i++) { children[i]->computeEnergy(); output_data += children[i]->output_data; } } void McPATComponent::displayData(uint32_t indent, int plevel) { if (debug) { fprintf(stderr, "WARNING: Called displayData from %s, with 'type' ", "%s\n", name.c_str(), xml_data->getAttribute("type")); } string indent_str(indent, ' '); string indent_str_next(indent + 2, ' '); double leakage_power = output_data.subthreshold_leakage_power + output_data.gate_leakage_power; double total_runtime_energy = output_data.runtime_dynamic_energy + leakage_power * execution_time; cout << indent_str << name << ":" << endl; cout << indent_str_next << "Area = " << output_data.area << " mm^2" << endl; cout << indent_str_next << "Peak Dynamic Power = " << output_data.peak_dynamic_power << " W" << endl; cout << indent_str_next << "Subthreshold Leakage Power = " << output_data.subthreshold_leakage_power << " W" << endl; cout << indent_str_next << "Gate Leakage Power = " << output_data.gate_leakage_power << " W" << endl; cout << indent_str_next << "Runtime Dynamic Power = " << (output_data.runtime_dynamic_energy / execution_time) << " W" << endl; cout << indent_str_next << "Runtime Dynamic Energy = " << output_data.runtime_dynamic_energy << " J" << endl; cout << indent_str_next << "Total Runtime Energy = " << total_runtime_energy << " J" << endl; cout << endl; // Recursively print children int i; int numChildren = children.size(); for (i = 0; i < numChildren; i++) { children[i]->displayData(indent + 4, plevel); } } void McPATComponent::errorUnspecifiedParam(string param) { fprintf(stderr, "ERROR: Parameter must be specified in %s: %s\n", name.c_str(), param.c_str()); exit(1); } void McPATComponent::errorNonPositiveParam(string param) { fprintf(stderr, "ERROR: Parameter must be positive in %s: %s\n", name.c_str(), param.c_str()); exit(1); } void McPATComponent::warnUnrecognizedComponent(XMLCSTR component) { fprintf(stderr, "WARNING: Component type not recognized in %s: %s\n", name.c_str(), component); } void McPATComponent::warnUnrecognizedParam(XMLCSTR param) { fprintf(stderr, "WARNING: Parameter not recognized in %s: %s\n", name.c_str(), param); } void McPATComponent::warnUnrecognizedStat(XMLCSTR stat) { fprintf(stderr, "WARNING: Statistic not recognized in %s: %s\n", name.c_str(), stat); } void McPATComponent::warnIncompleteComponentType(XMLCSTR type) { fprintf(stderr, " WARNING: %s handling not yet complete\n", type); } void McPATComponent::warnMissingComponentType(XMLCSTR id) { if (id) { fprintf(stderr, "WARNING: Ignoring a component due to the missing type: %s\n", id); } else { fprintf(stderr, "WARNING: Ignoring a component in %s due to the missing type\n", name.c_str()); } } void McPATComponent::warnMissingParamName(XMLCSTR id) { if (id) { fprintf(stderr, "WARNING: Ignoring a parameter due to the missing name: %s\n", id); } else { fprintf(stderr, "WARNING: Ignoring a parameter in %s due to the missing name\n", name.c_str()); } } void McPATComponent::warnMissingStatName(XMLCSTR id) { if (id) { fprintf(stderr, "WARNING: Ignoring a statistic due to the missing name: %s\n", id); } else { fprintf(stderr, "WARNING: Ignoring a statistic in %s due to the missing name\n", name.c_str()); } } double longer_channel_device_reduction( enum Device_ty device_ty, enum Core_type core_ty) { double longer_channel_device_percentage_core; double longer_channel_device_percentage_uncore; double longer_channel_device_percentage_llc; double long_channel_device_reduction; longer_channel_device_percentage_llc = 1.0; longer_channel_device_percentage_uncore = 0.82; if (core_ty == OOO) { //0.54 Xeon Tulsa //0.58 Nehelam longer_channel_device_percentage_core = 0.56; } else { //0.8;//Niagara longer_channel_device_percentage_core = 0.8; } if (device_ty == Core_device) { long_channel_device_reduction = (1 - longer_channel_device_percentage_core) + longer_channel_device_percentage_core * g_tp.peri_global.long_channel_leakage_reduction; } else if (device_ty == Uncore_device) { long_channel_device_reduction = (1 - longer_channel_device_percentage_uncore) + longer_channel_device_percentage_uncore * g_tp.peri_global.long_channel_leakage_reduction; } else if (device_ty == LLC_device) { long_channel_device_reduction = (1 - longer_channel_device_percentage_llc) + longer_channel_device_percentage_llc * g_tp.peri_global.long_channel_leakage_reduction; } else { cout << "ERROR: Unknown device category: " << device_ty << endl; exit(0); } return long_channel_device_reduction; } statsComponents operator+(const statsComponents & x, const statsComponents & y) { statsComponents z; z.access = x.access + y.access; z.hit = x.hit + y.hit; z.miss = x.miss + y.miss; return z; } statsComponents operator*(const statsComponents & x, double const * const y) { statsComponents z; z.access = x.access * y[0]; z.hit = x.hit * y[1]; z.miss = x.miss * y[2]; return z; } statsDef operator+(const statsDef & x, const statsDef & y) { statsDef z; z.readAc = x.readAc + y.readAc; z.writeAc = x.writeAc + y.writeAc; z.searchAc = x.searchAc + y.searchAc; return z; } statsDef operator*(const statsDef & x, double const * const y) { statsDef z; z.readAc = x.readAc * y; z.writeAc = x.writeAc * y; z.searchAc = x.searchAc * y; return z; }