OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_52/] [or1ksim/] [cache/] [dcache_model.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 lampret
/* dcache_model.c -- data cache simulation
2
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
/* Cache functions.
21
   At the moment this functions only simulate functionality of data
22
   caches and do not influence on fetche/decode/execute stages and timings.
23
   They are here only to verify performance of various cache configurations.
24
 */
25
 
26
#include <stdio.h>
27
#include <string.h>
28
#include <errno.h>
29
#include <stdarg.h>
30
 
31 1350 nogj
#include "config.h"
32
 
33
#ifdef HAVE_INTTYPES_H
34
#include <inttypes.h>
35
#endif
36
 
37
#include "port.h"
38
#include "arch.h"
39 5 lampret
#include "dcache_model.h"
40
#include "abstract.h"
41 992 simons
#include "except.h"
42 1344 nogj
#include "opcode/or32.h"
43 5 lampret
#include "stats.h"
44 102 lampret
#include "spr_defs.h"
45
#include "sprs.h"
46 428 markom
#include "sim-config.h"
47 5 lampret
 
48
/* Data cache */
49
 
50
struct dc_set {
51 428 markom
  struct {
52 1350 nogj
    uint32_t line[MAX_DC_BLOCK_SIZE];
53
    oraddr_t tagaddr;  /* tag address */
54 428 markom
    int lru;    /* least recently used */
55
  } way[MAX_DC_WAYS];
56
} dc[MAX_DC_SETS];
57 5 lampret
 
58
void dc_info()
59
{
60 428 markom
  if (!testsprbits(SPR_UPR, SPR_UPR_DCP)) {
61 997 markom
    PRINTF("DCache not implemented. Set UPR[DCP].\n");
62 428 markom
    return;
63
  }
64
 
65 997 markom
  PRINTF("Data cache %dKB: ", config.dc.nsets * config.dc.blocksize * config.dc.nways / 1024);
66
  PRINTF("%d ways, %d sets, block size %d bytes\n", config.dc.nways, config.dc.nsets, config.dc.blocksize);
67 5 lampret
}
68
 
69
/* First check if data is already in the cache and if it is:
70
    - increment DC read hit stats,
71 428 markom
    - set 'lru' at this way to config.dc.ustates - 1 and
72 5 lampret
      decrement 'lru' of other ways unless they have reached 0,
73
   and if not:
74
    - increment DC read miss stats
75
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
76 428 markom
    - set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
77 5 lampret
      ways unless they have reached 0
78 631 simons
    - refill cache line
79 5 lampret
*/
80
 
81 1350 nogj
uint32_t dc_simulate_read(oraddr_t dataaddr, int width)
82 5 lampret
{
83 428 markom
  int set, way = -1;
84
  int i;
85 1350 nogj
  oraddr_t tagaddr;
86
  uint32_t tmp;
87 102 lampret
 
88 638 simons
  if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
89
      (!testsprbits(SPR_SR, SPR_SR_DCE))   ||
90
      data_ci) {
91 631 simons
    if (width == 4)
92 992 simons
      tmp = evalsim_mem32(dataaddr);
93 631 simons
    else if (width == 2)
94 1350 nogj
      tmp = evalsim_mem16(dataaddr);
95 631 simons
    else if (width == 1)
96 1350 nogj
      tmp = evalsim_mem8(dataaddr);
97 992 simons
 
98
    if(!cur_area) {
99
      if (width == 4)
100 1350 nogj
        printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
101
               dataaddr);
102 992 simons
      else if (width == 2)
103 1350 nogj
        printf("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n",
104
               dataaddr);
105 992 simons
      else if (width == 1)
106 1350 nogj
        printf("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n",
107
               dataaddr);
108 992 simons
      except_handle(EXCEPT_BUSERR, cur_vadd);
109
      return 0;
110 1386 nogj
    } else if (cur_area->log)
111 1350 nogj
      fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
112
               tmp);
113 992 simons
 
114
    return tmp;
115 631 simons
  }
116 102 lampret
 
117 428 markom
  /* Which set to check out? */
118
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
119
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
120
 
121
  /* Scan all ways and try to find a matching way. */
122
  for (i = 0; i < config.dc.nways; i++)
123
    if (dc[set].way[i].tagaddr == tagaddr)
124
      way = i;
125
 
126
  /* Did we find our cached data? */
127
  if (way >= 0) { /* Yes, we did. */
128
    dc_stats.readhit++;
129 541 markom
 
130 428 markom
    for (i = 0; i < config.dc.nways; i++)
131 631 simons
      if (dc[set].way[i].lru > dc[set].way[way].lru)
132 428 markom
        dc[set].way[i].lru--;
133
    dc[set].way[way].lru = config.dc.ustates - 1;
134 884 markom
    runtime.sim.mem_cycles += config.dc.load_hitdelay;
135 631 simons
 
136
    tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
137
    if (width == 4)
138
      return tmp;
139
    else if (width == 2) {
140 1350 nogj
      tmp = ((tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff);
141 631 simons
      return tmp;
142
    }
143
    else if (width == 1) {
144 1350 nogj
      tmp = ((tmp  >> (8 * (3 - (dataaddr & 3)))) & 0xff);
145 631 simons
      return tmp;
146
    }
147 541 markom
  } else {  /* No, we didn't. */
148 428 markom
    int minlru = config.dc.ustates - 1;
149
    int minway = 0;
150 5 lampret
 
151 631 simons
    dc_stats.readmiss++;
152 5 lampret
 
153 1085 simons
    for (i = 0; i < config.dc.nways; i++) {
154
      if (dc[set].way[i].lru < minlru) {
155 428 markom
        minway = i;
156 1085 simons
        minlru = dc[set].way[i].lru;
157
      }
158
    }
159 428 markom
 
160 631 simons
    for (i = 0; i < (config.dc.blocksize); i += 4) {
161
      dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
162
        evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
163 638 simons
      if(!cur_area) {
164
        dc[set].way[minway].tagaddr = -1;
165
        dc[set].way[minway].lru = 0;
166 1350 nogj
        printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
167
               dataaddr);
168 992 simons
        except_handle(EXCEPT_BUSERR, cur_vadd);
169 631 simons
        return 0;
170 1386 nogj
      } else if (cur_area->log)
171 1350 nogj
        fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
172
                 tmp);
173 631 simons
    }
174
 
175 428 markom
    dc[set].way[minway].tagaddr = tagaddr;
176
    for (i = 0; i < config.dc.nways; i++)
177
      if (dc[set].way[i].lru)
178
        dc[set].way[i].lru--;
179
    dc[set].way[minway].lru = config.dc.ustates - 1;
180 884 markom
    runtime.sim.mem_cycles += config.dc.load_missdelay;
181 631 simons
 
182
    tmp = dc[set].way[minway].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
183
    if (width == 4)
184
      return tmp;
185
    else if (width == 2) {
186 1350 nogj
      tmp = (tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff;
187 631 simons
      return tmp;
188
    }
189
    else if (width == 1) {
190 1350 nogj
      tmp = (tmp  >> (8 * (3 - (dataaddr & 3)))) & 0xff;
191 631 simons
      return tmp;
192
    }
193 428 markom
  }
194 5 lampret
}
195
 
196
/* First check if data is already in the cache and if it is:
197
    - increment DC write hit stats,
198 428 markom
    - set 'lru' at this way to config.dc.ustates - 1 and
199 5 lampret
      decrement 'lru' of other ways unless they have reached 0,
200
   and if not:
201
    - increment DC write miss stats
202
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
203 428 markom
    - set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
204 5 lampret
      ways unless they have reached 0
205
*/
206
 
207 1350 nogj
void dc_simulate_write(oraddr_t dataaddr, uint32_t data, int width)
208 5 lampret
{
209 428 markom
  int set, way = -1;
210
  int i;
211 1350 nogj
  oraddr_t tagaddr;
212
  uint32_t tmp;
213 102 lampret
 
214 631 simons
  if (width == 4)
215
    setsim_mem32(dataaddr, data);
216
  else if (width == 2)
217 1350 nogj
    setsim_mem16(dataaddr, data);
218 631 simons
  else if (width == 1)
219 1350 nogj
    setsim_mem8(dataaddr, data);
220 631 simons
 
221 638 simons
  if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
222
      (!testsprbits(SPR_SR, SPR_SR_DCE)) ||
223
      data_ci ||
224
      (!cur_area))
225 631 simons
    return;
226 428 markom
 
227
  /* Which set to check out? */
228
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
229
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
230
 
231
  /* Scan all ways and try to find a matching way. */
232
  for (i = 0; i < config.dc.nways; i++)
233
    if (dc[set].way[i].tagaddr == tagaddr)
234
      way = i;
235
 
236
  /* Did we find our cached data? */
237
  if (way >= 0) { /* Yes, we did. */
238
    dc_stats.writehit++;
239
 
240
    for (i = 0; i < config.dc.nways; i++)
241 631 simons
      if (dc[set].way[i].lru > dc[set].way[way].lru)
242 428 markom
        dc[set].way[i].lru--;
243
    dc[set].way[way].lru = config.dc.ustates - 1;
244 884 markom
    runtime.sim.mem_cycles += config.dc.store_hitdelay;
245 631 simons
 
246
    tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
247
    if (width == 4)
248
      tmp = data;
249
    else if (width == 2) {
250
      tmp &= 0xffff << ((dataaddr & 2) ? 16 : 0);
251 1350 nogj
      tmp |= (data & 0xffff) << ((dataaddr & 2) ? 0 : 16);
252 631 simons
    }
253
    else if (width == 1) {
254
      tmp &= ~(0xff << (8 * (3 - (dataaddr & 3))));
255 1350 nogj
      tmp |= (data & 0xff) << (8 * (3 - (dataaddr & 3)));
256 631 simons
    }
257
    dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2] = tmp;
258 428 markom
  }
259
  else {  /* No, we didn't. */
260
    int minlru = config.dc.ustates - 1;
261
    int minway = 0;
262 5 lampret
 
263 631 simons
    dc_stats.writemiss++;
264 5 lampret
 
265 428 markom
    for (i = 0; i < config.dc.nways; i++)
266 631 simons
      if (dc[set].way[i].lru < minlru)
267 428 markom
        minway = i;
268
 
269 631 simons
    for (i = 0; i < (config.dc.blocksize); i += 4) {
270
      dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
271
        evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
272 638 simons
      if(!cur_area) {
273
        dc[set].way[minway].tagaddr = -1;
274
        dc[set].way[minway].lru = 0;
275 631 simons
        return;
276 638 simons
      }
277 631 simons
    }
278
 
279 428 markom
    dc[set].way[minway].tagaddr = tagaddr;
280
    for (i = 0; i < config.dc.nways; i++)
281
      if (dc[set].way[i].lru)
282
        dc[set].way[i].lru--;
283
    dc[set].way[minway].lru = config.dc.ustates - 1;
284 884 markom
    runtime.sim.mem_cycles += config.dc.store_missdelay;
285 428 markom
  }
286 5 lampret
}
287 102 lampret
 
288
/* First check if data is already in the cache and if it is:
289
    - invalidate block if way isn't locked
290
   otherwise don't do anything.
291
*/
292
 
293 1350 nogj
void dc_inv(oraddr_t dataaddr)
294 102 lampret
{
295 428 markom
  int set, way = -1;
296
  int i;
297 1350 nogj
  oraddr_t tagaddr;
298 102 lampret
 
299 428 markom
  if (!testsprbits(SPR_UPR, SPR_UPR_DCP))
300
    return;
301 102 lampret
 
302 428 markom
  /* Which set to check out? */
303
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
304
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
305
 
306 631 simons
  if (!testsprbits(SPR_SR, SPR_SR_DCE)) {
307
    for (i = 0; i < config.dc.nways; i++) {
308
      dc[set].way[i].tagaddr = -1;
309
      dc[set].way[i].lru = 0;
310
    }
311
    return;
312
  }
313
   /* Scan all ways and try to find a matching way. */
314 428 markom
  for (i = 0; i < config.dc.nways; i++)
315
    if (dc[set].way[i].tagaddr == tagaddr)
316
      way = i;
317
 
318
  /* Did we find our cached data? */
319 631 simons
  if (way >= 0) { /* Yes, we did. */
320 428 markom
    dc[set].way[way].tagaddr = -1;
321 631 simons
    dc[set].way[way].lru = 0;
322 428 markom
  }
323 102 lampret
}
324
 
325 1358 nogj
/*-----------------------------------------------------[ DC configuration ]---*/
326
void dc_enabled(union param_val val, void *dat)
327
{
328
  config.dc.enabled = val.int_val;
329
  setsprbits (SPR_UPR, SPR_UPR_DCP, val.int_val ? 1 : 0);
330
}
331
 
332
void dc_nsets(union param_val val, void *dat)
333
{
334 1382 nogj
  if (is_power2(val.int_val) && val.int_val <= MAX_DC_SETS){
335 1358 nogj
    config.dc.nsets = val.int_val;
336 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_NCS, log2(val.int_val));
337
  }
338 1358 nogj
  else {
339
    char tmp[200];
340
    sprintf (tmp, "value of power of two and lower or equal than %i expected.", MAX_DC_SETS);
341
    CONFIG_ERROR(tmp);
342
  }
343
}
344
 
345
void dc_nways(union param_val val, void *dat)
346
{
347 1382 nogj
  if (is_power2(val.int_val) && val.int_val <= MAX_DC_WAYS){
348 1358 nogj
    config.dc.nways = val.int_val;
349 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_NCW, log2(val.int_val));
350
  }
351
  else{
352
    char tmp[200];
353
    sprintf (tmp, "value of power of two and lower or equal than %i expected.",
354
    MAX_DC_WAYS);
355
    CONFIG_ERROR(tmp);
356
  }
357 1358 nogj
}
358
 
359
void dc_blocksize(union param_val val, void *dat)
360
{
361 1382 nogj
  if (is_power2(val.int_val)) {
362 1358 nogj
    config.dc.blocksize = val.int_val;
363 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_CBS,log2(val.int_val));
364
  } else
365 1358 nogj
    CONFIG_ERROR("value of power of two expected.");
366
}
367
 
368
void dc_ustates(union param_val val, void *dat)
369
{
370
  if (val.int_val >= 2 && val.int_val <= 4)
371
    config.dc.ustates = val.int_val;
372
  else
373
    CONFIG_ERROR("invalid USTATE.");
374
}
375
 
376
void dc_load_missdelay(union param_val val, void *dat)
377
{
378
  config.dc.load_missdelay = val.int_val;
379
}
380
 
381
void dc_load_hitdelay(union param_val val, void *dat)
382
{
383
  config.dc.load_hitdelay = val.int_val;
384
}
385
 
386
void dc_store_missdelay(union param_val val, void *dat)
387
{
388
  config.dc.store_missdelay = val.int_val;
389
}
390
 
391
void dc_store_hitdelay(union param_val val, void *dat)
392
{
393
  config.dc.store_hitdelay = val.int_val;
394
}
395
 
396
void reg_dc_sec(void)
397
{
398
  struct config_section *sec = reg_config_sec("dc", NULL, NULL);
399
 
400
  reg_config_param(sec, "enabled", paramt_int, dc_enabled);
401
  reg_config_param(sec, "nsets", paramt_int, dc_nsets);
402
  reg_config_param(sec, "nways", paramt_int, dc_nways);
403
  reg_config_param(sec, "blocksize", paramt_int, dc_blocksize);
404
  reg_config_param(sec, "ustates", paramt_int, dc_ustates);
405
  reg_config_param(sec, "load_missdelay", paramt_int, dc_load_missdelay);
406
  reg_config_param(sec, "load_hitdelay", paramt_int, dc_load_hitdelay);
407
  reg_config_param(sec, "store_missdelay", paramt_int, dc_store_missdelay);
408
  reg_config_param(sec, "store_hitdelay", paramt_int, dc_store_hitdelay);
409
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.