1/*****************************************************************************
2 *                                McPAT
3 *                      SOFTWARE LICENSE AGREEMENT
4 *            Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
5 *                          All Rights Reserved
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Authors: Joel Hestness
31 *          Yasuko Eckert
32 *
33 ***************************************************************************/
34
35#include <algorithm>
36#include <cmath>
37#include <cstring>
38#include <iostream>
39
40#include "arbiter.h"
41#include "array.h"
42#include "basic_circuit.h"
43#include "cachearray.h"
44#include "cacheunit.h"
45#include "common.h"
46#include "const.h"
47#include "io.h"
48#include "logic.h"
49#include "parameter.h"
50
51bool CacheUnit::is_cache = true;
52bool CacheUnit::pure_cam = false;
53bool CacheUnit::opt_local = true;
54bool CacheUnit::force_cache_config = false;
55
56CacheUnit::CacheUnit(XMLNode* _xml_data, InputParameter* _interface_ip)
57        : dir_overhead(0), McPATComponent(_xml_data, _interface_ip) {
58
59    int tag;
60    int data;
61
62    name = "Cache Unit";
63    CacheArray* arrayPtr = NULL;
64
65    set_cache_param_from_xml_data();
66
67    //All lower level cache are physically indexed and tagged.
68    double size;
69    double line;
70    double assoc;
71    double banks;
72    size                             = cache_params.capacity;
73    line                             = cache_params.blockW;
74    assoc                            = cache_params.assoc;
75    banks                            = cache_params.nbanks;
76    if ((cache_params.dir_ty == ST &&
77         cache_params.cache_level == L1Directory) ||
78        (cache_params.dir_ty == ST &&
79         cache_params.cache_level == L2Directory)) {
80        tag = physical_address_width + EXTRA_TAG_BITS;
81    } else {
82        tag = physical_address_width - int(ceil(log2(size / line / assoc))) -
83            int(ceil(log2(line))) + EXTRA_TAG_BITS;
84
85        if (cache_params.dir_ty == SBT) {
86            dir_overhead = ceil(cache_params.num_cores / BITS_PER_BYTE) *
87                BITS_PER_BYTE / (line * BITS_PER_BYTE);
88            line *= (1 + dir_overhead);
89            size *= (1 + dir_overhead);
90        }
91    }
92
93    interface_ip.cache_sz = (int)size;
94    interface_ip.line_sz = (int)line;
95    interface_ip.assoc = (int)assoc;
96    interface_ip.nbanks = (int)banks;
97    interface_ip.specific_tag = tag > 0;
98    interface_ip.tag_w = tag;
99
100    if (cache_params.cache_level == L1) {
101        interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE;
102    } else {
103        interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE / 2;
104    }
105
106    interface_ip.access_mode = cache_params.cache_access_mode;
107    interface_ip.throughput= cache_params.throughput;
108    interface_ip.latency = cache_params.latency;
109    interface_ip.obj_func_dyn_energy = 0;
110    interface_ip.obj_func_dyn_power = 0;
111    interface_ip.obj_func_leak_power = 0;
112    interface_ip.obj_func_cycle_t = 1;
113    interface_ip.is_cache = is_cache;
114    interface_ip.pure_ram = cache_params.pure_ram;
115    interface_ip.pure_cam = pure_cam;
116    interface_ip.num_rw_ports = cache_params.cache_rw_ports;
117    interface_ip.num_rd_ports = cache_params.cache_rd_ports;
118    interface_ip.num_wr_ports = cache_params.cache_wr_ports;
119    interface_ip.num_se_rd_ports = cache_params.cache_se_rd_ports;
120    interface_ip.num_search_ports = cache_params.cache_search_ports;
121
122    arrayPtr = new CacheArray(xml_data, &interface_ip, "Data and Tag Arrays",
123                              cache_params.device_ty, clockRate, opt_local,
124                              cache_params.core_ty);
125    children.push_back(arrayPtr);
126
127    // This is for calculating TDP, which depends on the number of
128    // available ports
129    int num_tdp_ports = arrayPtr->l_ip.num_rw_ports +
130        arrayPtr->l_ip.num_rd_ports + arrayPtr->l_ip.num_wr_ports;
131
132    // Set new array stats for calculating TDP and runtime power
133    arrayPtr->tdp_stats.reset();
134    arrayPtr->tdp_stats.readAc.access = cache_stats.tdp_read_access_scalar *
135        num_tdp_ports * cache_stats.duty_cycle *
136        cache_stats.homenode_access_scalar;
137    arrayPtr->tdp_stats.readAc.miss = 0;
138    arrayPtr->tdp_stats.readAc.hit = arrayPtr->tdp_stats.readAc.access -
139        arrayPtr->tdp_stats.readAc.miss;
140    arrayPtr->tdp_stats.writeAc.access = cache_stats.tdp_write_access_scalar *
141        num_tdp_ports * cache_stats.duty_cycle *
142        cache_stats.homenode_access_scalar;
143    arrayPtr->tdp_stats.writeAc.miss = 0;
144    arrayPtr->tdp_stats.writeAc.hit = arrayPtr->tdp_stats.writeAc.access -
145        arrayPtr->tdp_stats.writeAc.miss;
146    arrayPtr->tdp_stats.searchAc.access = 0;
147    arrayPtr->tdp_stats.searchAc.miss = 0;
148    arrayPtr->tdp_stats.searchAc.hit = 0;
149
150    arrayPtr->rtp_stats.reset();
151    if (cache_stats.use_detailed_stats) {
152        arrayPtr->rtp_stats.dataReadAc.access =
153            cache_stats.num_data_array_reads;
154        arrayPtr->rtp_stats.dataWriteAc.access =
155            cache_stats.num_data_array_writes;
156        arrayPtr->rtp_stats.tagReadAc.access =
157            cache_stats.num_tag_array_reads;
158        arrayPtr->rtp_stats.tagWriteAc.access =
159            cache_stats.num_tag_array_writes;
160    } else {
161        // This code makes assumptions. For instance, it assumes that
162        // tag and data arrays are accessed in parallel on a read request and
163        // this is a write-allocate cache. It also ignores any coherence
164        // requests. Using detailed stats as above can avoid the ambiguity
165        // that is introduced here
166        arrayPtr->rtp_stats.dataReadAc.access =
167            cache_stats.read_accesses + cache_stats.write_misses;
168        arrayPtr->rtp_stats.dataWriteAc.access =
169            cache_stats.write_accesses + cache_stats.read_misses;
170        arrayPtr->rtp_stats.tagReadAc.access =
171            cache_stats.read_accesses + cache_stats.write_accesses;
172        arrayPtr->rtp_stats.tagWriteAc.access =
173            cache_stats.read_misses + cache_stats.write_misses;
174    }
175
176    // Set SBT stats if this is an SBT directory type
177    if (dir_overhead > 0) {
178        arrayPtr->setSBTDirOverhead(dir_overhead);
179
180        // TDP stats
181        arrayPtr->sbt_tdp_stats.readAc.access =
182            cache_stats.tdp_read_access_scalar *
183            num_tdp_ports * cache_stats.dir_duty_cycle *
184            (1 - cache_stats.homenode_access_scalar);
185        arrayPtr->sbt_tdp_stats.readAc.miss = 0;
186        arrayPtr->sbt_tdp_stats.readAc.hit =
187            arrayPtr->sbt_tdp_stats.readAc.access -
188            arrayPtr->sbt_tdp_stats.readAc.miss;
189        arrayPtr->sbt_tdp_stats.writeAc.access =
190            cache_stats.tdp_sbt_write_access_scalar *
191            num_tdp_ports * cache_stats.dir_duty_cycle *
192            (1 - cache_stats.homenode_access_scalar);
193        arrayPtr->sbt_tdp_stats.writeAc.miss = 0;
194        arrayPtr->sbt_tdp_stats.writeAc.hit =
195            arrayPtr->sbt_tdp_stats.writeAc.access -
196            arrayPtr->sbt_tdp_stats.writeAc.miss;
197
198        // Runtime power stats
199        arrayPtr->sbt_rtp_stats.readAc.access =
200            cache_stats.homenode_read_accesses;
201        arrayPtr->sbt_rtp_stats.readAc.miss =
202            cache_stats.homenode_read_misses;
203        arrayPtr->sbt_rtp_stats.readAc.access =
204            cache_stats.homenode_read_accesses -
205            cache_stats.homenode_read_misses;
206        arrayPtr->sbt_rtp_stats.writeAc.access =
207            cache_stats.homenode_write_accesses;
208        arrayPtr->sbt_rtp_stats.writeAc.miss =
209            cache_stats.homenode_write_misses;
210        arrayPtr->sbt_rtp_stats.writeAc.hit =
211            cache_stats.homenode_write_accesses -
212            cache_stats.homenode_write_misses;
213    }
214
215    interface_ip.force_cache_config = force_cache_config;
216    if (!((cache_params.dir_ty == ST &&
217           cache_params.cache_level == L1Directory) ||
218          (cache_params.dir_ty == ST &&
219           cache_params.cache_level== L2Directory))) {
220        // Miss Buffer
221        tag = physical_address_width + EXTRA_TAG_BITS;
222        data = (physical_address_width) +
223            int(ceil(log2(size / cache_params.blockW))) +
224            (cache_params.blockW * BITS_PER_BYTE);
225        line = int(ceil(data / BITS_PER_BYTE));
226        size = cache_params.missb_size * line;
227
228        interface_ip.cache_sz = size;
229        interface_ip.line_sz = line;
230        interface_ip.assoc = cache_params.missb_assoc;
231        interface_ip.nbanks = cache_params.missb_banks;
232        interface_ip.specific_tag = tag > 0;
233        interface_ip.tag_w = tag;
234
235        if (cache_params.cache_level == L1) {
236            interface_ip.out_w = line * BITS_PER_BYTE;
237        } else {
238            interface_ip.out_w = line * BITS_PER_BYTE / 2;
239        }
240
241        interface_ip.access_mode = cache_params.miss_buff_access_mode;
242        interface_ip.obj_func_dyn_energy = 0;
243        interface_ip.obj_func_dyn_power = 0;
244        interface_ip.obj_func_leak_power = 0;
245        interface_ip.obj_func_cycle_t = 1;
246        interface_ip.is_cache = is_cache;
247        interface_ip.pure_ram = cache_params.pure_ram;
248        interface_ip.pure_cam = pure_cam;
249        interface_ip.throughput = cache_params.throughput;
250        interface_ip.latency = cache_params.latency;
251        interface_ip.num_rw_ports = cache_params.miss_buff_rw_ports;
252        interface_ip.num_rd_ports = cache_params.miss_buff_rd_ports;
253        interface_ip.num_wr_ports = cache_params.miss_buff_wr_ports;
254        interface_ip.num_se_rd_ports = cache_params.miss_buff_se_rd_ports;
255        interface_ip.num_search_ports = cache_params.miss_buff_search_ports;
256
257        arrayPtr = new CacheArray(xml_data, &interface_ip, "Miss Buffer",
258                                  cache_params.device_ty, clockRate, opt_local,
259                                  cache_params.core_ty);
260        children.push_back(arrayPtr);
261
262        arrayPtr->tdp_stats.reset();
263        arrayPtr->tdp_stats.readAc.access = 0;
264        arrayPtr->tdp_stats.writeAc.access = arrayPtr->l_ip.num_search_ports;
265        arrayPtr->tdp_stats.searchAc.access = arrayPtr->l_ip.num_search_ports;
266
267        arrayPtr->rtp_stats.reset();
268        arrayPtr->rtp_stats.readAc.access =
269            cache_stats.read_misses + cache_stats.write_misses;
270        arrayPtr->rtp_stats.writeAc.access =
271            cache_stats.read_misses + cache_stats.write_misses;
272        arrayPtr->rtp_stats.searchAc.access = 0;
273
274        if (cache_params.dir_ty == SBT) {
275            arrayPtr->rtp_stats.readAc.access +=
276                cache_stats.homenode_write_misses;
277            arrayPtr->rtp_stats.writeAc.access +=
278                cache_stats.homenode_write_misses;
279        }
280
281        // Fill Buffer
282        tag = physical_address_width + EXTRA_TAG_BITS;
283        data = cache_params.blockW;
284
285        interface_ip.cache_sz = data * cache_params.fu_size;
286        interface_ip.line_sz = data;
287        interface_ip.assoc = cache_params.fu_assoc;
288        interface_ip.nbanks = cache_params.fu_banks;
289        interface_ip.specific_tag = tag > 0;
290        interface_ip.tag_w = tag;
291
292        if (cache_params.cache_level == L1) {
293            interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE;
294        } else {
295            interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE / 2;
296        }
297
298        interface_ip.access_mode = cache_params.fetch_buff_access_mode;
299        interface_ip.obj_func_dyn_energy = 0;
300        interface_ip.obj_func_dyn_power = 0;
301        interface_ip.obj_func_leak_power = 0;
302        interface_ip.obj_func_cycle_t = 1;
303        interface_ip.is_cache = is_cache;
304        interface_ip.pure_cam = pure_cam;
305        interface_ip.throughput = cache_params.throughput;
306        interface_ip.latency = cache_params.latency;
307        interface_ip.num_rw_ports = cache_params.fetch_buff_rw_ports;
308        interface_ip.num_rd_ports = cache_params.fetch_buff_rd_ports;
309        interface_ip.num_wr_ports = cache_params.fetch_buff_wr_ports;
310        interface_ip.num_se_rd_ports = cache_params.fetch_buff_se_rd_ports;
311        interface_ip.num_search_ports = cache_params.fetch_buff_search_ports;
312        arrayPtr = new CacheArray(xml_data, &interface_ip, "Fill Buffer",
313                                  cache_params.device_ty, clockRate, opt_local,
314                                  cache_params.core_ty);
315        children.push_back(arrayPtr);
316
317        arrayPtr->tdp_stats.reset();
318        arrayPtr->tdp_stats.readAc.access = 0;
319        arrayPtr->tdp_stats.writeAc.access = arrayPtr->l_ip.num_search_ports;
320        arrayPtr->tdp_stats.searchAc.access = arrayPtr->l_ip.num_search_ports;
321
322        arrayPtr->rtp_stats.reset();
323        arrayPtr->rtp_stats.readAc.access =
324            cache_stats.read_misses + cache_stats.write_misses;
325        arrayPtr->rtp_stats.writeAc.access =
326            cache_stats.read_misses + cache_stats.write_misses;
327        arrayPtr->rtp_stats.searchAc.access = 0;
328
329        if (cache_params.dir_ty == SBT) {
330            arrayPtr->rtp_stats.readAc.access +=
331                cache_stats.homenode_write_misses;
332            arrayPtr->rtp_stats.writeAc.access +=
333                cache_stats.homenode_write_misses;
334        }
335
336        // Prefetch Buffer
337        tag = physical_address_width + EXTRA_TAG_BITS;
338        line = cache_params.blockW;
339
340        interface_ip.cache_sz = cache_params.prefetchb_size * line;
341        interface_ip.line_sz = line;
342        interface_ip.assoc = cache_params.prefetchb_assoc;
343        interface_ip.nbanks = cache_params.prefetchb_banks;
344        interface_ip.specific_tag = tag > 0;
345        interface_ip.tag_w = tag;
346
347        if (cache_params.cache_level == L1) {
348            interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE;
349        } else {
350            interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE / 2;
351        }
352
353        interface_ip.access_mode = cache_params.prefetch_buff_access_mode;
354        interface_ip.obj_func_dyn_energy = 0;
355        interface_ip.obj_func_dyn_power = 0;
356        interface_ip.obj_func_leak_power = 0;
357        interface_ip.obj_func_cycle_t = 1;
358        interface_ip.is_cache = is_cache;
359        interface_ip.pure_ram = cache_params.pure_ram;
360        interface_ip.pure_cam = pure_cam;
361        interface_ip.throughput = cache_params.throughput;
362        interface_ip.latency = cache_params.latency;
363        interface_ip.num_rw_ports = cache_params.pf_buff_rw_ports;
364        interface_ip.num_rd_ports = cache_params.pf_buff_rd_ports;
365        interface_ip.num_wr_ports = cache_params.pf_buff_wr_ports;
366        interface_ip.num_se_rd_ports = cache_params.pf_buff_se_rd_ports;
367        interface_ip.num_search_ports = cache_params.pf_buff_search_ports;
368        arrayPtr = new CacheArray(xml_data, &interface_ip, "Prefetch Buffer",
369                                  cache_params.device_ty, clockRate, opt_local,
370                                  cache_params.core_ty);
371        children.push_back(arrayPtr);
372
373        arrayPtr->tdp_stats.reset();
374        arrayPtr->tdp_stats.readAc.access = 0;
375        arrayPtr->tdp_stats.writeAc.access = arrayPtr->l_ip.num_search_ports;
376        arrayPtr->tdp_stats.searchAc.access = arrayPtr->l_ip.num_search_ports;
377
378        arrayPtr->rtp_stats.reset();
379        arrayPtr->rtp_stats.readAc.access = cache_stats.read_misses;
380        arrayPtr->rtp_stats.writeAc.access = cache_stats.read_misses;
381        arrayPtr->rtp_stats.searchAc.access = 0;
382
383        if (cache_params.dir_ty == SBT) {
384            arrayPtr->rtp_stats.readAc.access +=
385                cache_stats.homenode_write_misses;
386            arrayPtr->rtp_stats.writeAc.access +=
387                cache_stats.homenode_write_misses;
388        }
389
390        // Writeback Buffer
391        if (cache_params.wbb_size > 0) {
392            tag = physical_address_width + EXTRA_TAG_BITS;
393            line = cache_params.blockW;
394
395            interface_ip.cache_sz = cache_params.wbb_size * line;
396            interface_ip.line_sz = line;
397            interface_ip.assoc = cache_params.wbb_assoc;
398            interface_ip.nbanks = cache_params.wbb_banks;
399            interface_ip.specific_tag = tag > 0;
400            interface_ip.tag_w = tag;
401
402            if (cache_params.cache_level == L1) {
403                interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE;
404            } else {
405                interface_ip.out_w = interface_ip.line_sz * BITS_PER_BYTE / 2;
406            }
407
408            interface_ip.access_mode = cache_params.writeback_buff_access_mode;
409            interface_ip.obj_func_dyn_energy = 0;
410            interface_ip.obj_func_dyn_power = 0;
411            interface_ip.obj_func_leak_power = 0;
412            interface_ip.obj_func_cycle_t = 1;
413            interface_ip.is_cache = is_cache;
414            interface_ip.pure_ram = cache_params.pure_ram;
415            interface_ip.pure_cam = pure_cam;
416            interface_ip.throughput = cache_params.throughput;
417            interface_ip.latency = cache_params.latency;
418            interface_ip.num_rw_ports = cache_params.wb_buff_rw_ports;
419            interface_ip.num_rd_ports = cache_params.wb_buff_rd_ports;
420            interface_ip.num_wr_ports = cache_params.wb_buff_wr_ports;
421            interface_ip.num_se_rd_ports = cache_params.wb_buff_se_rd_ports;
422            interface_ip.num_search_ports = cache_params.wb_buff_search_ports;
423            arrayPtr = new CacheArray(xml_data, &interface_ip,
424                                      "Writeback Buffer",
425                                      cache_params.device_ty, clockRate,
426                                      opt_local, cache_params.core_ty);
427            children.push_back(arrayPtr);
428
429            arrayPtr->tdp_stats.reset();
430            arrayPtr->tdp_stats.readAc.access = 0;
431            arrayPtr->tdp_stats.writeAc.access =
432                arrayPtr->l_ip.num_search_ports;
433            arrayPtr->tdp_stats.searchAc.access =
434                arrayPtr->l_ip.num_search_ports;
435
436            arrayPtr->rtp_stats.reset();
437            arrayPtr->rtp_stats.readAc.access = cache_stats.write_misses;
438            arrayPtr->rtp_stats.writeAc.access = cache_stats.write_misses;
439            arrayPtr->rtp_stats.searchAc.access = 0;
440
441            if (cache_params.dir_ty == SBT) {
442                arrayPtr->rtp_stats.readAc.access +=
443                    cache_stats.homenode_write_misses;
444                arrayPtr->rtp_stats.writeAc.access +=
445                    cache_stats.homenode_write_misses;
446            }
447        }
448    }
449}
450
451void CacheUnit::computeEnergy() {
452    McPATComponent::computeEnergy();
453}
454
455void CacheUnit::set_cache_param_from_xml_data() {
456    int level, type;
457
458    // Initialization... move this?
459    memset(&cache_params, 0, sizeof(CacheParameters));
460    memset(&cache_stats, 0, sizeof(CacheStatistics));
461
462    // By default, use the core clock frequency. This can be changed by
463    // setting the clockrate param in the XML definition of the CacheUnit
464    clockRate = target_core_clockrate;
465    XMLCSTR comp_name = xml_data->getAttribute("name");
466    if (comp_name) {
467        name = comp_name;
468    }
469
470    int num_children = xml_data->nChildNode("param");
471    int i;
472    int tech_type;
473    int mat_type;
474    for (i = 0; i < num_children; i++) {
475        XMLNode* paramNode = xml_data->getChildNodePtr("param", &i);
476        XMLCSTR node_name = paramNode->getAttribute("name");
477        XMLCSTR value = paramNode->getAttribute("value");
478
479        if (!node_name)
480            warnMissingParamName(paramNode->getAttribute("id"));
481
482        ASSIGN_INT_IF("level", level);
483        ASSIGN_FP_IF("size", cache_params.capacity);
484        ASSIGN_FP_IF("block_size", cache_params.blockW);
485        ASSIGN_FP_IF("assoc", cache_params.assoc);
486        ASSIGN_FP_IF("num_banks", cache_params.nbanks);
487        ASSIGN_FP_IF("latency", cache_params.latency);
488        ASSIGN_FP_IF("throughput", cache_params.throughput);
489        ASSIGN_INT_IF("miss_buffer_size", cache_params.missb_size);
490        ASSIGN_INT_IF("fetch_buffer_size", cache_params.fu_size);
491        ASSIGN_INT_IF("prefetch_buffer_size", cache_params.prefetchb_size);
492        ASSIGN_INT_IF("writeback_buffer_size", cache_params.wbb_size);
493        ASSIGN_INT_IF("miss_buffer_assoc", cache_params.missb_assoc);
494        ASSIGN_INT_IF("fetch_buffer_assoc", cache_params.fu_assoc);
495        ASSIGN_INT_IF("prefetch_buffer_assoc", cache_params.prefetchb_assoc);
496        ASSIGN_INT_IF("writeback_buffer_assoc", cache_params.wbb_assoc);
497        ASSIGN_INT_IF("miss_buffer_banks", cache_params.missb_banks);
498        ASSIGN_INT_IF("fetch_buffer_banks", cache_params.fu_banks);
499        ASSIGN_INT_IF("prefetch_buffer_banks", cache_params.prefetchb_banks);
500        ASSIGN_INT_IF("writeback_buffer_banks", cache_params.wbb_banks);
501        ASSIGN_ENUM_IF("cache_access_mode",
502                       cache_params.cache_access_mode, Access_mode);
503        ASSIGN_ENUM_IF("miss_buff_access_mode",
504                       cache_params.miss_buff_access_mode, Access_mode);
505        ASSIGN_ENUM_IF("fetch_buff_access_mode",
506                       cache_params.fetch_buff_access_mode, Access_mode);
507        ASSIGN_ENUM_IF("prefetch_buff_access_mode",
508                       cache_params.prefetch_buff_access_mode, Access_mode);
509        ASSIGN_ENUM_IF("writeback_buff_access_mode",
510                       cache_params.writeback_buff_access_mode, Access_mode);
511        ASSIGN_INT_IF("cache_rw_ports", cache_params.cache_rw_ports);
512        ASSIGN_INT_IF("cache_rd_ports", cache_params.cache_rd_ports);
513        ASSIGN_INT_IF("cache_wr_ports", cache_params.cache_wr_ports);
514        ASSIGN_INT_IF("cache_se_rd_ports", cache_params.cache_se_rd_ports);
515        ASSIGN_INT_IF("cache_search_ports", cache_params.cache_search_ports);
516        ASSIGN_INT_IF("miss_buff_rw_ports", cache_params.miss_buff_rw_ports);
517        ASSIGN_INT_IF("miss_buff_rd_ports", cache_params.miss_buff_rd_ports);
518        ASSIGN_INT_IF("miss_buff_wr_ports", cache_params.miss_buff_wr_ports);
519        ASSIGN_INT_IF("miss_buff_se_rd_ports" ,
520                      cache_params.miss_buff_se_rd_ports);
521        ASSIGN_INT_IF("miss_buff_search_ports",
522                      cache_params.miss_buff_search_ports);
523        ASSIGN_INT_IF("fetch_buff_rw_ports", cache_params.fetch_buff_rw_ports);
524        ASSIGN_INT_IF("fetch_buff_rd_ports", cache_params.fetch_buff_rd_ports);
525        ASSIGN_INT_IF("fetch_buff_wr_ports", cache_params.fetch_buff_wr_ports);
526        ASSIGN_INT_IF("fetch_buff_se_rd_ports",
527                      cache_params.fetch_buff_se_rd_ports);
528        ASSIGN_INT_IF("fetch_buff_search_ports",
529                      cache_params.fetch_buff_search_ports);
530        ASSIGN_INT_IF("pf_buff_rw_ports", cache_params.pf_buff_rw_ports);
531        ASSIGN_INT_IF("pf_buff_rd_ports", cache_params.pf_buff_rd_ports);
532        ASSIGN_INT_IF("pf_buff_wr_ports", cache_params.pf_buff_wr_ports);
533        ASSIGN_INT_IF("pf_buff_se_rd_ports", cache_params.pf_buff_se_rd_ports);
534        ASSIGN_INT_IF("pf_buff_search_ports",
535                      cache_params.pf_buff_search_ports);
536        ASSIGN_INT_IF("wb_buff_rw_ports", cache_params.wb_buff_rw_ports);
537        ASSIGN_INT_IF("wb_buff_rd_ports", cache_params.wb_buff_rd_ports);
538        ASSIGN_INT_IF("wb_buff_wr_ports", cache_params.wb_buff_wr_ports);
539        ASSIGN_INT_IF("wb_buff_se_rd_ports", cache_params.wb_buff_se_rd_ports);
540        ASSIGN_INT_IF("wb_buff_search_ports",
541                      cache_params.wb_buff_search_ports);
542        ASSIGN_FP_IF("clockrate", cache_params.clockRate);
543        ASSIGN_INT_IF("pure_ram", cache_params.pure_ram);
544        ASSIGN_INT_IF("tech_type", tech_type);
545        ASSIGN_ENUM_IF("Directory_type", cache_params.dir_ty, Dir_type);
546        ASSIGN_ENUM_IF("device_type", cache_params.device_ty, Device_ty);
547        ASSIGN_ENUM_IF("core_type", cache_params.core_ty, Core_type);
548        ASSIGN_INT_IF("num_cores", cache_params.num_cores);
549        ASSIGN_INT_IF("wire_mat_type", mat_type);
550        ASSIGN_ENUM_IF("wire_type", interface_ip.wt, Wire_type);
551
552        else {
553            warnUnrecognizedParam(node_name);
554        }
555    }
556
557    // Change from MHz to Hz
558    cache_params.clockRate *= 1e6;
559    if (cache_params.clockRate > 0) {
560        clockRate = cache_params.clockRate;
561    }
562
563    interface_ip.data_arr_ram_cell_tech_type    = tech_type;
564    interface_ip.data_arr_peri_global_tech_type = tech_type;
565    interface_ip.tag_arr_ram_cell_tech_type     = tech_type;
566    interface_ip.tag_arr_peri_global_tech_type  = tech_type;
567
568    interface_ip.wire_is_mat_type = mat_type;
569    interface_ip.wire_os_mat_type = mat_type;
570
571    switch(level) {
572      case 1:
573        cache_params.cache_level = L1;
574        break;
575      case 2:
576        cache_params.cache_level = L2;
577        break;
578      case 3:
579        cache_params.cache_level = L3;
580        break;
581      case 4:
582        cache_params.cache_level = L1Directory;
583        break;
584      case 5:
585        cache_params.cache_level = L2Directory;
586        break;
587
588      default:
589        fprintf(stderr, "ERROR: Unrecognized cache level in %s: %d\n",
590                name.c_str(), level);
591        exit(1);
592    }
593
594    cache_stats.use_detailed_stats = false;
595
596    num_children = xml_data->nChildNode("stat");
597    for (i = 0; i < num_children; i++) {
598        XMLNode* statNode = xml_data->getChildNodePtr("stat", &i);
599        XMLCSTR node_name = statNode->getAttribute("name");
600        XMLCSTR value = statNode->getAttribute("value");
601
602        if (!node_name)
603            warnMissingStatName(statNode->getAttribute("id"));
604
605        ASSIGN_FP_IF("num_data_array_reads", cache_stats.num_data_array_reads);
606        ASSIGN_FP_IF("num_data_array_writes",
607                     cache_stats.num_data_array_writes);
608        ASSIGN_FP_IF("num_tag_array_reads", cache_stats.num_tag_array_reads);
609        ASSIGN_FP_IF("num_tag_array_writes", cache_stats.num_tag_array_writes);
610        ASSIGN_FP_IF("duty_cycle", cache_stats.duty_cycle);
611        ASSIGN_FP_IF("read_accesses", cache_stats.read_accesses);
612        ASSIGN_FP_IF("write_accesses", cache_stats.write_accesses);
613        ASSIGN_FP_IF("read_misses", cache_stats.read_misses);
614        ASSIGN_FP_IF("write_misses", cache_stats.write_misses);
615        ASSIGN_FP_IF("conflicts", cache_stats.conflicts);
616        ASSIGN_INT_IF("homenode_read_accesses",
617                      cache_stats.homenode_read_accesses);
618        ASSIGN_INT_IF("homenode_write_accesses",
619                      cache_stats.homenode_write_accesses);
620        ASSIGN_INT_IF("homenode_read_misses",
621                      cache_stats.homenode_read_misses);
622        ASSIGN_INT_IF("homenode_write_misses",
623                      cache_stats.homenode_write_misses);
624        ASSIGN_FP_IF("homenode_access_scalar",
625                     cache_stats.homenode_access_scalar);
626        ASSIGN_FP_IF("tdp_read_access_scalar",
627                     cache_stats.tdp_read_access_scalar);
628        ASSIGN_FP_IF("tdp_write_access_scalar",
629                     cache_stats.tdp_write_access_scalar);
630        ASSIGN_FP_IF("tdp_sbt_write_access_scalar",
631                     cache_stats.tdp_sbt_write_access_scalar);
632        ASSIGN_FP_IF("dir_duty_cycle",
633                     cache_stats.dir_duty_cycle);
634
635        else {
636            warnUnrecognizedStat(node_name);
637        }
638    }
639
640    if (cache_stats.num_data_array_reads > 0 ||
641        cache_stats.num_data_array_writes > 0 ||
642        cache_stats.num_tag_array_reads > 0 ||
643        cache_stats.num_tag_array_writes > 0) {
644        cache_stats.use_detailed_stats = true;
645        calculate_runtime_data_and_tag = true;
646    }
647}
648