1/*****************************************************************************
2 *                                McPAT
3 *                      SOFTWARE LICENSE AGREEMENT
4 *            Copyright 2012 Hewlett-Packard Development Company, L.P.
5 *            Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
6 *                          All Rights Reserved
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met: redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer;
12 * redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution;
15 * neither the name of the copyright holders nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 ***************************************************************************/
32
33#include <cassert>
34#include <cmath>
35#include <iostream>
36
37#include "basic_components.h"
38#include "cacheunit.h"
39#include "common.h"
40
41// Turn this to true to get debugging messages
42bool McPATComponent::debug = false;
43
44bool McPATComponent::opt_for_clk = true;
45int McPATComponent::longer_channel_device = 0;
46// Number of cycles per second, 2GHz = 2e9
47double McPATComponent::target_core_clockrate = 2e9;
48double McPATComponent::total_cycles = 0.0f;
49double McPATComponent::execution_time = 0.0f;
50int McPATComponent::physical_address_width = 0;
51int McPATComponent::virtual_address_width = 0;
52int McPATComponent::virtual_memory_page_size = 0;
53int McPATComponent::data_path_width = 0;
54
55void McPATOutput::reset() {
56    storage = 0.0;
57    area = 0.0;
58    peak_dynamic_power = 0.0;
59    subthreshold_leakage_power = 0.0;
60    gate_leakage_power = 0.0;
61    runtime_dynamic_energy = 0.0;
62}
63
64McPATOutput operator+(const McPATOutput &lhs, const McPATOutput &rhs) {
65    McPATOutput to_return;
66    to_return.storage = lhs.storage + rhs.storage;
67    to_return.area = lhs.area + rhs.area;
68    to_return.peak_dynamic_power = lhs.peak_dynamic_power +
69        rhs.peak_dynamic_power;
70    to_return.subthreshold_leakage_power = lhs.subthreshold_leakage_power +
71        rhs.subthreshold_leakage_power;
72    to_return.gate_leakage_power = lhs.gate_leakage_power +
73        rhs.gate_leakage_power;
74    to_return.runtime_dynamic_energy = lhs.runtime_dynamic_energy +
75        rhs.runtime_dynamic_energy;
76    return to_return;
77}
78
79void McPATOutput::operator+=(const McPATOutput &rhs) {
80    storage += rhs.storage;
81    area += rhs.area;
82    peak_dynamic_power += rhs.peak_dynamic_power;
83    subthreshold_leakage_power += rhs.subthreshold_leakage_power;
84    gate_leakage_power += rhs.gate_leakage_power;
85    runtime_dynamic_energy += rhs.runtime_dynamic_energy;
86}
87
88McPATComponent::McPATComponent()
89        : xml_data(NULL), name("") {
90}
91
92McPATComponent::McPATComponent(XMLNode* _xml_data)
93        : xml_data(_xml_data), name("") {
94}
95
96McPATComponent::McPATComponent(XMLNode* _xml_data,
97                               InputParameter* _interface_ip)
98        : xml_data(_xml_data), interface_ip(*_interface_ip), name("") {
99}
100
101McPATComponent::~McPATComponent() {
102}
103
104void McPATComponent::recursiveInstantiate() {
105    if (debug) {
106        fprintf(stderr, "WARNING: Called recursiveInstantiate from %s, with ",
107                "'type' %s\n", name.c_str(), xml_data->getAttribute("type"));
108    }
109    int i;
110    int numChildren = xml_data->nChildNode("component");
111    for (i = 0; i < numChildren; i++ ) {
112        // For each child node of the system,
113        XMLNode* childXML = xml_data->getChildNodePtr("component", &i);
114        XMLCSTR type = childXML->getAttribute("type");
115
116        if (!type)
117            warnMissingComponentType(childXML->getAttribute("id"));
118
119        STRCMP(type, "Core")
120            warnIncompleteComponentType(type);
121        STRCMP(type, "CacheUnit")
122            children.push_back(new CacheUnit(childXML, &interface_ip));
123        STRCMP(type, "CacheController")
124            warnIncompleteComponentType(type);
125        STRCMP(type, "MemoryController")
126            warnIncompleteComponentType(type);
127        STRCMP(type, "Memory")
128            warnIncompleteComponentType(type);
129        STRCMP(type, "OnChipNetwork")
130            warnIncompleteComponentType(type);
131        STRCMP(type, "BusInterconnect")
132            warnIncompleteComponentType(type);
133        STRCMP(type, "Directory")
134            warnIncompleteComponentType(type);
135
136        else
137            warnUnrecognizedComponent(type);
138    }
139}
140
141void McPATComponent::computeArea() {
142    if (debug) {
143        fprintf(stderr, "WARNING: Called computeArea from %s, with 'type' ",
144                "%s\n", name.c_str(), xml_data->getAttribute("type"));
145    }
146
147    // TODO: This calculation is incorrect and is overwritten by computeEnergy
148    // Fix it up so that the values are available at the correct times
149    int i;
150    int numChildren = children.size();
151    area.set_area(0.0);
152    output_data.area = 0.0;
153    for (i = 0; i < numChildren; i++) {
154        children[i]->computeArea();
155        output_data.area += area.get_area();
156    }
157}
158
159void McPATComponent::computeEnergy() {
160    if (debug) {
161        fprintf(stderr, "WARNING: Called computeEnergy from %s, with 'type' ",
162                "%s\n", name.c_str(), xml_data->getAttribute("type"));
163    }
164
165    power.reset();
166    rt_power.reset();
167    memset(&output_data, 0, sizeof(McPATOutput));
168    int i;
169    int numChildren = children.size();
170    for (i = 0; i < numChildren; i++) {
171        children[i]->computeEnergy();
172        output_data += children[i]->output_data;
173    }
174}
175
176void McPATComponent::displayData(uint32_t indent, int plevel) {
177    if (debug) {
178        fprintf(stderr, "WARNING: Called displayData from %s, with 'type' ",
179                "%s\n", name.c_str(), xml_data->getAttribute("type"));
180    }
181
182    string indent_str(indent, ' ');
183    string indent_str_next(indent + 2, ' ');
184
185    double leakage_power = output_data.subthreshold_leakage_power +
186        output_data.gate_leakage_power;
187    double total_runtime_energy = output_data.runtime_dynamic_energy +
188        leakage_power * execution_time;
189    cout << indent_str << name << ":" << endl;
190    cout << indent_str_next << "Area = " << output_data.area << " mm^2"
191         << endl;
192    cout << indent_str_next << "Peak Dynamic Power = "
193         << output_data.peak_dynamic_power << " W" << endl;
194    cout << indent_str_next << "Subthreshold Leakage Power = "
195         << output_data.subthreshold_leakage_power << " W" << endl;
196    cout << indent_str_next << "Gate Leakage Power = "
197         << output_data.gate_leakage_power << " W" << endl;
198    cout << indent_str_next << "Runtime Dynamic Power = "
199         << (output_data.runtime_dynamic_energy / execution_time) << " W"
200         << endl;
201    cout << indent_str_next << "Runtime Dynamic Energy = "
202         << output_data.runtime_dynamic_energy << " J" << endl;
203    cout << indent_str_next << "Total Runtime Energy = "
204         << total_runtime_energy << " J" << endl;
205    cout << endl;
206
207    // Recursively print children
208    int i;
209    int numChildren = children.size();
210    for (i = 0; i < numChildren; i++) {
211        children[i]->displayData(indent + 4, plevel);
212    }
213}
214
215void McPATComponent::errorUnspecifiedParam(string param) {
216    fprintf(stderr, "ERROR: Parameter must be specified in %s: %s\n",
217            name.c_str(), param.c_str());
218    exit(1);
219}
220
221void McPATComponent::errorNonPositiveParam(string param) {
222    fprintf(stderr, "ERROR: Parameter must be positive in %s: %s\n",
223            name.c_str(), param.c_str());
224    exit(1);
225}
226
227void McPATComponent::warnUnrecognizedComponent(XMLCSTR component) {
228    fprintf(stderr, "WARNING: Component type not recognized in %s: %s\n",
229            name.c_str(), component);
230}
231
232void McPATComponent::warnUnrecognizedParam(XMLCSTR param) {
233    fprintf(stderr, "WARNING: Parameter not recognized in %s: %s\n",
234            name.c_str(), param);
235}
236
237void McPATComponent::warnUnrecognizedStat(XMLCSTR stat) {
238    fprintf(stderr, "WARNING: Statistic not recognized in %s: %s\n",
239            name.c_str(), stat);
240}
241
242void McPATComponent::warnIncompleteComponentType(XMLCSTR type) {
243    fprintf(stderr, "  WARNING: %s handling not yet complete\n", type);
244}
245
246void McPATComponent::warnMissingComponentType(XMLCSTR id) {
247    if (id) {
248        fprintf(stderr,
249                "WARNING: Ignoring a component due to the missing type: %s\n",
250                id);
251    } else {
252        fprintf(stderr,
253                "WARNING: Ignoring a component in %s due to the missing type\n",
254                name.c_str());
255    }
256}
257
258void McPATComponent::warnMissingParamName(XMLCSTR id) {
259    if (id) {
260        fprintf(stderr,
261                "WARNING: Ignoring a parameter due to the missing name: %s\n",
262                id);
263    } else {
264        fprintf(stderr,
265                "WARNING: Ignoring a parameter in %s due to the missing name\n",
266                name.c_str());
267    }
268}
269
270void McPATComponent::warnMissingStatName(XMLCSTR id) {
271    if (id) {
272        fprintf(stderr,
273                "WARNING: Ignoring a statistic due to the missing name: %s\n",
274                id);
275    } else {
276        fprintf(stderr,
277                "WARNING: Ignoring a statistic in %s due to the missing name\n",
278                name.c_str());
279    }
280}
281
282double longer_channel_device_reduction(
283    enum Device_ty device_ty,
284    enum Core_type core_ty) {
285
286    double longer_channel_device_percentage_core;
287    double longer_channel_device_percentage_uncore;
288    double longer_channel_device_percentage_llc;
289
290    double long_channel_device_reduction;
291
292    longer_channel_device_percentage_llc    = 1.0;
293    longer_channel_device_percentage_uncore = 0.82;
294    if (core_ty == OOO) {
295        //0.54 Xeon Tulsa //0.58 Nehelam
296        longer_channel_device_percentage_core   = 0.56;
297    } else {
298        //0.8;//Niagara
299        longer_channel_device_percentage_core   = 0.8;
300    }
301
302    if (device_ty == Core_device) {
303        long_channel_device_reduction =
304            (1 - longer_channel_device_percentage_core) +
305            longer_channel_device_percentage_core *
306            g_tp.peri_global.long_channel_leakage_reduction;
307    } else if (device_ty == Uncore_device) {
308        long_channel_device_reduction =
309            (1 - longer_channel_device_percentage_uncore) +
310            longer_channel_device_percentage_uncore *
311            g_tp.peri_global.long_channel_leakage_reduction;
312    } else if (device_ty == LLC_device) {
313        long_channel_device_reduction =
314            (1 - longer_channel_device_percentage_llc) +
315            longer_channel_device_percentage_llc *
316            g_tp.peri_global.long_channel_leakage_reduction;
317    } else {
318        cout << "ERROR: Unknown device category: " << device_ty << endl;
319        exit(0);
320    }
321
322    return long_channel_device_reduction;
323}
324
325statsComponents operator+(const statsComponents & x, const statsComponents & y) {
326    statsComponents z;
327
328    z.access = x.access + y.access;
329    z.hit    = x.hit + y.hit;
330    z.miss   = x.miss  + y.miss;
331
332    return z;
333}
334
335statsComponents operator*(const statsComponents & x, double const * const y) {
336    statsComponents z;
337
338    z.access = x.access * y[0];
339    z.hit    = x.hit * y[1];
340    z.miss   = x.miss * y[2];
341
342    return z;
343}
344
345statsDef operator+(const statsDef & x, const statsDef & y) {
346    statsDef z;
347
348    z.readAc   = x.readAc  + y.readAc;
349    z.writeAc  = x.writeAc + y.writeAc;
350    z.searchAc  = x.searchAc + y.searchAc;
351    return z;
352}
353
354statsDef operator*(const statsDef & x, double const * const y) {
355    statsDef z;
356
357    z.readAc   = x.readAc * y;
358    z.writeAc  = x.writeAc * y;
359    z.searchAc  = x.searchAc * y;
360    return z;
361}
362