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 102

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
#include "dcache_model.h"
32
#include "abstract.h"
33
#include "stats.h"
34 102 lampret
#include "spr_defs.h"
35
#include "sprs.h"
36 5 lampret
 
37
/* Data cache */
38
 
39
/* Number of DC sets (power of 2) */
40 54 lampret
#define DC_SETS 512
41 5 lampret
 
42
/* Block size in bytes (1, 2, 4, 8, 16, 32 etc.) */
43 26 lampret
#define DC_BLOCK_SIZE 16
44 5 lampret
 
45
/* Number of DC ways (1, 2, 3 etc.). */
46
#define DC_WAYS 1
47
 
48
/* Number of usage states (2, 3, 4 etc.). */
49
#define DC_USTATES 2
50
 
51
struct dc_set {
52
        struct {
53
                unsigned long tagaddr;  /* tag address */
54
                int lru;                /* least recently used */
55
        } way[DC_WAYS];
56
} dc[DC_SETS];
57
 
58
void dc_info()
59
{
60 102 lampret
        if (!getsprbits(SPR_UPR, SPR_UPR_DCP)) {
61
                printf("DCache not implemented. Set UPR[DCP].\n");
62
                return;
63
        }
64
 
65 5 lampret
        printf("Data cache %dKB: ", DC_SETS * DC_BLOCK_SIZE * DC_WAYS / 1024);
66
        printf("%d ways, %d sets, block size %d bytes\n", DC_WAYS, DC_SETS, DC_BLOCK_SIZE);
67
}
68
 
69
/* First check if data is already in the cache and if it is:
70
    - increment DC read hit stats,
71
    - set 'lru' at this way to DC_USTATES - 1 and
72
      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
    - set 'lru' with DC_USTATES - 1 and decrement 'lru' of other
77
      ways unless they have reached 0
78
*/
79
 
80
void dc_simulate_read(unsigned long dataaddr)
81
{
82
        int set, way = -1;
83
        int i;
84
        unsigned long tagaddr;
85 102 lampret
 
86
        if ((!getsprbits(SPR_UPR, SPR_UPR_DCP)) || (!getsprbits(SPR_SR, SPR_SR_DCE)))
87
                return;
88
 
89 5 lampret
        /* Which set to check out? */
90
        set = (dataaddr / DC_BLOCK_SIZE) % DC_SETS;
91
        tagaddr = (dataaddr / DC_BLOCK_SIZE) / DC_SETS;
92
 
93
        /* Scan all ways and try to find a matching way. */
94
        for (i = 0; i < DC_WAYS; i++)
95
                if (dc[set].way[i].tagaddr == tagaddr)
96
                        way = i;
97
 
98
        /* Did we find our cached data? */
99
        if (way >= 0) { /* Yes, we did. */
100
                dc_stats.readhit++;
101
 
102
                for (i = 0; i < DC_WAYS; i++)
103
                        if (dc[set].way[i].lru)
104
                                dc[set].way[i].lru--;
105
                dc[set].way[way].lru = DC_USTATES - 1;
106
        }
107
        else {  /* No, we didn't. */
108
                int minlru = DC_USTATES - 1;
109
                int minway = 0;
110
 
111
                dc_stats.readmiss++;
112
 
113
                for (i = 0; i < DC_WAYS; i++)
114 102 lampret
                        if ((dc[set].way[i].lru < minlru) &&
115
                            (getsprbits(SPR_DCCR, SPR_DCCR_EW) & (1 << i)))
116 5 lampret
                                minway = i;
117
 
118
                dc[set].way[minway].tagaddr = tagaddr;
119
                for (i = 0; i < DC_WAYS; i++)
120
                        if (dc[set].way[i].lru)
121
                                dc[set].way[i].lru--;
122
                dc[set].way[minway].lru = DC_USTATES - 1;
123
        }
124
}
125
 
126
/* First check if data is already in the cache and if it is:
127
    - increment DC write hit stats,
128
    - set 'lru' at this way to DC_USTATES - 1 and
129
      decrement 'lru' of other ways unless they have reached 0,
130
   and if not:
131
    - increment DC write miss stats
132
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
133
    - set 'lru' with DC_USTATES - 1 and decrement 'lru' of other
134
      ways unless they have reached 0
135
*/
136
 
137
void dc_simulate_write(unsigned long dataaddr)
138
{
139
        int set, way = -1;
140
        int i;
141
        unsigned long tagaddr;
142 102 lampret
 
143
        if ((!getsprbits(SPR_UPR, SPR_UPR_DCP)) || (!getsprbits(SPR_SR, SPR_SR_DCE)))
144
                return;
145 5 lampret
 
146
        /* Which set to check out? */
147
        set = (dataaddr / DC_BLOCK_SIZE) % DC_SETS;
148
        tagaddr = (dataaddr / DC_BLOCK_SIZE) / DC_SETS;
149
 
150
        /* Scan all ways and try to find a matching way. */
151
        for (i = 0; i < DC_WAYS; i++)
152
                if (dc[set].way[i].tagaddr == tagaddr)
153
                        way = i;
154
 
155
        /* Did we find our cached data? */
156
        if (way >= 0) { /* Yes, we did. */
157
                dc_stats.writehit++;
158
 
159
                for (i = 0; i < DC_WAYS; i++)
160
                        if (dc[set].way[i].lru)
161
                                dc[set].way[i].lru--;
162
                dc[set].way[way].lru = DC_USTATES - 1;
163
        }
164
        else {  /* No, we didn't. */
165
                int minlru = DC_USTATES - 1;
166
                int minway = 0;
167
 
168
                dc_stats.writemiss++;
169
 
170
                for (i = 0; i < DC_WAYS; i++)
171 102 lampret
                        if ((dc[set].way[i].lru < minlru) &&
172
                            (getsprbits(SPR_DCCR, SPR_DCCR_EW) & (1 << i)))
173 5 lampret
                                minway = i;
174
 
175
                dc[set].way[minway].tagaddr = tagaddr;
176
                for (i = 0; i < DC_WAYS; i++)
177
                        if (dc[set].way[i].lru)
178
                                dc[set].way[i].lru--;
179
                dc[set].way[minway].lru = DC_USTATES - 1;
180
        }
181
}
182 102 lampret
 
183
/* First check if data is already in the cache and if it is:
184
    - invalidate block if way isn't locked
185
   otherwise don't do anything.
186
*/
187
 
188
void dc_inv(unsigned long dataaddr)
189
{
190
        int set, way = -1;
191
        int i;
192
        unsigned long tagaddr;
193
 
194
        if (!getsprbits(SPR_UPR, SPR_UPR_DCP))
195
                return;
196
 
197
        /* Which set to check out? */
198
        set = (dataaddr / DC_BLOCK_SIZE) % DC_SETS;
199
        tagaddr = (dataaddr / DC_BLOCK_SIZE) / DC_SETS;
200
 
201
        /* Scan all ways and try to find a matching way. */
202
        for (i = 0; i < DC_WAYS; i++)
203
                if (dc[set].way[i].tagaddr == tagaddr)
204
                        way = i;
205
 
206
        /* Did we find our cached data? */
207
        if ((way >= 0) && (getsprbits(SPR_DCCR, SPR_DCCR_EW) & (1 << way))) { /* Yes, we did. */
208
                dc[set].way[way].tagaddr = -1;
209
        }
210
}
211
 
212
void dc_clock()
213
{
214
        unsigned long addr;
215
 
216
        if (addr = mfspr(SPR_DCBPR)) {
217
                dc_simulate_read(addr);
218
                mtspr(SPR_DCBPR, 0);
219
        }
220
        if (addr = mfspr(SPR_DCBFR)) {
221
                dc_inv(addr);
222
                mtspr(SPR_DCBFR, 0);
223
        }
224
        if (addr = mfspr(SPR_DCBIR)) {
225
                dc_inv(addr);
226
                mtspr(SPR_DCBIR, 0);
227
        }
228
        if (addr = mfspr(SPR_DCBWR)) {
229
                mtspr(SPR_DCBWR, 0);
230
        }
231
        if (addr = mfspr(SPR_DCBLR)) {
232
                mtspr(SPR_DCBLR, 0);
233
        }
234
}

powered by: WebSVN 2.1.0

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