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

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [cache/] [dcache_model.c] - Blame information for rev 1432

Go to most recent revision | 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 1432 nogj
#include "spr_defs.h"
44
#include "execute.h"
45 5 lampret
#include "stats.h"
46 102 lampret
#include "sprs.h"
47 428 markom
#include "sim-config.h"
48 5 lampret
 
49
/* Data cache */
50
 
51
struct dc_set {
52 428 markom
  struct {
53 1350 nogj
    uint32_t line[MAX_DC_BLOCK_SIZE];
54
    oraddr_t tagaddr;  /* tag address */
55 428 markom
    int lru;    /* least recently used */
56
  } way[MAX_DC_WAYS];
57
} dc[MAX_DC_SETS];
58 5 lampret
 
59
void dc_info()
60
{
61 428 markom
  if (!testsprbits(SPR_UPR, SPR_UPR_DCP)) {
62 997 markom
    PRINTF("DCache not implemented. Set UPR[DCP].\n");
63 428 markom
    return;
64
  }
65
 
66 997 markom
  PRINTF("Data cache %dKB: ", config.dc.nsets * config.dc.blocksize * config.dc.nways / 1024);
67
  PRINTF("%d ways, %d sets, block size %d bytes\n", config.dc.nways, config.dc.nsets, config.dc.blocksize);
68 5 lampret
}
69
 
70
/* First check if data is already in the cache and if it is:
71
    - increment DC read hit stats,
72 428 markom
    - set 'lru' at this way to config.dc.ustates - 1 and
73 5 lampret
      decrement 'lru' of other ways unless they have reached 0,
74
   and if not:
75
    - increment DC read miss stats
76
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
77 428 markom
    - set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
78 5 lampret
      ways unless they have reached 0
79 631 simons
    - refill cache line
80 5 lampret
*/
81
 
82 1350 nogj
uint32_t dc_simulate_read(oraddr_t dataaddr, int width)
83 5 lampret
{
84 428 markom
  int set, way = -1;
85
  int i;
86 1350 nogj
  oraddr_t tagaddr;
87
  uint32_t tmp;
88 102 lampret
 
89 638 simons
  if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
90
      (!testsprbits(SPR_SR, SPR_SR_DCE))   ||
91
      data_ci) {
92 631 simons
    if (width == 4)
93 992 simons
      tmp = evalsim_mem32(dataaddr);
94 631 simons
    else if (width == 2)
95 1350 nogj
      tmp = evalsim_mem16(dataaddr);
96 631 simons
    else if (width == 1)
97 1350 nogj
      tmp = evalsim_mem8(dataaddr);
98 992 simons
 
99
    if(!cur_area) {
100
      if (width == 4)
101 1350 nogj
        printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
102
               dataaddr);
103 992 simons
      else if (width == 2)
104 1350 nogj
        printf("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n",
105
               dataaddr);
106 992 simons
      else if (width == 1)
107 1350 nogj
        printf("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n",
108
               dataaddr);
109 992 simons
      except_handle(EXCEPT_BUSERR, cur_vadd);
110
      return 0;
111 1386 nogj
    } else if (cur_area->log)
112 1350 nogj
      fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
113
               tmp);
114 992 simons
 
115
    return tmp;
116 631 simons
  }
117 102 lampret
 
118 428 markom
  /* Which set to check out? */
119
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
120
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
121
 
122
  /* Scan all ways and try to find a matching way. */
123
  for (i = 0; i < config.dc.nways; i++)
124
    if (dc[set].way[i].tagaddr == tagaddr)
125
      way = i;
126
 
127
  /* Did we find our cached data? */
128
  if (way >= 0) { /* Yes, we did. */
129
    dc_stats.readhit++;
130 541 markom
 
131 428 markom
    for (i = 0; i < config.dc.nways; i++)
132 631 simons
      if (dc[set].way[i].lru > dc[set].way[way].lru)
133 428 markom
        dc[set].way[i].lru--;
134
    dc[set].way[way].lru = config.dc.ustates - 1;
135 884 markom
    runtime.sim.mem_cycles += config.dc.load_hitdelay;
136 631 simons
 
137
    tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
138
    if (width == 4)
139
      return tmp;
140
    else if (width == 2) {
141 1350 nogj
      tmp = ((tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff);
142 631 simons
      return tmp;
143
    }
144
    else if (width == 1) {
145 1350 nogj
      tmp = ((tmp  >> (8 * (3 - (dataaddr & 3)))) & 0xff);
146 631 simons
      return tmp;
147
    }
148 541 markom
  } else {  /* No, we didn't. */
149 428 markom
    int minlru = config.dc.ustates - 1;
150
    int minway = 0;
151 5 lampret
 
152 631 simons
    dc_stats.readmiss++;
153 5 lampret
 
154 1085 simons
    for (i = 0; i < config.dc.nways; i++) {
155
      if (dc[set].way[i].lru < minlru) {
156 428 markom
        minway = i;
157 1085 simons
        minlru = dc[set].way[i].lru;
158
      }
159
    }
160 428 markom
 
161 631 simons
    for (i = 0; i < (config.dc.blocksize); i += 4) {
162
      dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
163
        evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
164 638 simons
      if(!cur_area) {
165
        dc[set].way[minway].tagaddr = -1;
166
        dc[set].way[minway].lru = 0;
167 1350 nogj
        printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
168
               dataaddr);
169 992 simons
        except_handle(EXCEPT_BUSERR, cur_vadd);
170 631 simons
        return 0;
171 1386 nogj
      } else if (cur_area->log)
172 1350 nogj
        fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
173
                 tmp);
174 631 simons
    }
175
 
176 428 markom
    dc[set].way[minway].tagaddr = tagaddr;
177
    for (i = 0; i < config.dc.nways; i++)
178
      if (dc[set].way[i].lru)
179
        dc[set].way[i].lru--;
180
    dc[set].way[minway].lru = config.dc.ustates - 1;
181 884 markom
    runtime.sim.mem_cycles += config.dc.load_missdelay;
182 631 simons
 
183
    tmp = dc[set].way[minway].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
184
    if (width == 4)
185
      return tmp;
186
    else if (width == 2) {
187 1350 nogj
      tmp = (tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff;
188 631 simons
      return tmp;
189
    }
190
    else if (width == 1) {
191 1350 nogj
      tmp = (tmp  >> (8 * (3 - (dataaddr & 3)))) & 0xff;
192 631 simons
      return tmp;
193
    }
194 428 markom
  }
195 5 lampret
}
196
 
197
/* First check if data is already in the cache and if it is:
198
    - increment DC write hit stats,
199 428 markom
    - set 'lru' at this way to config.dc.ustates - 1 and
200 5 lampret
      decrement 'lru' of other ways unless they have reached 0,
201
   and if not:
202
    - increment DC write miss stats
203
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
204 428 markom
    - set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
205 5 lampret
      ways unless they have reached 0
206
*/
207
 
208 1350 nogj
void dc_simulate_write(oraddr_t dataaddr, uint32_t data, int width)
209 5 lampret
{
210 428 markom
  int set, way = -1;
211
  int i;
212 1350 nogj
  oraddr_t tagaddr;
213
  uint32_t tmp;
214 102 lampret
 
215 631 simons
  if (width == 4)
216
    setsim_mem32(dataaddr, data);
217
  else if (width == 2)
218 1350 nogj
    setsim_mem16(dataaddr, data);
219 631 simons
  else if (width == 1)
220 1350 nogj
    setsim_mem8(dataaddr, data);
221 631 simons
 
222 638 simons
  if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
223
      (!testsprbits(SPR_SR, SPR_SR_DCE)) ||
224
      data_ci ||
225
      (!cur_area))
226 631 simons
    return;
227 428 markom
 
228
  /* Which set to check out? */
229
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
230
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
231
 
232
  /* Scan all ways and try to find a matching way. */
233
  for (i = 0; i < config.dc.nways; i++)
234
    if (dc[set].way[i].tagaddr == tagaddr)
235
      way = i;
236
 
237
  /* Did we find our cached data? */
238
  if (way >= 0) { /* Yes, we did. */
239
    dc_stats.writehit++;
240
 
241
    for (i = 0; i < config.dc.nways; i++)
242 631 simons
      if (dc[set].way[i].lru > dc[set].way[way].lru)
243 428 markom
        dc[set].way[i].lru--;
244
    dc[set].way[way].lru = config.dc.ustates - 1;
245 884 markom
    runtime.sim.mem_cycles += config.dc.store_hitdelay;
246 631 simons
 
247
    tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
248
    if (width == 4)
249
      tmp = data;
250
    else if (width == 2) {
251
      tmp &= 0xffff << ((dataaddr & 2) ? 16 : 0);
252 1350 nogj
      tmp |= (data & 0xffff) << ((dataaddr & 2) ? 0 : 16);
253 631 simons
    }
254
    else if (width == 1) {
255
      tmp &= ~(0xff << (8 * (3 - (dataaddr & 3))));
256 1350 nogj
      tmp |= (data & 0xff) << (8 * (3 - (dataaddr & 3)));
257 631 simons
    }
258
    dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2] = tmp;
259 428 markom
  }
260
  else {  /* No, we didn't. */
261
    int minlru = config.dc.ustates - 1;
262
    int minway = 0;
263 5 lampret
 
264 631 simons
    dc_stats.writemiss++;
265 5 lampret
 
266 428 markom
    for (i = 0; i < config.dc.nways; i++)
267 631 simons
      if (dc[set].way[i].lru < minlru)
268 428 markom
        minway = i;
269
 
270 631 simons
    for (i = 0; i < (config.dc.blocksize); i += 4) {
271
      dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
272
        evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
273 638 simons
      if(!cur_area) {
274
        dc[set].way[minway].tagaddr = -1;
275
        dc[set].way[minway].lru = 0;
276 631 simons
        return;
277 638 simons
      }
278 631 simons
    }
279
 
280 428 markom
    dc[set].way[minway].tagaddr = tagaddr;
281
    for (i = 0; i < config.dc.nways; i++)
282
      if (dc[set].way[i].lru)
283
        dc[set].way[i].lru--;
284
    dc[set].way[minway].lru = config.dc.ustates - 1;
285 884 markom
    runtime.sim.mem_cycles += config.dc.store_missdelay;
286 428 markom
  }
287 5 lampret
}
288 102 lampret
 
289
/* First check if data is already in the cache and if it is:
290
    - invalidate block if way isn't locked
291
   otherwise don't do anything.
292
*/
293
 
294 1350 nogj
void dc_inv(oraddr_t dataaddr)
295 102 lampret
{
296 428 markom
  int set, way = -1;
297
  int i;
298 1350 nogj
  oraddr_t tagaddr;
299 102 lampret
 
300 428 markom
  if (!testsprbits(SPR_UPR, SPR_UPR_DCP))
301
    return;
302 102 lampret
 
303 428 markom
  /* Which set to check out? */
304
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
305
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
306
 
307 631 simons
  if (!testsprbits(SPR_SR, SPR_SR_DCE)) {
308
    for (i = 0; i < config.dc.nways; i++) {
309
      dc[set].way[i].tagaddr = -1;
310
      dc[set].way[i].lru = 0;
311
    }
312
    return;
313
  }
314
   /* Scan all ways and try to find a matching way. */
315 428 markom
  for (i = 0; i < config.dc.nways; i++)
316
    if (dc[set].way[i].tagaddr == tagaddr)
317
      way = i;
318
 
319
  /* Did we find our cached data? */
320 631 simons
  if (way >= 0) { /* Yes, we did. */
321 428 markom
    dc[set].way[way].tagaddr = -1;
322 631 simons
    dc[set].way[way].lru = 0;
323 428 markom
  }
324 102 lampret
}
325
 
326 1358 nogj
/*-----------------------------------------------------[ DC configuration ]---*/
327
void dc_enabled(union param_val val, void *dat)
328
{
329
  config.dc.enabled = val.int_val;
330
  setsprbits (SPR_UPR, SPR_UPR_DCP, val.int_val ? 1 : 0);
331
}
332
 
333
void dc_nsets(union param_val val, void *dat)
334
{
335 1382 nogj
  if (is_power2(val.int_val) && val.int_val <= MAX_DC_SETS){
336 1358 nogj
    config.dc.nsets = val.int_val;
337 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_NCS, log2(val.int_val));
338
  }
339 1358 nogj
  else {
340
    char tmp[200];
341
    sprintf (tmp, "value of power of two and lower or equal than %i expected.", MAX_DC_SETS);
342
    CONFIG_ERROR(tmp);
343
  }
344
}
345
 
346
void dc_nways(union param_val val, void *dat)
347
{
348 1382 nogj
  if (is_power2(val.int_val) && val.int_val <= MAX_DC_WAYS){
349 1358 nogj
    config.dc.nways = val.int_val;
350 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_NCW, log2(val.int_val));
351
  }
352
  else{
353
    char tmp[200];
354
    sprintf (tmp, "value of power of two and lower or equal than %i expected.",
355
    MAX_DC_WAYS);
356
    CONFIG_ERROR(tmp);
357
  }
358 1358 nogj
}
359
 
360
void dc_blocksize(union param_val val, void *dat)
361
{
362 1382 nogj
  if (is_power2(val.int_val)) {
363 1358 nogj
    config.dc.blocksize = val.int_val;
364 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_CBS,log2(val.int_val));
365
  } else
366 1358 nogj
    CONFIG_ERROR("value of power of two expected.");
367
}
368
 
369
void dc_ustates(union param_val val, void *dat)
370
{
371
  if (val.int_val >= 2 && val.int_val <= 4)
372
    config.dc.ustates = val.int_val;
373
  else
374
    CONFIG_ERROR("invalid USTATE.");
375
}
376
 
377
void dc_load_missdelay(union param_val val, void *dat)
378
{
379
  config.dc.load_missdelay = val.int_val;
380
}
381
 
382
void dc_load_hitdelay(union param_val val, void *dat)
383
{
384
  config.dc.load_hitdelay = val.int_val;
385
}
386
 
387
void dc_store_missdelay(union param_val val, void *dat)
388
{
389
  config.dc.store_missdelay = val.int_val;
390
}
391
 
392
void dc_store_hitdelay(union param_val val, void *dat)
393
{
394
  config.dc.store_hitdelay = val.int_val;
395
}
396
 
397
void reg_dc_sec(void)
398
{
399
  struct config_section *sec = reg_config_sec("dc", NULL, NULL);
400
 
401
  reg_config_param(sec, "enabled", paramt_int, dc_enabled);
402
  reg_config_param(sec, "nsets", paramt_int, dc_nsets);
403
  reg_config_param(sec, "nways", paramt_int, dc_nways);
404
  reg_config_param(sec, "blocksize", paramt_int, dc_blocksize);
405
  reg_config_param(sec, "ustates", paramt_int, dc_ustates);
406
  reg_config_param(sec, "load_missdelay", paramt_int, dc_load_missdelay);
407
  reg_config_param(sec, "load_hitdelay", paramt_int, dc_load_hitdelay);
408
  reg_config_param(sec, "store_missdelay", paramt_int, dc_store_missdelay);
409
  reg_config_param(sec, "store_hitdelay", paramt_int, dc_store_hitdelay);
410
}

powered by: WebSVN 2.1.0

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