1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Cache simulation.                                            ---*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*---                                                        sim.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Callgrind, a Valgrind tool for call graph
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   profiling programs.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2003-2013, Josef Weidendorfer (Josef.Weidendorfer@gmx.de)
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This tool is derived from and contains code from Cachegrind
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   Copyright (C) 2002-2013 Nicholas Nethercote (njn@valgrind.org)
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "global.h"
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Notes:
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  - simulates a write-allocate cache
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  - (block --> set) hash function uses simple bit selection
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  - handling of references straddling two cache blocks:
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - counts as only one cache access (not two)
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - both blocks hit                  --> one hit
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - one block hits, the other misses --> one miss
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - both blocks miss                 --> one miss (not two)
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Cache configuration */
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "cg_arch.c"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* additional structures for cache use info, separated
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * according usage frequency:
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - line_loaded : pointer to cost center of instruction
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *                 which loaded the line into cache.
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *                 Needed to increment counters when line is evicted.
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - line_use    : updated on every access
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct {
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt count;
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt mask; /* e.g. for 64Byte line size 1bit/2Byte */
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} line_use;
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct {
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Addr memline, iaddr;
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  line_use* dep_use; /* point to higher-level cacheblock for this memline */
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong* use_base;
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} line_loaded;
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Cache state */
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef struct {
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   const HChar* name;
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          size;                   /* bytes */
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          assoc;
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          line_size;              /* bytes */
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool         sectored;  /* prefetch nearside cacheline on read */
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          sets;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          sets_min_1;
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          line_size_bits;
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          tag_shift;
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord        tag_mask;
79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   HChar        desc_line[128];
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord*       tags;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* for cache use */
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int          line_size_mask;
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int*         line_start_mask;
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int*         line_end_mask;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   line_loaded* loaded;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   line_use*    use;
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} cache_t2;
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * States of flat caches in our model.
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * We use a 2-level hierarchy,
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic cache_t2 I1, D1, LL;
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Lower bits of cache tags are used as flags for a cache line */
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CACHELINE_FLAGMASK (MIN_LINE_SIZE-1)
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CACHELINE_DIRTY    1
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Cache simulator Options */
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_simulate_writeback = False;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_simulate_hwpref = False;
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_simulate_sectors = False;
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool clo_collect_cacheuse = False;
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Following global vars are setup before by setup_bbcc():
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - Addr   CLG_(bb_base)     (instruction start address of original BB)
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * - ULong* CLG_(cost_base)   (start of cost array for BB)
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAddr   CLG_(bb_base);
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong* CLG_(cost_base);
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic InstrInfo* current_ii;
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Cache use offsets */
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* The offsets are only correct because all per-instruction event sets get
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the "Use" set added first !
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int off_I1_AcCost  = 0;
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int off_I1_SpLoss  = 1;
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int off_D1_AcCost  = 0;
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int off_D1_SpLoss  = 1;
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int off_LL_AcCost  = 2;
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int off_LL_SpLoss  = 3;
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Cache access types */
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef enum { Read = 0, Write = CACHELINE_DIRTY } RefType;
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Result of a reference into a flat cache */
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef enum { Hit  = 0, Miss, MissDirty } CacheResult;
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Result of a reference into a hierarchical cache model */
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef enum {
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    L1_Hit,
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    LL_Hit,
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MemAccess,
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WriteBackMemAccess } CacheModelResult;
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef CacheModelResult (*simcall_type)(Addr, UChar);
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic struct {
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    simcall_type I1_Read;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    simcall_type D1_Read;
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    simcall_type D1_Write;
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} simulator;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Cache Simulator Initialization                       ---*/
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cachesim_clearcache(cache_t2* c)
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int i;
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (i = 0; i < c->sets * c->assoc; i++)
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c->tags[i] = 0;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (c->use) {
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 0; i < c->sets * c->assoc; i++) {
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c->loaded[i].memline  = 0;
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c->loaded[i].use_base = 0;
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c->loaded[i].dep_use = 0;
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c->loaded[i].iaddr = 0;
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c->use[i].mask    = 0;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c->use[i].count   = 0;
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c->tags[i] = i % c->assoc; /* init lower bits as pointer */
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cacheuse_initcache(cache_t2* c);
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* By this point, the size/assoc/line_size has been checked. */
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cachesim_initcache(cache_t config, cache_t2* c)
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->size      = config.size;
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->assoc     = config.assoc;
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->line_size = config.line_size;
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->sectored  = False; // FIXME
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->sets           = (c->size / c->line_size) / c->assoc;
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->sets_min_1     = c->sets - 1;
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->line_size_bits = VG_(log2)(c->line_size);
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->tag_shift      = c->line_size_bits + VG_(log2)(c->sets);
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->tag_mask       = ~((1<<c->tag_shift)-1);
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Can bits in tag entries be used for flags?
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * Should be always true as MIN_LINE_SIZE >= 16 */
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_ASSERT( (c->tag_mask & CACHELINE_FLAGMASK) == 0);
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (c->assoc == 1) {
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(c->desc_line, "%d B, %d B, direct-mapped%s",
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   c->size, c->line_size,
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   c->sectored ? ", sectored":"");
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(sprintf)(c->desc_line, "%d B, %d B, %d-way associative%s",
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   c->size, c->line_size, c->assoc,
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   c->sectored ? ", sectored":"");
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   c->tags = (UWord*) CLG_MALLOC("cl.sim.cs_ic.1",
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 sizeof(UWord) * c->sets * c->assoc);
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (clo_collect_cacheuse)
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       cacheuse_initcache(c);
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     c->use = 0;
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cachesim_clearcache(c);
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void print_cache(cache_t2* c)
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt set, way, i;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note initialisation and update of 'i'. */
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0, set = 0; set < c->sets; set++) {
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (way = 0; way < c->assoc; way++, i++) {
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(printf)("%8x ", c->tags[i]);
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("\n");
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/*--- Simple Cache Simulation                              ---*/
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * Model: single inclusive, 2-level cache hierarchy (L1/LL)
235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *        with write-allocate
236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov *
237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * For simple cache hit/miss counts, we do not have to
238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * maintain the dirty state of lines (no need to distinguish
239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * read/write references), and the resulting counts are the
240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov * same for write-through and write-back caches.
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Simulator functions:
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  CacheModelResult cachesim_I1_ref(Addr a, UChar size)
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  CacheModelResult cachesim_D1_ref(Addr a, UChar size)
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((always_inline))
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheResult cachesim_setref(cache_t2* c, UInt set_no, UWord tag)
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, j;
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UWord *set;
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    set = &(c->tags[set_no * c->assoc]);
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* This loop is unrolled for just the first case, which is the most */
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* common.  We can't unroll any further because it would screw up   */
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if we have a direct-mapped (1-way) cache.                        */
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tag == set[0])
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return Hit;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* If the tag is one other than the MRU, move it into the MRU spot  */
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* and shuffle the rest down.                                       */
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 1; i < c->assoc; i++) {
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (tag == set[i]) {
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = i; j > 0; j--) {
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                set[j] = set[j - 1];
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set[0] = tag;
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return Hit;
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* A miss;  install this tag as MRU, shuffle rest down. */
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (j = c->assoc - 1; j > 0; j--) {
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set[j] = set[j - 1];
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    set[0] = tag;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return Miss;
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((always_inline))
283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic __inline__
284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovCacheResult cachesim_ref(cache_t2* c, Addr a, UChar size)
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    UWord block1 =  a         >> c->line_size_bits;
287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    UWord block2 = (a+size-1) >> c->line_size_bits;
288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    UInt  set1   = block1 & c->sets_min_1;
289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    /* the tag does not need to include bits specifying the set,
290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     * but it can, and this saves instructions */
291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    UWord tag1   = block1;
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Access entirely within line. */
294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    if (block1 == block2)
295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	return cachesim_setref(c, set1, tag1);
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Access straddles two lines. */
298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    else if (block1 + 1 == block2) {
299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        UInt  set2 = block2 & c->sets_min_1;
300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        UWord tag2 = block2;
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* the call updates cache structures as side effect */
303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov	CacheResult res1 =  cachesim_setref(c, set1, tag1);
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CacheResult res2 =  cachesim_setref(c, set2, tag2);
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return ((res1 == Miss) || (res2 == Miss)) ? Miss : Hit;
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov       VG_(printf)("addr: %lx  size: %u  blocks: %ld %ld",
309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov		   a, size, block1, block2);
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(tool_panic)("item straddles more than two cache sets");
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return Hit;
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult cachesim_I1_ref(Addr a, UChar size)
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &I1, a, size) == Hit ) return L1_Hit;
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &LL, a, size) == Hit ) return LL_Hit;
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return MemAccess;
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult cachesim_D1_ref(Addr a, UChar size)
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &D1, a, size) == Hit ) return L1_Hit;
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &LL, a, size) == Hit ) return LL_Hit;
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return MemAccess;
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Write Back Cache Simulation                          ---*/
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * More complex model: L1 Write-through, LL Write-back
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This needs to distinguish among read and write references.
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Simulator functions:
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  CacheModelResult cachesim_I1_Read(Addr a, UChar size)
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  CacheModelResult cachesim_D1_Read(Addr a, UChar size)
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *  CacheModelResult cachesim_D1_Write(Addr a, UChar size)
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * With write-back, result can be a miss evicting a dirty line
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * The dirty state of a cache line is stored in Bit0 of the tag for
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * this cache line (CACHELINE_DIRTY = 1). By OR'ing the reference
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * type (Read/Write), the line gets dirty on a write.
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((always_inline))
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheResult cachesim_setref_wb(cache_t2* c, RefType ref, UInt set_no, UWord tag)
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i, j;
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UWord *set, tmp_tag;
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    set = &(c->tags[set_no * c->assoc]);
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* This loop is unrolled for just the first case, which is the most */
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* common.  We can't unroll any further because it would screw up   */
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* if we have a direct-mapped (1-way) cache.                        */
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (tag == (set[0] & ~CACHELINE_DIRTY)) {
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	set[0] |= ref;
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        return Hit;
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* If the tag is one other than the MRU, move it into the MRU spot  */
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* and shuffle the rest down.                                       */
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 1; i < c->assoc; i++) {
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (tag == (set[i] & ~CACHELINE_DIRTY)) {
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    tmp_tag = set[i] | ref; // update dirty flag
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = i; j > 0; j--) {
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                set[j] = set[j - 1];
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set[0] = tmp_tag;
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return Hit;
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* A miss;  install this tag as MRU, shuffle rest down. */
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    tmp_tag = set[c->assoc - 1];
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (j = c->assoc - 1; j > 0; j--) {
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        set[j] = set[j - 1];
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    set[0] = tag | ref;
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return (tmp_tag & CACHELINE_DIRTY) ? MissDirty : Miss;
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((always_inline))
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheResult cachesim_ref_wb(cache_t2* c, RefType ref, Addr a, UChar size)
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UInt set1 = ( a         >> c->line_size_bits) & (c->sets_min_1);
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UInt set2 = ((a+size-1) >> c->line_size_bits) & (c->sets_min_1);
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    UWord tag = a & c->tag_mask;
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Access entirely within line. */
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (set1 == set2)
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return cachesim_setref_wb(c, ref, set1, tag);
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Access straddles two lines. */
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Nb: this is a fast way of doing ((set1+1) % c->sets) */
405b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov    else if (((set1 + 1) & (c->sets_min_1)) == set2) {
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	UWord tag2  = (a+size-1) & c->tag_mask;
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* the call updates cache structures as side effect */
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CacheResult res1 =  cachesim_setref_wb(c, ref, set1, tag);
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CacheResult res2 =  cachesim_setref_wb(c, ref, set2, tag2);
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if ((res1 == MissDirty) || (res2 == MissDirty)) return MissDirty;
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return ((res1 == Miss) || (res2 == Miss)) ? Miss : Hit;
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(printf)("addr: %lx  size: %u  sets: %d %d", a, size, set1, set2);
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(tool_panic)("item straddles more than two cache sets");
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return Hit;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult cachesim_I1_Read(Addr a, UChar size)
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &I1, a, size) == Hit ) return L1_Hit;
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch( cachesim_ref_wb( &LL, Read, a, size) ) {
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Hit: return LL_Hit;
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Miss: return MemAccess;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default: break;
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return WriteBackMemAccess;
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult cachesim_D1_Read(Addr a, UChar size)
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &D1, a, size) == Hit ) return L1_Hit;
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch( cachesim_ref_wb( &LL, Read, a, size) ) {
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Hit: return LL_Hit;
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Miss: return MemAccess;
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default: break;
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return WriteBackMemAccess;
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult cachesim_D1_Write(Addr a, UChar size)
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &D1, a, size) == Hit ) {
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Even for a L1 hit, the write-trough L1 passes
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 * the write to the LL to make the LL line dirty.
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 * But this causes no latency, so return the hit.
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 */
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cachesim_ref_wb( &LL, Write, a, size);
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return L1_Hit;
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch( cachesim_ref_wb( &LL, Write, a, size) ) {
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Hit: return LL_Hit;
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Miss: return MemAccess;
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default: break;
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return WriteBackMemAccess;
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Hardware Prefetch Simulation                         ---*/
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong prefetch_up = 0;
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong prefetch_down = 0;
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_STREAMS  8
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PF_PAGEBITS 12
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic UInt pf_lastblock[PF_STREAMS];
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int  pf_seqblocks[PF_STREAMS];
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid prefetch_clear(void)
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int i;
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(i=0;i<PF_STREAMS;i++)
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pf_lastblock[i] = pf_seqblocks[i] = 0;
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * HW Prefetch emulation
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Start prefetching when detecting sequential access to 3 memory blocks.
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * One stream can be detected per 4k page.
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid prefetch_LL_doref(Addr a)
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt stream = (a >> PF_PAGEBITS) % PF_STREAMS;
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  UInt block = ( a >> LL.line_size_bits);
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (block != pf_lastblock[stream]) {
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (pf_seqblocks[stream] == 0) {
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (pf_lastblock[stream] +1 == block) pf_seqblocks[stream]++;
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else if (pf_lastblock[stream] -1 == block) pf_seqblocks[stream]--;
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (pf_seqblocks[stream] >0) {
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (pf_lastblock[stream] +1 == block) {
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pf_seqblocks[stream]++;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (pf_seqblocks[stream] >= 2) {
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  prefetch_up++;
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cachesim_ref(&LL, a + 5 * LL.line_size,1);
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else pf_seqblocks[stream] = 0;
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (pf_seqblocks[stream] <0) {
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (pf_lastblock[stream] -1 == block) {
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	pf_seqblocks[stream]--;
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (pf_seqblocks[stream] <= -2) {
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  prefetch_down++;
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  cachesim_ref(&LL, a - 5 * LL.line_size,1);
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else pf_seqblocks[stream] = 0;
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pf_lastblock[stream] = block;
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* simple model with hardware prefetch */
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult prefetch_I1_ref(Addr a, UChar size)
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &I1, a, size) == Hit ) return L1_Hit;
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prefetch_LL_doref(a);
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &LL, a, size) == Hit ) return LL_Hit;
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return MemAccess;
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult prefetch_D1_ref(Addr a, UChar size)
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &D1, a, size) == Hit ) return L1_Hit;
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prefetch_LL_doref(a);
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &LL, a, size) == Hit ) return LL_Hit;
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return MemAccess;
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* complex model with hardware prefetch */
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult prefetch_I1_Read(Addr a, UChar size)
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &I1, a, size) == Hit ) return L1_Hit;
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prefetch_LL_doref(a);
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch( cachesim_ref_wb( &LL, Read, a, size) ) {
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Hit: return LL_Hit;
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Miss: return MemAccess;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default: break;
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return WriteBackMemAccess;
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult prefetch_D1_Read(Addr a, UChar size)
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &D1, a, size) == Hit ) return L1_Hit;
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prefetch_LL_doref(a);
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch( cachesim_ref_wb( &LL, Read, a, size) ) {
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Hit: return LL_Hit;
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Miss: return MemAccess;
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default: break;
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return WriteBackMemAccess;
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult prefetch_D1_Write(Addr a, UChar size)
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prefetch_LL_doref(a);
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( cachesim_ref( &D1, a, size) == Hit ) {
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	/* Even for a L1 hit, the write-trough L1 passes
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 * the write to the LL to make the LL line dirty.
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 * But this causes no latency, so return the hit.
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 */
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cachesim_ref_wb( &LL, Write, a, size);
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return L1_Hit;
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch( cachesim_ref_wb( &LL, Write, a, size) ) {
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Hit: return LL_Hit;
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case Miss: return MemAccess;
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default: break;
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return WriteBackMemAccess;
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Cache Simulation with use metric collection          ---*/
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* can not be combined with write-back or prefetch */
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid cacheuse_initcache(cache_t2* c)
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int i;
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int start_mask, start_val;
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    unsigned int end_mask, end_val;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c->use    = CLG_MALLOC("cl.sim.cu_ic.1",
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           sizeof(line_use) * c->sets * c->assoc);
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c->loaded = CLG_MALLOC("cl.sim.cu_ic.2",
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                           sizeof(line_loaded) * c->sets * c->assoc);
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c->line_start_mask = CLG_MALLOC("cl.sim.cu_ic.3",
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                    sizeof(int) * c->line_size);
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c->line_end_mask = CLG_MALLOC("cl.sim.cu_ic.4",
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  sizeof(int) * c->line_size);
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    c->line_size_mask = c->line_size-1;
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Meaning of line_start_mask/line_end_mask
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * Example: for a given cache line, you get an access starting at
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * byte offset 5, length 4, byte 5 - 8 was touched. For a cache
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * line size of 32, you have 1 bit per byte in the mask:
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *   bit31   bit8 bit5  bit 0
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *       |      |  |    |
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *       11..111111100000   line_start_mask[5]
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *       00..000111111111   line_end_mask[(5+4)-1]
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *  use_mask |= line_start_mask[5] && line_end_mask[8]
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    start_val = end_val = ~0;
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (c->line_size < 32) {
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int bits_per_byte = 32/c->line_size;
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	start_mask = (1<<bits_per_byte)-1;
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	end_mask   = start_mask << (32-bits_per_byte);
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(i=0;i<c->line_size;i++) {
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c->line_start_mask[i] = start_val;
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    start_val  = start_val & ~start_mask;
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    start_mask = start_mask << bits_per_byte;
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c->line_end_mask[c->line_size-i-1] = end_val;
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    end_val  = end_val & ~end_mask;
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    end_mask = end_mask >> bits_per_byte;
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	int bytes_per_bit = c->line_size/32;
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	start_mask = 1;
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	end_mask   = 1 << 31;
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	for(i=0;i<c->line_size;i++) {
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c->line_start_mask[i] = start_val;
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c->line_end_mask[c->line_size-i-1] = end_val;
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if ( ((i+1)%bytes_per_bit) == 0) {
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		start_val   &= ~start_mask;
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		end_val     &= ~end_mask;
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		start_mask <<= 1;
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		end_mask   >>= 1;
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "Config %s:\n", c->desc_line);
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(i=0;i<c->line_size;i++) {
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6, " [%2d]: start mask %8x, end mask %8x\n",
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  i, c->line_start_mask[i], c->line_end_mask[i]);
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* We use lower tag bits as offset pointers to cache use info.
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     * I.e. some cache parameters don't work.
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     */
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ( (1<<c->tag_shift) < c->assoc) {
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(message)(Vg_DebugMsg,
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     "error: Use associativity < %d for cache use statistics!\n",
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     (1<<c->tag_shift) );
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	VG_(tool_panic)("Unsupported cache configuration");
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* for I1/D1 caches */
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define CACHEUSE(L)                                                         \
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CacheModelResult cacheuse##_##L##_doRead(Addr a, UChar size)         \
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                                           \
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt set1 = ( a         >> L.line_size_bits) & (L.sets_min_1);           \
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt set2 = ((a+size-1) >> L.line_size_bits) & (L.sets_min_1);           \
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord tag  = a & L.tag_mask;                                             \
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord tag2;                                                              \
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i, j, idx;                                                           \
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord *set, tmp_tag; 						    \
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt use_mask;							    \
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(6,"%s.Acc(Addr %#lx, size %d): Sets [%d/%d]\n",                  \
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    L.name, a, size, set1, set2);				    \
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* First case: word entirely within line. */                             \
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (set1 == set2) {                                                      \
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set = &(L.tags[set1 * L.assoc]);                                      \
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      use_mask = L.line_start_mask[a & L.line_size_mask] &                  \
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	         L.line_end_mask[(a+size-1) & L.line_size_mask];	    \
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* This loop is unrolled for just the first case, which is the most */\
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* common.  We can't unroll any further because it would screw up   */\
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* if we have a direct-mapped (1-way) cache.                        */\
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tag == (set[0] & L.tag_mask)) {                                   \
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        idx = (set1 * L.assoc) + (set[0] & ~L.tag_mask);                    \
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        L.use[idx].count ++;                                                \
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        L.use[idx].mask |= use_mask;                                        \
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6," Hit0 [idx %d] (line %#lx from %#lx): %x => %08x, count %d\n",\
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 idx, L.loaded[idx].memline,  L.loaded[idx].iaddr,          \
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 use_mask, L.use[idx].mask, L.use[idx].count);              \
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return L1_Hit;							    \
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* If the tag is one other than the MRU, move it into the MRU spot  */\
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* and shuffle the rest down.                                       */\
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 1; i < L.assoc; i++) {                                       \
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (tag == (set[i] & L.tag_mask)) {			            \
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  	    tmp_tag = set[i];                                               \
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = i; j > 0; j--) {                                       \
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set[j] = set[j - 1];                                         \
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }                                                               \
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set[0] = tmp_tag;			                            \
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            idx = (set1 * L.assoc) + (tmp_tag & ~L.tag_mask);               \
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            L.use[idx].count ++;                                            \
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            L.use[idx].mask |= use_mask;                                    \
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6," Hit%d [idx %d] (line %#lx from %#lx): %x => %08x, count %d\n",\
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 i, idx, L.loaded[idx].memline,  L.loaded[idx].iaddr,       \
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 use_mask, L.use[idx].mask, L.use[idx].count);              \
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return L1_Hit;                                                  \
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }                                                                  \
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* A miss;  install this tag as MRU, shuffle rest down. */            \
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp_tag = set[L.assoc - 1] & ~L.tag_mask;                             \
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = L.assoc - 1; j > 0; j--) {                                   \
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set[j] = set[j - 1];                                               \
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set[0] = tag | tmp_tag;                                               \
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      idx = (set1 * L.assoc) + tmp_tag;                                     \
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return update_##L##_use(&L, idx,         			            \
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       use_mask, a &~ L.line_size_mask);		    \
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Second case: word straddles two lines. */                             \
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Nb: this is a fast way of doing ((set1+1) % L.sets) */                \
750b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   } else if (((set1 + 1) & (L.sets_min_1)) == set2) {                      \
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Int miss1=0, miss2=0; /* 0: L1 hit, 1:L1 miss, 2:LL miss */           \
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set = &(L.tags[set1 * L.assoc]);                                      \
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      use_mask = L.line_start_mask[a & L.line_size_mask];		    \
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tag == (set[0] & L.tag_mask)) {                                   \
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         idx = (set1 * L.assoc) + (set[0] & ~L.tag_mask);                   \
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         L.use[idx].count ++;                                               \
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         L.use[idx].mask |= use_mask;                                       \
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6," Hit0 [idx %d] (line %#lx from %#lx): %x => %08x, count %d\n",\
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 idx, L.loaded[idx].memline,  L.loaded[idx].iaddr,          \
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 use_mask, L.use[idx].mask, L.use[idx].count);              \
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto block2;                                                       \
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 1; i < L.assoc; i++) {                                       \
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (tag == (set[i] & L.tag_mask)) {			            \
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  	    tmp_tag = set[i];                                               \
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = i; j > 0; j--) {                                       \
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set[j] = set[j - 1];                                         \
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }                                                               \
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set[0] = tmp_tag;                                               \
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            idx = (set1 * L.assoc) + (tmp_tag & ~L.tag_mask);               \
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            L.use[idx].count ++;                                            \
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            L.use[idx].mask |= use_mask;                                    \
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6," Hit%d [idx %d] (line %#lx from %#lx): %x => %08x, count %d\n",\
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 i, idx, L.loaded[idx].memline,  L.loaded[idx].iaddr,       \
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 use_mask, L.use[idx].mask, L.use[idx].count);              \
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            goto block2;                                                    \
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }                                                                  \
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp_tag = set[L.assoc - 1] & ~L.tag_mask;                             \
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = L.assoc - 1; j > 0; j--) {                                   \
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set[j] = set[j - 1];                                               \
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set[0] = tag | tmp_tag;                                               \
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      idx = (set1 * L.assoc) + tmp_tag;                                     \
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      miss1 = update_##L##_use(&L, idx,        			            \
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       use_mask, a &~ L.line_size_mask);		    \
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownblock2:                                                                     \
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set = &(L.tags[set2 * L.assoc]);                                      \
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      use_mask = L.line_end_mask[(a+size-1) & L.line_size_mask];  	    \
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tag2  = (a+size-1) & L.tag_mask;                                      \
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (tag2 == (set[0] & L.tag_mask)) {                                  \
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         idx = (set2 * L.assoc) + (set[0] & ~L.tag_mask);                   \
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         L.use[idx].count ++;                                               \
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         L.use[idx].mask |= use_mask;                                       \
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6," Hit0 [idx %d] (line %#lx from %#lx): %x => %08x, count %d\n",\
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 idx, L.loaded[idx].memline,  L.loaded[idx].iaddr,          \
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 use_mask, L.use[idx].mask, L.use[idx].count);              \
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return miss1;                                                      \
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (i = 1; i < L.assoc; i++) {                                       \
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 if (tag2 == (set[i] & L.tag_mask)) {			            \
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  	    tmp_tag = set[i];                                               \
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            for (j = i; j > 0; j--) {                                       \
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               set[j] = set[j - 1];                                         \
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }                                                               \
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            set[0] = tmp_tag;                                               \
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            idx = (set2 * L.assoc) + (tmp_tag & ~L.tag_mask);               \
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            L.use[idx].count ++;                                            \
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            L.use[idx].mask |= use_mask;                                    \
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6," Hit%d [idx %d] (line %#lx from %#lx): %x => %08x, count %d\n",\
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 i, idx, L.loaded[idx].memline,  L.loaded[idx].iaddr,       \
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 use_mask, L.use[idx].mask, L.use[idx].count);              \
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return miss1;                                                   \
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }                                                                  \
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tmp_tag = set[L.assoc - 1] & ~L.tag_mask;                             \
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (j = L.assoc - 1; j > 0; j--) {                                   \
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         set[j] = set[j - 1];                                               \
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }                                                                     \
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      set[0] = tag2 | tmp_tag;                                              \
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      idx = (set2 * L.assoc) + tmp_tag;                                     \
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      miss2 = update_##L##_use(&L, idx,			                    \
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       use_mask, (a+size-1) &~ L.line_size_mask);	    \
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return (miss1==MemAccess || miss2==MemAccess) ? MemAccess:LL_Hit;     \
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                            \
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {                                                                 \
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(printf)("addr: %#lx  size: %u  sets: %d %d", a, size, set1, set2); \
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       VG_(tool_panic)("item straddles more than two cache sets");          \
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }                                                                        \
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;                                                                \
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* logarithmic bitcounting algorithm, see
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * http://graphics.stanford.edu/~seander/bithacks.html
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__ unsigned int countBits(unsigned int bits)
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unsigned int c; // store the total here
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const int S[] = {1, 2, 4, 8, 16}; // Magic Binary Numbers
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  c = bits;
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  c = ((c >> S[0]) & B[0]) + (c & B[0]);
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  c = ((c >> S[1]) & B[1]) + (c & B[1]);
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  c = ((c >> S[2]) & B[2]) + (c & B[2]);
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  c = ((c >> S[3]) & B[3]) + (c & B[3]);
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  c = ((c >> S[4]) & B[4]) + (c & B[4]);
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return c;
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void update_LL_use(int idx, Addr memline)
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  line_loaded* loaded = &(LL.loaded[idx]);
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  line_use* use = &(LL.use[idx]);
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int i = ((32 - countBits(use->mask)) * LL.line_size)>>5;
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(2, " LL.miss [%d]: at %#lx accessing memline %#lx\n",
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           idx, CLG_(bb_base) + current_ii->instr_offset, memline);
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (use->count>0) {
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "   old: used %d, loss bits %d (%08x) [line %#lx from %#lx]\n",
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     use->count, i, use->mask, loaded->memline, loaded->iaddr);
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "   collect: %d, use_base %p\n",
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     CLG_(current_state).collect, loaded->use_base);
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).collect && loaded->use_base) {
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (loaded->use_base)[off_LL_AcCost] += 1000 / use->count;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (loaded->use_base)[off_LL_SpLoss] += i;
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use->count = 0;
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   use->mask  = 0;
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  loaded->memline = memline;
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  loaded->iaddr   = CLG_(bb_base) + current_ii->instr_offset;
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  loaded->use_base = (CLG_(current_state).nonskipped) ?
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).nonskipped->skipped :
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cost_base) + current_ii->cost_offset;
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCacheModelResult cacheuse_LL_access(Addr memline, line_loaded* l1_loaded)
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt setNo = (memline >> LL.line_size_bits) & (LL.sets_min_1);
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord* set = &(LL.tags[setNo * LL.assoc]);
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord tag  = memline & LL.tag_mask;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i, j, idx;
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord tmp_tag;
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   CLG_DEBUG(6,"LL.Acc(Memline %#lx): Set %d\n", memline, setNo);
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (tag == (set[0] & LL.tag_mask)) {
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     idx = (setNo * LL.assoc) + (set[0] & ~LL.tag_mask);
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     l1_loaded->dep_use = &(LL.use[idx]);
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     CLG_DEBUG(6," Hit0 [idx %d] (line %#lx from %#lx): => %08x, count %d\n",
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 idx, LL.loaded[idx].memline,  LL.loaded[idx].iaddr,
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 LL.use[idx].mask, LL.use[idx].count);
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return LL_Hit;
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 1; i < LL.assoc; i++) {
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (tag == (set[i] & LL.tag_mask)) {
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       tmp_tag = set[i];
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       for (j = i; j > 0; j--) {
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 set[j] = set[j - 1];
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       set[0] = tmp_tag;
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       idx = (setNo * LL.assoc) + (tmp_tag & ~LL.tag_mask);
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       l1_loaded->dep_use = &(LL.use[idx]);
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(6," Hit%d [idx %d] (line %#lx from %#lx): => %08x, count %d\n",
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 i, idx, LL.loaded[idx].memline,  LL.loaded[idx].iaddr,
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 LL.use[idx].mask, LL.use[idx].count);
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return LL_Hit;
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* A miss;  install this tag as MRU, shuffle rest down. */
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tmp_tag = set[LL.assoc - 1] & ~LL.tag_mask;
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = LL.assoc - 1; j > 0; j--) {
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     set[j] = set[j - 1];
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   set[0] = tag | tmp_tag;
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   idx = (setNo * LL.assoc) + tmp_tag;
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   l1_loaded->dep_use = &(LL.use[idx]);
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   update_LL_use(idx, memline);
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return MemAccess;
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define UPDATE_USE(L)					             \
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                     \
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic CacheModelResult update##_##L##_use(cache_t2* cache, int idx, \
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			       UInt mask, Addr memline)		     \
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{                                                                    \
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  line_loaded* loaded = &(cache->loaded[idx]);			     \
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  line_use* use = &(cache->use[idx]);				     \
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int c = ((32 - countBits(use->mask)) * cache->line_size)>>5;       \
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                     \
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_DEBUG(2, " %s.miss [%d]: at %#lx accessing memline %#lx (mask %08x)\n", \
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           cache->name, idx, CLG_(bb_base) + current_ii->instr_offset, memline, mask); \
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (use->count>0) {                                                \
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "   old: used %d, loss bits %d (%08x) [line %#lx from %#lx]\n",\
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     use->count, c, use->mask, loaded->memline, loaded->iaddr);	\
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(2, "   collect: %d, use_base %p\n", \
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     CLG_(current_state).collect, loaded->use_base);	     \
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                     \
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).collect && loaded->use_base) {           \
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (loaded->use_base)[off_##L##_AcCost] += 1000 / use->count;     \
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (loaded->use_base)[off_##L##_SpLoss] += c;                     \
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                     \
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FIXME (?): L1/LL line sizes must be equal ! */              \
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loaded->dep_use->mask |= use->mask;                            \
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      loaded->dep_use->count += use->count;                          \
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }                                                                \
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }                                                                  \
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                     \
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  use->count = 1;                                                    \
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  use->mask  = mask;                                                 \
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  loaded->memline = memline;                                         \
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  loaded->iaddr   = CLG_(bb_base) + current_ii->instr_offset;        \
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  loaded->use_base = (CLG_(current_state).nonskipped) ?              \
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(current_state).nonskipped->skipped :                        \
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cost_base) + current_ii->cost_offset;                       \
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                                     \
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (memline == 0) return LL_Hit;                                   \
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return cacheuse_LL_access(memline, loaded);                        \
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUPDATE_USE(I1);
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownUPDATE_USE(D1);
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCACHEUSE(I1);
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCACHEUSE(D1);
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid cacheuse_finish(void)
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int i;
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  InstrInfo ii = { 0,0,0,0 };
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!CLG_(current_state).collect) return;
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(bb_base) = 0;
992b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  current_ii = &ii; /* needs to be set for update_XX_use */
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cost_base) = 0;
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* update usage counters */
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (I1.use)
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 0; i < I1.sets * I1.assoc; i++)
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (I1.loaded[i].use_base)
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	update_I1_use( &I1, i, 0,0);
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (D1.use)
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 0; i < D1.sets * D1.assoc; i++)
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (D1.loaded[i].use_base)
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	update_D1_use( &D1, i, 0,0);
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (LL.use)
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (i = 0; i < LL.sets * LL.assoc; i++)
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (LL.loaded[i].use_base)
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	update_LL_use(i, 0);
1010b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1011b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  current_ii = 0;
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Helper functions called by instrumented code         ---*/
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __inline__
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid inc_costs(CacheModelResult r, ULong* c1, ULong* c2)
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(r) {
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case WriteBackMemAccess:
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    if (clo_simulate_writeback) {
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		c1[3]++;
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		c2[3]++;
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    }
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // fall through
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case MemAccess:
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c1[2]++;
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c2[2]++;
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // fall through
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	case LL_Hit:
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c1[1]++;
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c2[1]++;
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    // fall through
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	default:
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c1[0]++;
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    c2[0]++;
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1049436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst HChar* cacheRes(CacheModelResult r)
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(r) {
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case L1_Hit:    return "L1 Hit ";
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case LL_Hit:    return "LL Hit ";
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case MemAccess: return "LL Miss";
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    case WriteBackMemAccess: return "LL Miss (dirty)";
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    default:
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	tl_assert(0);
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return "??";
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(1)
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_1I0D(InstrInfo* ii)
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CacheModelResult IrRes;
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii;
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    IrRes = (*simulator.I1_Read)(CLG_(bb_base) + ii->instr_offset, ii->instr_size);
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_1I0D:  Ir  %#lx/%u => %s\n",
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii->instr_offset, ii->instr_size, cacheRes(IrRes));
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).collect) {
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong* cost_Ir;
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(current_state).nonskipped)
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cost_Ir = CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cost_Ir = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_IR];
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(IrRes, cost_Ir,
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost + fullOffset(EG_IR) );
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(2)
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_2I0D(InstrInfo* ii1, InstrInfo* ii2)
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CacheModelResult Ir1Res, Ir2Res;
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong *global_cost_Ir;
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii1;
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Ir1Res = (*simulator.I1_Read)(CLG_(bb_base) + ii1->instr_offset, ii1->instr_size);
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii2;
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Ir2Res = (*simulator.I1_Read)(CLG_(bb_base) + ii2->instr_offset, ii2->instr_size);
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_2I0D:  Ir1 %#lx/%u => %s, Ir2 %#lx/%u => %s\n",
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii1->instr_offset, ii1->instr_size, cacheRes(Ir1Res),
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii2->instr_offset, ii2->instr_size, cacheRes(Ir2Res) );
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(current_state).collect) return;
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    global_cost_Ir = CLG_(current_state).cost + fullOffset(EG_IR);
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).nonskipped) {
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong* skipped_cost_Ir =
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(Ir1Res, global_cost_Ir, skipped_cost_Ir);
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(Ir2Res, global_cost_Ir, skipped_cost_Ir);
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return;
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    inc_costs(Ir1Res, global_cost_Ir,
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(cost_base) + ii1->cost_offset + ii1->eventset->offset[EG_IR]);
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    inc_costs(Ir2Res, global_cost_Ir,
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(cost_base) + ii2->cost_offset + ii2->eventset->offset[EG_IR]);
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(3)
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_3I0D(InstrInfo* ii1, InstrInfo* ii2, InstrInfo* ii3)
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CacheModelResult Ir1Res, Ir2Res, Ir3Res;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ULong *global_cost_Ir;
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii1;
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Ir1Res = (*simulator.I1_Read)(CLG_(bb_base) + ii1->instr_offset, ii1->instr_size);
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii2;
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Ir2Res = (*simulator.I1_Read)(CLG_(bb_base) + ii2->instr_offset, ii2->instr_size);
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii3;
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Ir3Res = (*simulator.I1_Read)(CLG_(bb_base) + ii3->instr_offset, ii3->instr_size);
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_3I0D:  Ir1 %#lx/%u => %s, Ir2 %#lx/%u => %s, Ir3 %#lx/%u => %s\n",
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii1->instr_offset, ii1->instr_size, cacheRes(Ir1Res),
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii2->instr_offset, ii2->instr_size, cacheRes(Ir2Res),
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii3->instr_offset, ii3->instr_size, cacheRes(Ir3Res) );
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(current_state).collect) return;
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    global_cost_Ir = CLG_(current_state).cost + fullOffset(EG_IR);
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).nonskipped) {
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong* skipped_cost_Ir =
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(Ir1Res, global_cost_Ir, skipped_cost_Ir);
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(Ir2Res, global_cost_Ir, skipped_cost_Ir);
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(Ir3Res, global_cost_Ir, skipped_cost_Ir);
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	return;
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    inc_costs(Ir1Res, global_cost_Ir,
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(cost_base) + ii1->cost_offset + ii1->eventset->offset[EG_IR]);
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    inc_costs(Ir2Res, global_cost_Ir,
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(cost_base) + ii2->cost_offset + ii2->eventset->offset[EG_IR]);
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    inc_costs(Ir3Res, global_cost_Ir,
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(cost_base) + ii3->cost_offset + ii3->eventset->offset[EG_IR]);
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Instruction doing a read access */
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(3)
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_1I1Dr(InstrInfo* ii, Addr data_addr, Word data_size)
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CacheModelResult IrRes, DrRes;
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii;
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    IrRes = (*simulator.I1_Read)(CLG_(bb_base) + ii->instr_offset, ii->instr_size);
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DrRes = (*simulator.D1_Read)(data_addr, data_size);
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_1I1Dr: Ir  %#lx/%u => %s, Dr  %#lx/%lu => %s\n",
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii->instr_offset, ii->instr_size, cacheRes(IrRes),
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      data_addr, data_size, cacheRes(DrRes));
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).collect) {
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong *cost_Ir, *cost_Dr;
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(current_state).nonskipped) {
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cost_Ir = CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cost_Dr = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DR);
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cost_Ir = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_IR];
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cost_Dr = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_DR];
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(IrRes, cost_Ir,
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost + fullOffset(EG_IR) );
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(DrRes, cost_Dr,
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost + fullOffset(EG_DR) );
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Note that addEvent_D_guarded assumes that log_0I1Dr and log_0I1Dw
1193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   have exactly the same prototype.  If you change them, you must
1194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   change addEvent_D_guarded too. */
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(3)
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_0I1Dr(InstrInfo* ii, Addr data_addr, Word data_size)
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CacheModelResult DrRes;
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii;
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DrRes = (*simulator.D1_Read)(data_addr, data_size);
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_0I1Dr: Dr  %#lx/%lu => %s\n",
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      data_addr, data_size, cacheRes(DrRes));
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).collect) {
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong *cost_Dr;
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(current_state).nonskipped)
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cost_Dr = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DR);
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cost_Dr = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_DR];
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(DrRes, cost_Dr,
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost + fullOffset(EG_DR) );
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Instruction doing a write access */
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(3)
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_1I1Dw(InstrInfo* ii, Addr data_addr, Word data_size)
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CacheModelResult IrRes, DwRes;
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii;
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    IrRes = (*simulator.I1_Read)(CLG_(bb_base) + ii->instr_offset, ii->instr_size);
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DwRes = (*simulator.D1_Write)(data_addr, data_size);
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_1I1Dw: Ir  %#lx/%u => %s, Dw  %#lx/%lu => %s\n",
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              CLG_(bb_base) + ii->instr_offset, ii->instr_size, cacheRes(IrRes),
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      data_addr, data_size, cacheRes(DwRes));
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).collect) {
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong *cost_Ir, *cost_Dw;
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(current_state).nonskipped) {
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cost_Ir = CLG_(current_state).nonskipped->skipped + fullOffset(EG_IR);
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cost_Dw = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DW);
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else {
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cost_Ir = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_IR];
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cost_Dw = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_DW];
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	}
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(IrRes, cost_Ir,
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost + fullOffset(EG_IR) );
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(DwRes, cost_Dw,
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost + fullOffset(EG_DW) );
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* See comment on log_0I1Dr. */
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVG_REGPARM(3)
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void log_0I1Dw(InstrInfo* ii, Addr data_addr, Word data_size)
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CacheModelResult DwRes;
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    current_ii = ii;
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    DwRes = (*simulator.D1_Write)(data_addr, data_size);
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUG(6, "log_0I1Dw: Dw  %#lx/%lu => %s\n",
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	      data_addr, data_size, cacheRes(DwRes));
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(current_state).collect) {
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	ULong *cost_Dw;
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	if (CLG_(current_state).nonskipped)
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	    cost_Dw = CLG_(current_state).nonskipped->skipped + fullOffset(EG_DW);
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	else
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            cost_Dw = CLG_(cost_base) + ii->cost_offset + ii->eventset->offset[EG_DW];
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	inc_costs(DwRes, cost_Dw,
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		  CLG_(current_state).cost + fullOffset(EG_DW) );
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Cache configuration                                  ---*/
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic cache_t clo_I1_cache = UNDEFINED_CACHE;
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic cache_t clo_D1_cache = UNDEFINED_CACHE;
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic cache_t clo_LL_cache = UNDEFINED_CACHE;
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Initialize and clear simulator state */
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cachesim_post_clo_init(void)
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Cache configurations. */
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cache_t  I1c, D1c, LLc;
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Initialize access handlers */
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!CLG_(clo).simulate_cache) {
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_1I0D  = 0;
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_1I0D_name = "(no function)";
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_2I0D  = 0;
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_2I0D_name = "(no function)";
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_3I0D  = 0;
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_3I0D_name = "(no function)";
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_1I1Dr = 0;
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_1I1Dr_name = "(no function)";
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_1I1Dw = 0;
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_1I1Dw_name = "(no function)";
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_0I1Dr = 0;
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_0I1Dr_name = "(no function)";
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_0I1Dw = 0;
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(cachesim).log_0I1Dw_name = "(no function)";
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return;
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* Configuration of caches only needed with real cache simulation */
1317b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  VG_(post_clo_init_configure_caches)(&I1c, &D1c, &LLc,
1318b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      &clo_I1_cache,
1319b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      &clo_D1_cache,
1320b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                      &clo_LL_cache);
1321b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  I1.name = "I1";
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  D1.name = "D1";
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  LL.name = "LL";
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  // min_line_size is used to make sure that we never feed
1327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  // accesses to the simulator straddling more than two
1328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  // cache lines at any cache level
1329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  CLG_(min_line_size) = (I1c.line_size < D1c.line_size)
1330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           ? I1c.line_size : D1c.line_size;
1331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  CLG_(min_line_size) = (LLc.line_size < CLG_(min_line_size))
1332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                           ? LLc.line_size : CLG_(min_line_size);
1333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  Int largest_load_or_store_size
1335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     = VG_(machine_get_size_of_largest_guest_register)();
1336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  if (CLG_(min_line_size) < largest_load_or_store_size) {
1337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     /* We can't continue, because the cache simulation might
1338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        straddle more than 2 lines, and it will assert.  So let's
1339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng        just stop before we start. */
1340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     VG_(umsg)("Callgrind: cannot continue: the minimum line size (%d)\n",
1341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               (Int)CLG_(min_line_size));
1342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     VG_(umsg)("  must be equal to or larger than the maximum register size (%d)\n",
1343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng               largest_load_or_store_size );
1344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     VG_(umsg)("  but it is not.  Exiting now.\n");
1345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     VG_(exit)(1);
1346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng  }
1347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cachesim_initcache(I1c, &I1);
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cachesim_initcache(D1c, &D1);
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cachesim_initcache(LLc, &LL);
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* the other cache simulators use the standard helpers
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * with dispatching via simulator struct */
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_1I0D  = log_1I0D;
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_1I0D_name  = "log_1I0D";
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_2I0D  = log_2I0D;
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_2I0D_name  = "log_2I0D";
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_3I0D  = log_3I0D;
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_3I0D_name  = "log_3I0D";
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_1I1Dr = log_1I1Dr;
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_1I1Dw = log_1I1Dw;
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_1I1Dr_name = "log_1I1Dr";
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_1I1Dw_name = "log_1I1Dw";
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_0I1Dr = log_0I1Dr;
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_0I1Dw = log_0I1Dw;
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_0I1Dr_name = "log_0I1Dr";
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(cachesim).log_0I1Dw_name = "log_0I1Dw";
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (clo_collect_cacheuse) {
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Output warning for not supported option combinations */
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (clo_simulate_hwpref) {
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  VG_(message)(Vg_DebugMsg,
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       "warning: prefetch simulation can not be "
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       "used with cache usage\n");
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  clo_simulate_hwpref = False;
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (clo_simulate_writeback) {
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  VG_(message)(Vg_DebugMsg,
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		       "warning: write-back simulation can not be "
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       "used with cache usage\n");
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	  clo_simulate_writeback = False;
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.I1_Read  = cacheuse_I1_doRead;
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Read  = cacheuse_D1_doRead;
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Write = cacheuse_D1_doRead;
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (clo_simulate_hwpref) {
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    prefetch_clear();
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (clo_simulate_writeback) {
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.I1_Read  = prefetch_I1_Read;
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Read  = prefetch_D1_Read;
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Write = prefetch_D1_Write;
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else {
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.I1_Read  = prefetch_I1_ref;
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Read  = prefetch_D1_ref;
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Write = prefetch_D1_ref;
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return;
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (clo_simulate_writeback) {
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.I1_Read  = cachesim_I1_Read;
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Read  = cachesim_D1_Read;
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Write = cachesim_D1_Write;
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  else {
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.I1_Read  = cachesim_I1_ref;
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Read  = cachesim_D1_ref;
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      simulator.D1_Write = cachesim_D1_ref;
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Clear simulator state. Has to be initialized before */
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid cachesim_clear(void)
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cachesim_clearcache(&I1);
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cachesim_clearcache(&D1);
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  cachesim_clearcache(&LL);
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  prefetch_clear();
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void cachesim_getdesc(HChar* buf)
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int p;
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  p = VG_(sprintf)(buf, "\ndesc: I1 cache: %s\n", I1.desc_line);
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  p += VG_(sprintf)(buf+p, "desc: D1 cache: %s\n", D1.desc_line);
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(sprintf)(buf+p, "desc: LL cache: %s\n", LL.desc_line);
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid cachesim_print_opts(void)
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(printf)(
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"\n   cache simulator options (does cache simulation if used):\n"
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --simulate-wb=no|yes      Count write-back events [no]\n"
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --simulate-hwpref=no|yes  Simulate hardware prefetch [no]\n"
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if CLG_EXPERIMENTAL
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"    --simulate-sectors=no|yes Simulate sectored behaviour [no]\n"
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
1455b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov"    --cacheuse=no|yes         Collect cache block use [no]\n");
1456b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  VG_(print_cache_clo_opts)();
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Check for command line option for cache configuration.
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Return False if unknown and not handled.
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Called from CLG_(process_cmd_line_option)() in clo.c
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
1464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic Bool cachesim_parse_opt(const HChar* arg)
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if      VG_BOOL_CLO(arg, "--simulate-wb",      clo_simulate_writeback) {}
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--simulate-hwpref",  clo_simulate_hwpref)    {}
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--simulate-sectors", clo_simulate_sectors)   {}
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else if VG_BOOL_CLO(arg, "--cacheuse", clo_collect_cacheuse) {
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (clo_collect_cacheuse) {
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Use counters only make sense with fine dumping */
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         CLG_(clo).dump_instr = True;
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1477b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else if (VG_(str_clo_cache_opt)(arg,
1478b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   &clo_I1_cache,
1479b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   &clo_D1_cache,
1480b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov                                   &clo_LL_cache)) {}
1481b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov
1482b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov   else
1483b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov     return False;
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return True;
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Adds commas to ULong, right justifying in a field field_width wide, returns
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the string in buf. */
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovInt commify(ULong n, int field_width, HChar* buf)
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int len, n_commas, i, j, new_len, space;
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sprintf)(buf, "%llu", n);
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   len = VG_(strlen)(buf);
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   n_commas = (len - 1) / 3;
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   new_len = len + n_commas;
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   space = field_width - new_len;
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Allow for printing a number in a field_width smaller than it's size */
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (space < 0) space = 0;
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make j = -1 because we copy the '\0' before doing the numbers in groups
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    * of three. */
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (j = -1, i = len ; i >= 0; i--) {
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      buf[i + n_commas + space] = buf[i];
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((i>0) && (3 == ++j)) {
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         j = 0;
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         n_commas--;
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         buf[i + n_commas + space] = ',';
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Right justify in field. */
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < space; i++)  buf[i] = ' ';
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return new_len;
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid percentify(Int n, Int ex, Int field_width, HChar buf[])
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int i, len, space;
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sprintf)(buf, "%d.%d%%", n / ex, n % ex);
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   len = VG_(strlen)(buf);
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   space = field_width - len;
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (space < 0) space = 0;     /* Allow for v. small field_width */
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   i = len;
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Right justify in field */
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (     ; i >= 0;    i--)  buf[i + space] = buf[i];
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < space; i++)  buf[i] = ' ';
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid cachesim_printstat(Int l1, Int l2, Int l3)
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FullCost total = CLG_(total_cost), D_total = 0;
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ULong LL_total_m, LL_total_mr, LL_total_mw,
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    LL_total, LL_total_r, LL_total_w;
1542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  HChar buf1[RESULTS_BUF_LEN],
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    buf2[RESULTS_BUF_LEN],
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    buf3[RESULTS_BUF_LEN];
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Int p;
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if ((VG_(clo_verbosity) >1) && clo_simulate_hwpref) {
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(message)(Vg_DebugMsg, "Prefetch Up:       %llu\n",
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 prefetch_up);
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(message)(Vg_DebugMsg, "Prefetch Down:     %llu\n",
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		 prefetch_down);
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    VG_(message)(Vg_DebugMsg, "\n");
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_IR) +1], l1, buf1);
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "I1  misses:    %s\n", buf1);
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_IR) +2], l1, buf1);
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "LLi misses:    %s\n", buf1);
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  p = 100;
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (0 == total[fullOffset(EG_IR)])
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_IR)] = 1;
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(total[fullOffset(EG_IR)+1] * 100 * p /
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total[fullOffset(EG_IR)], p, l1+1, buf1);
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "I1  miss rate: %s\n", buf1);
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(total[fullOffset(EG_IR)+2] * 100 * p /
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total[fullOffset(EG_IR)], p, l1+1, buf1);
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "LLi miss rate: %s\n", buf1);
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "\n");
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* D cache results.
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     Use the D_refs.rd and D_refs.wr values to determine the
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   * width of columns 2 & 3. */
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  D_total = CLG_(get_eventset_cost)( CLG_(sets).full );
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(init_cost)( CLG_(sets).full, D_total);
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // we only use the first 3 values of D_total, adding up Dr and Dw costs
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(copy_cost)( CLG_(get_event_set)(EG_DR), D_total, total + fullOffset(EG_DR) );
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CLG_(add_cost) ( CLG_(get_event_set)(EG_DW), D_total, total + fullOffset(EG_DW) );
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify( D_total[0], l1, buf1);
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_DR)], l2,  buf2);
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_DW)], l3,  buf3);
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "D   refs:      %s  (%s rd + %s wr)\n",
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       buf1,  buf2,  buf3);
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify( D_total[1], l1, buf1);
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_DR)+1], l2, buf2);
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_DW)+1], l3, buf3);
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "D1  misses:    %s  (%s rd + %s wr)\n",
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       buf1, buf2, buf3);
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify( D_total[2], l1, buf1);
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_DR)+2], l2, buf2);
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(total[fullOffset(EG_DW)+2], l3, buf3);
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "LLd misses:    %s  (%s rd + %s wr)\n",
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       buf1, buf2, buf3);
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  p = 10;
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (0 == D_total[0])   D_total[0] = 1;
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (0 == total[fullOffset(EG_DR)]) total[fullOffset(EG_DR)] = 1;
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (0 == total[fullOffset(EG_DW)]) total[fullOffset(EG_DW)] = 1;
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify( D_total[1] * 100 * p / D_total[0],  p, l1+1, buf1);
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(total[fullOffset(EG_DR)+1] * 100 * p /
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total[fullOffset(EG_DR)], p, l2+1, buf2);
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(total[fullOffset(EG_DW)+1] * 100 * p /
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total[fullOffset(EG_DW)], p, l3+1, buf3);
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "D1  miss rate: %s (%s   + %s  )\n",
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               buf1, buf2,buf3);
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify( D_total[2] * 100 * p / D_total[0],  p, l1+1, buf1);
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(total[fullOffset(EG_DR)+2] * 100 * p /
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total[fullOffset(EG_DR)], p, l2+1, buf2);
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(total[fullOffset(EG_DW)+2] * 100 * p /
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total[fullOffset(EG_DW)], p, l3+1, buf3);
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "LLd miss rate: %s (%s   + %s  )\n",
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               buf1, buf2,buf3);
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "\n");
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* LL overall results */
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  LL_total   =
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_DR) +1] +
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_DW) +1] +
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_IR) +1];
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  LL_total_r =
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_DR) +1] +
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_IR) +1];
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  LL_total_w = total[fullOffset(EG_DW) +1];
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(LL_total,   l1, buf1);
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(LL_total_r, l2, buf2);
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(LL_total_w, l3, buf3);
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "LL refs:       %s  (%s rd + %s wr)\n",
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       buf1, buf2, buf3);
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  LL_total_m  =
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_DR) +2] +
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_DW) +2] +
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_IR) +2];
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  LL_total_mr =
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_DR) +2] +
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    total[fullOffset(EG_IR) +2];
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  LL_total_mw = total[fullOffset(EG_DW) +2];
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(LL_total_m,  l1, buf1);
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(LL_total_mr, l2, buf2);
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  commify(LL_total_mw, l3, buf3);
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "LL misses:     %s  (%s rd + %s wr)\n",
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       buf1, buf2, buf3);
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(LL_total_m  * 100 * p /
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     (total[fullOffset(EG_IR)] + D_total[0]),  p, l1+1, buf1);
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(LL_total_mr * 100 * p /
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     (total[fullOffset(EG_IR)] + total[fullOffset(EG_DR)]),
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     p, l2+1, buf2);
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  percentify(LL_total_mw * 100 * p /
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total[fullOffset(EG_DW)], p, l3+1, buf3);
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VG_(message)(Vg_UserMsg, "LL miss rate:  %s (%s   + %s  )\n",
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	       buf1, buf2,buf3);
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Setup for Event set.                                 ---*/
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct event_sets CLG_(sets);
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CLG_(init_eventsets)()
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // Event groups from which the event sets are composed
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // the "Use" group only is used with "cacheuse" simulation
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (clo_collect_cacheuse)
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group4)(EG_USE,
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				    "AcCost1", "SpLoss1", "AcCost2", "SpLoss2");
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(clo).simulate_cache)
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group)(EG_IR, "Ir");
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else if (!clo_simulate_writeback) {
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group3)(EG_IR, "Ir", "I1mr", "ILmr");
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group3)(EG_DR, "Dr", "D1mr", "DLmr");
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group3)(EG_DW, "Dw", "D1mw", "DLmw");
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else { // clo_simulate_writeback
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group4)(EG_IR, "Ir", "I1mr", "ILmr", "ILdmr");
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CLG_(register_event_group4)(EG_DR, "Dr", "D1mr", "DLmr", "DLdmr");
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CLG_(register_event_group4)(EG_DW, "Dw", "D1mw", "DLmw", "DLdmw");
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).simulate_branch) {
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CLG_(register_event_group2)(EG_BC, "Bc", "Bcm");
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CLG_(register_event_group2)(EG_BI, "Bi", "Bim");
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).collect_bus)
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group)(EG_BUS, "Ge");
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).collect_alloc)
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group2)(EG_ALLOC, "allocCount", "allocSize");
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (CLG_(clo).collect_systime)
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(register_event_group2)(EG_SYS, "sysCount", "sysTime");
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // event set used as base for instruction self cost
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(sets).base = CLG_(get_event_set2)(EG_USE, EG_IR);
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // event set comprising all event groups, used for inclusive cost
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(sets).full = CLG_(add_event_group2)(CLG_(sets).base, EG_DR, EG_DW);
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(sets).full = CLG_(add_event_group2)(CLG_(sets).full, EG_BC, EG_BI);
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(sets).full = CLG_(add_event_group) (CLG_(sets).full, EG_BUS);
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(sets).full = CLG_(add_event_group2)(CLG_(sets).full, EG_ALLOC, EG_SYS);
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_DEBUGIF(1) {
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_DEBUG(1, "EventSets:\n");
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(print_eventset)(-2, CLG_(sets).base);
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(print_eventset)(-2, CLG_(sets).full);
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    /* Not-existing events are silently ignored */
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(dumpmap) = CLG_(get_eventmapping)(CLG_(sets).full);
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Ir");
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Dr");
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Dw");
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "I1mr");
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "D1mr");
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "D1mw");
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "ILmr");
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "DLmr");
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "DLmw");
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "ILdmr");
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "DLdmr");
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "DLdmw");
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Bc");
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Bcm");
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Bi");
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Bim");
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "AcCost1");
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "SpLoss1");
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "AcCost2");
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "SpLoss2");
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "Ge");
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "allocCount");
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "allocSize");
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "sysCount");
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CLG_(append_event)(CLG_(dumpmap), "sysTime");
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* this is called at dump time for every instruction executed */
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void cachesim_add_icost(SimCost cost, BBCC* bbcc,
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			       InstrInfo* ii, ULong exe_count)
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!CLG_(clo).simulate_cache)
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	cost[ fullOffset(EG_IR) ] += exe_count;
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ii->eventset)
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	CLG_(add_and_zero_cost2)( CLG_(sets).full, cost,
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown				  ii->eventset, bbcc->cost + ii->cost_offset);
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid cachesim_finish(void)
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (clo_collect_cacheuse)
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    cacheuse_finish();
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- The simulator defined in this file                   ---*/
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct cachesim_if CLG_(cachesim) = {
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .print_opts    = cachesim_print_opts,
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .parse_opt     = cachesim_parse_opt,
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .post_clo_init = cachesim_post_clo_init,
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .clear         = cachesim_clear,
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .getdesc       = cachesim_getdesc,
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .printstat     = cachesim_printstat,
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .add_icost     = cachesim_add_icost,
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .finish        = cachesim_finish,
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /* these will be set by cachesim_post_clo_init */
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_1I0D        = 0,
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_2I0D        = 0,
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_3I0D        = 0,
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_1I1Dr       = 0,
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_1I1Dw       = 0,
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_0I1Dr       = 0,
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_0I1Dw       = 0,
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_1I0D_name = "(no function)",
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_2I0D_name = "(no function)",
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_3I0D_name = "(no function)",
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_1I1Dr_name = "(no function)",
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_1I1Dw_name = "(no function)",
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_0I1Dr_name = "(no function)",
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  .log_0I1Dw_name = "(no function)",
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                 ct_sim.c ---*/
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
1815