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 1382

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 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
    }
111
 
112
    if (!pending.valid && cur_area->log)
113 1350 nogj
      fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
114
               tmp);
115 992 simons
 
116
    return tmp;
117 631 simons
  }
118 102 lampret
 
119 428 markom
  /* Which set to check out? */
120
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
121
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
122
 
123
  /* Scan all ways and try to find a matching way. */
124
  for (i = 0; i < config.dc.nways; i++)
125
    if (dc[set].way[i].tagaddr == tagaddr)
126
      way = i;
127
 
128
  /* Did we find our cached data? */
129
  if (way >= 0) { /* Yes, we did. */
130
    dc_stats.readhit++;
131 541 markom
 
132 428 markom
    for (i = 0; i < config.dc.nways; i++)
133 631 simons
      if (dc[set].way[i].lru > dc[set].way[way].lru)
134 428 markom
        dc[set].way[i].lru--;
135
    dc[set].way[way].lru = config.dc.ustates - 1;
136 884 markom
    runtime.sim.mem_cycles += config.dc.load_hitdelay;
137 631 simons
 
138
    tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
139
    if (width == 4)
140
      return tmp;
141
    else if (width == 2) {
142 1350 nogj
      tmp = ((tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff);
143 631 simons
      return tmp;
144
    }
145
    else if (width == 1) {
146 1350 nogj
      tmp = ((tmp  >> (8 * (3 - (dataaddr & 3)))) & 0xff);
147 631 simons
      return tmp;
148
    }
149 541 markom
  } else {  /* No, we didn't. */
150 428 markom
    int minlru = config.dc.ustates - 1;
151
    int minway = 0;
152 5 lampret
 
153 631 simons
    dc_stats.readmiss++;
154 5 lampret
 
155 1085 simons
    for (i = 0; i < config.dc.nways; i++) {
156
      if (dc[set].way[i].lru < minlru) {
157 428 markom
        minway = i;
158 1085 simons
        minlru = dc[set].way[i].lru;
159
      }
160
    }
161 428 markom
 
162 631 simons
    for (i = 0; i < (config.dc.blocksize); i += 4) {
163
      dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
164
        evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
165 638 simons
      if(!cur_area) {
166
        dc[set].way[minway].tagaddr = -1;
167
        dc[set].way[minway].lru = 0;
168 1350 nogj
        printf("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
169
               dataaddr);
170 992 simons
        except_handle(EXCEPT_BUSERR, cur_vadd);
171 631 simons
        return 0;
172 638 simons
      }
173 992 simons
      if (!pending.valid && cur_area->log)
174 1350 nogj
        fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", dataaddr,
175
                 tmp);
176 631 simons
    }
177
 
178 428 markom
    dc[set].way[minway].tagaddr = tagaddr;
179
    for (i = 0; i < config.dc.nways; i++)
180
      if (dc[set].way[i].lru)
181
        dc[set].way[i].lru--;
182
    dc[set].way[minway].lru = config.dc.ustates - 1;
183 884 markom
    runtime.sim.mem_cycles += config.dc.load_missdelay;
184 631 simons
 
185
    tmp = dc[set].way[minway].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
186
    if (width == 4)
187
      return tmp;
188
    else if (width == 2) {
189 1350 nogj
      tmp = (tmp >> ((dataaddr & 2) ? 0 : 16)) & 0xffff;
190 631 simons
      return tmp;
191
    }
192
    else if (width == 1) {
193 1350 nogj
      tmp = (tmp  >> (8 * (3 - (dataaddr & 3)))) & 0xff;
194 631 simons
      return tmp;
195
    }
196 428 markom
  }
197 5 lampret
}
198
 
199
/* First check if data is already in the cache and if it is:
200
    - increment DC write hit stats,
201 428 markom
    - set 'lru' at this way to config.dc.ustates - 1 and
202 5 lampret
      decrement 'lru' of other ways unless they have reached 0,
203
   and if not:
204
    - increment DC write miss stats
205
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
206 428 markom
    - set 'lru' with config.dc.ustates - 1 and decrement 'lru' of other
207 5 lampret
      ways unless they have reached 0
208
*/
209
 
210 1350 nogj
void dc_simulate_write(oraddr_t dataaddr, uint32_t data, int width)
211 5 lampret
{
212 428 markom
  int set, way = -1;
213
  int i;
214 1350 nogj
  oraddr_t tagaddr;
215
  uint32_t tmp;
216 102 lampret
 
217 631 simons
  if (width == 4)
218
    setsim_mem32(dataaddr, data);
219
  else if (width == 2)
220 1350 nogj
    setsim_mem16(dataaddr, data);
221 631 simons
  else if (width == 1)
222 1350 nogj
    setsim_mem8(dataaddr, data);
223 631 simons
 
224 638 simons
  if ((!testsprbits(SPR_UPR, SPR_UPR_DCP)) ||
225
      (!testsprbits(SPR_SR, SPR_SR_DCE)) ||
226
      data_ci ||
227
      (!cur_area))
228 631 simons
    return;
229 428 markom
 
230
  /* Which set to check out? */
231
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
232
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
233
 
234
  /* Scan all ways and try to find a matching way. */
235
  for (i = 0; i < config.dc.nways; i++)
236
    if (dc[set].way[i].tagaddr == tagaddr)
237
      way = i;
238
 
239
  /* Did we find our cached data? */
240
  if (way >= 0) { /* Yes, we did. */
241
    dc_stats.writehit++;
242
 
243
    for (i = 0; i < config.dc.nways; i++)
244 631 simons
      if (dc[set].way[i].lru > dc[set].way[way].lru)
245 428 markom
        dc[set].way[i].lru--;
246
    dc[set].way[way].lru = config.dc.ustates - 1;
247 884 markom
    runtime.sim.mem_cycles += config.dc.store_hitdelay;
248 631 simons
 
249
    tmp = dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2];
250
    if (width == 4)
251
      tmp = data;
252
    else if (width == 2) {
253
      tmp &= 0xffff << ((dataaddr & 2) ? 16 : 0);
254 1350 nogj
      tmp |= (data & 0xffff) << ((dataaddr & 2) ? 0 : 16);
255 631 simons
    }
256
    else if (width == 1) {
257
      tmp &= ~(0xff << (8 * (3 - (dataaddr & 3))));
258 1350 nogj
      tmp |= (data & 0xff) << (8 * (3 - (dataaddr & 3)));
259 631 simons
    }
260
    dc[set].way[way].line[(dataaddr & (config.dc.blocksize - 1)) >> 2] = tmp;
261 428 markom
  }
262
  else {  /* No, we didn't. */
263
    int minlru = config.dc.ustates - 1;
264
    int minway = 0;
265 5 lampret
 
266 631 simons
    dc_stats.writemiss++;
267 5 lampret
 
268 428 markom
    for (i = 0; i < config.dc.nways; i++)
269 631 simons
      if (dc[set].way[i].lru < minlru)
270 428 markom
        minway = i;
271
 
272 631 simons
    for (i = 0; i < (config.dc.blocksize); i += 4) {
273
      dc[set].way[minway].line[((dataaddr + i) & (config.dc.blocksize - 1)) >> 2] =
274
        evalsim_mem32((dataaddr & ~(config.dc.blocksize - 1)) + (((dataaddr & ~3ul)+ i) & (config.dc.blocksize - 1)));
275 638 simons
      if(!cur_area) {
276
        dc[set].way[minway].tagaddr = -1;
277
        dc[set].way[minway].lru = 0;
278 631 simons
        return;
279 638 simons
      }
280 631 simons
    }
281
 
282 428 markom
    dc[set].way[minway].tagaddr = tagaddr;
283
    for (i = 0; i < config.dc.nways; i++)
284
      if (dc[set].way[i].lru)
285
        dc[set].way[i].lru--;
286
    dc[set].way[minway].lru = config.dc.ustates - 1;
287 884 markom
    runtime.sim.mem_cycles += config.dc.store_missdelay;
288 428 markom
  }
289 5 lampret
}
290 102 lampret
 
291
/* First check if data is already in the cache and if it is:
292
    - invalidate block if way isn't locked
293
   otherwise don't do anything.
294
*/
295
 
296 1350 nogj
void dc_inv(oraddr_t dataaddr)
297 102 lampret
{
298 428 markom
  int set, way = -1;
299
  int i;
300 1350 nogj
  oraddr_t tagaddr;
301 102 lampret
 
302 428 markom
  if (!testsprbits(SPR_UPR, SPR_UPR_DCP))
303
    return;
304 102 lampret
 
305 428 markom
  /* Which set to check out? */
306
  set = (dataaddr / config.dc.blocksize) % config.dc.nsets;
307
  tagaddr = (dataaddr / config.dc.blocksize) / config.dc.nsets;
308
 
309 631 simons
  if (!testsprbits(SPR_SR, SPR_SR_DCE)) {
310
    for (i = 0; i < config.dc.nways; i++) {
311
      dc[set].way[i].tagaddr = -1;
312
      dc[set].way[i].lru = 0;
313
    }
314
    return;
315
  }
316
   /* Scan all ways and try to find a matching way. */
317 428 markom
  for (i = 0; i < config.dc.nways; i++)
318
    if (dc[set].way[i].tagaddr == tagaddr)
319
      way = i;
320
 
321
  /* Did we find our cached data? */
322 631 simons
  if (way >= 0) { /* Yes, we did. */
323 428 markom
    dc[set].way[way].tagaddr = -1;
324 631 simons
    dc[set].way[way].lru = 0;
325 428 markom
  }
326 102 lampret
}
327
 
328 1350 nogj
void dc_clock()
329 102 lampret
{
330 1350 nogj
  oraddr_t addr;
331 428 markom
 
332 1308 phoenix
  if ((addr = mfspr(SPR_DCBPR))) {
333 631 simons
    dc_simulate_read(addr, 4);
334 428 markom
    mtspr(SPR_DCBPR, 0);
335
  }
336 631 simons
  if ((addr = mfspr(SPR_DCBFR)) != -1) {
337 428 markom
    dc_inv(addr);
338 631 simons
    mtspr(SPR_DCBFR, -1);
339 428 markom
  }
340 1308 phoenix
  if ((addr = mfspr(SPR_DCBIR))) {
341 428 markom
    dc_inv(addr);
342
    mtspr(SPR_DCBIR, 0);
343
  }
344 1308 phoenix
  if ((addr = mfspr(SPR_DCBWR))) {
345 428 markom
    mtspr(SPR_DCBWR, 0);
346
  }
347 1308 phoenix
  if ((addr = mfspr(SPR_DCBLR))) {
348 428 markom
    mtspr(SPR_DCBLR, 0);
349
  }
350 102 lampret
}
351 1358 nogj
 
352
/*-----------------------------------------------------[ DC configuration ]---*/
353
void dc_enabled(union param_val val, void *dat)
354
{
355
  config.dc.enabled = val.int_val;
356
  setsprbits (SPR_UPR, SPR_UPR_DCP, val.int_val ? 1 : 0);
357
}
358
 
359
void dc_nsets(union param_val val, void *dat)
360
{
361 1382 nogj
  if (is_power2(val.int_val) && val.int_val <= MAX_DC_SETS){
362 1358 nogj
    config.dc.nsets = val.int_val;
363 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_NCS, log2(val.int_val));
364
  }
365 1358 nogj
  else {
366
    char tmp[200];
367
    sprintf (tmp, "value of power of two and lower or equal than %i expected.", MAX_DC_SETS);
368
    CONFIG_ERROR(tmp);
369
  }
370
}
371
 
372
void dc_nways(union param_val val, void *dat)
373
{
374 1382 nogj
  if (is_power2(val.int_val) && val.int_val <= MAX_DC_WAYS){
375 1358 nogj
    config.dc.nways = val.int_val;
376 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_NCW, log2(val.int_val));
377
  }
378
  else{
379
    char tmp[200];
380
    sprintf (tmp, "value of power of two and lower or equal than %i expected.",
381
    MAX_DC_WAYS);
382
    CONFIG_ERROR(tmp);
383
  }
384 1358 nogj
}
385
 
386
void dc_blocksize(union param_val val, void *dat)
387
{
388 1382 nogj
  if (is_power2(val.int_val)) {
389 1358 nogj
    config.dc.blocksize = val.int_val;
390 1382 nogj
    setsprbits (SPR_DCCFGR, SPR_DCCFGR_CBS,log2(val.int_val));
391
  } else
392 1358 nogj
    CONFIG_ERROR("value of power of two expected.");
393
}
394
 
395
void dc_ustates(union param_val val, void *dat)
396
{
397
  if (val.int_val >= 2 && val.int_val <= 4)
398
    config.dc.ustates = val.int_val;
399
  else
400
    CONFIG_ERROR("invalid USTATE.");
401
}
402
 
403
void dc_load_missdelay(union param_val val, void *dat)
404
{
405
  config.dc.load_missdelay = val.int_val;
406
}
407
 
408
void dc_load_hitdelay(union param_val val, void *dat)
409
{
410
  config.dc.load_hitdelay = val.int_val;
411
}
412
 
413
void dc_store_missdelay(union param_val val, void *dat)
414
{
415
  config.dc.store_missdelay = val.int_val;
416
}
417
 
418
void dc_store_hitdelay(union param_val val, void *dat)
419
{
420
  config.dc.store_hitdelay = val.int_val;
421
}
422
 
423
void reg_dc_sec(void)
424
{
425
  struct config_section *sec = reg_config_sec("dc", NULL, NULL);
426
 
427
  reg_config_param(sec, "enabled", paramt_int, dc_enabled);
428
  reg_config_param(sec, "nsets", paramt_int, dc_nsets);
429
  reg_config_param(sec, "nways", paramt_int, dc_nways);
430
  reg_config_param(sec, "blocksize", paramt_int, dc_blocksize);
431
  reg_config_param(sec, "ustates", paramt_int, dc_ustates);
432
  reg_config_param(sec, "load_missdelay", paramt_int, dc_load_missdelay);
433
  reg_config_param(sec, "load_hitdelay", paramt_int, dc_load_hitdelay);
434
  reg_config_param(sec, "store_missdelay", paramt_int, dc_store_missdelay);
435
  reg_config_param(sec, "store_hitdelay", paramt_int, dc_store_hitdelay);
436
}

powered by: WebSVN 2.1.0

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