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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [cache/] [dcache_model.c] - Blame information for rev 1778

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

powered by: WebSVN 2.1.0

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