2014-04-01 18:44:30 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* McPAT
|
|
|
|
* SOFTWARE LICENSE AGREEMENT
|
|
|
|
* Copyright 2012 Hewlett-Packard Development Company, L.P.
|
2014-06-03 22:32:59 +02:00
|
|
|
* Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
|
2014-04-01 18:44:30 +02:00
|
|
|
* 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
|
2014-06-03 22:32:59 +02:00
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2014-04-01 18:44:30 +02:00
|
|
|
*
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
#include <cmath>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
#include "basic_components.h"
|
2014-06-03 22:32:59 +02:00
|
|
|
#include "cacheunit.h"
|
|
|
|
#include "common.h"
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
// Turn this to true to get debugging messages
|
|
|
|
bool McPATComponent::debug = false;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
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;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
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;
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
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);
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
else
|
2014-06-03 22:32:59 +02:00
|
|
|
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);
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
return long_channel_device_reduction;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
statsComponents operator+(const statsComponents & x, const statsComponents & y) {
|
|
|
|
statsComponents z;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
z.access = x.access + y.access;
|
|
|
|
z.hit = x.hit + y.hit;
|
|
|
|
z.miss = x.miss + y.miss;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
return z;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
statsComponents operator*(const statsComponents & x, double const * const y) {
|
|
|
|
statsComponents z;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
z.access = x.access * y[0];
|
|
|
|
z.hit = x.hit * y[1];
|
|
|
|
z.miss = x.miss * y[2];
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
return z;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
statsDef operator+(const statsDef & x, const statsDef & y) {
|
|
|
|
statsDef z;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
z.readAc = x.readAc + y.readAc;
|
|
|
|
z.writeAc = x.writeAc + y.writeAc;
|
|
|
|
z.searchAc = x.searchAc + y.searchAc;
|
|
|
|
return z;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
statsDef operator*(const statsDef & x, double const * const y) {
|
|
|
|
statsDef z;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
z.readAc = x.readAc * y;
|
|
|
|
z.writeAc = x.writeAc * y;
|
|
|
|
z.searchAc = x.searchAc * y;
|
|
|
|
return z;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|