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

Subversion Repositories or1k_old

[/] [or1k_old/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [cache/] [dcache_model.c] - Blame information for rev 1506

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

powered by: WebSVN 2.1.0

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