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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_47/] [or1ksim/] [testbench/] [mmu.c] - Blame information for rev 412

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 410 simons
/* This is MMU test for OpenRISC 1200 */
2
 
3
#include "spr_defs.h"
4
#include "support.h"
5
 
6
/* Define RAM physical location and size
7
   Bottom half will be used for this program, the rest
8
   will be used for testing */
9
#define RAM_START 0x40000000
10
#define RAM_SIZE  0x00200000
11
 
12
/* What is the last address in ram that is used by this program */
13
#define CODE_END_ADD (RAM_START + (RAM_SIZE / 2))
14
 
15
/* MMU page size */
16
#define PAGE_SIZE 4096
17
 
18
/* Number of DTLB sets used (power of 2, max is 256) */
19
#define DTLB_SETS 16
20
 
21
/* Number of DTLB ways (1, 2, 3 etc., max is 4). */
22
#define DTLB_WAYS 2
23
 
24
/* Number of ITLB sets used (power of 2, max is 256) */
25
#define ITLB_SETS 16
26
 
27
/* Number of ITLB ways (1, 2, 3 etc., max is 4). */
28
#define ITLB_WAYS 2
29
 
30
/* TLB mode codes */
31
#define TLB_CODE_ONE_TO_ONE     0x00000000
32
#define TLB_CODE_PLUS_ONE_PAGE  0x10000000
33
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
34
 
35 412 simons
#define TLB_CODE_MASK   0xfffff000
36
#define TLB_PR_MASK     0x00000fff
37
#define TLB_PR_NOLIMIT  ( SPR_DTLBTR_CI   | \
38
                          SPR_DTLBTR_URE  | \
39
                          SPR_DTLBTR_UWE  | \
40
                          SPR_DTLBTR_SRE  | \
41
                          SPR_DTLBTR_SWE  )
42 410 simons
 
43 412 simons
/* fails if x is false */
44
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
45
 
46 410 simons
/* Extern functions */
47
extern void lo_dmmu_en (void);
48
extern void lo_immu_en (void);
49
 
50
/* Global variables */
51
extern unsigned long ram_end;
52
 
53
/* DTLB mode status */
54
unsigned long dtlb_val;
55
 
56
/* ITLB mode status */
57
unsigned long itlb_val;
58
 
59 412 simons
/* DTLB miss counter */
60
int dtlb_miss_count;
61
 
62
/* ITLB miss counter */
63
int itlb_miss_count;
64
 
65
/* EA of last DTLB miss exception */
66
unsigned long dtlb_miss_ea;
67
 
68
/* EA of last ITLB miss exception */
69
unsigned long itlb_miss_ea;
70
 
71 410 simons
/*inline static
72
unsigned int dtlb_write_entry (int way, int entry, unsigned int val)
73
{
74
  mtspr (SPR_DTLBMR_BASE(way) + entry, val);
75
}
76
*/
77
 
78 412 simons
void fail (char *func, int line)
79
{
80
#ifndef __FUNCTION__
81
#define __FUNCTION__ "?"
82
#endif
83
  printf ("Test failed in %s:%i\n", func, line);
84
  report(0xeeeeeeee);
85
  exit (1);
86
}
87
 
88 410 simons
/* DTLB miss exception handler */
89
void dtlb_miss_handler (void)
90
{
91
  unsigned long ea, ta, tlbtr;
92
  int set, way = 0;
93
  int i;
94
 
95
  /* Get EA that cause the exception */
96
  ea = mfspr (SPR_EEAR_BASE);
97 412 simons
 
98 410 simons
  /* Find TLB set and LRU way */
99
  set = (ea / PAGE_SIZE) % DTLB_SETS;
100
  for (i = 0; i < DTLB_WAYS; i++) {
101
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_LRU) == 0) {
102
      way = i;
103
      break;
104
    }
105
  }
106
 
107 412 simons
printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
108 410 simons
 
109 412 simons
  if ((RAM_START <= ea) && (ea < CODE_END_ADD)) {
110 410 simons
    /* If this is acces to data of this program set one to one translation */
111
    mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
112 412 simons
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | TLB_PR_NOLIMIT);
113 410 simons
    return;
114
  }
115
 
116 412 simons
  /* Update DTLB miss counter and EA */
117
  dtlb_miss_count++;
118
  dtlb_miss_ea = ea;
119
 
120 410 simons
  /* Whatever access is in progress, translated address have to point to physical RAM */
121 412 simons
  ta = (ea & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2);
122
printf("ta = %.8lx\n", ta);
123 410 simons
 
124
  /* Set appropriate TLB entry */
125
  switch (dtlb_val & TLB_CODE_MASK) {
126
    case TLB_CODE_ONE_TO_ONE:
127 412 simons
      tlbtr = (ta & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
128
printf("1: tlbtr = %.8lx\n", tlbtr);
129 410 simons
      break;
130
    case TLB_CODE_PLUS_ONE_PAGE:
131
      if ((ta + PAGE_SIZE) >= (RAM_START + RAM_SIZE))
132
        /* Wrapp last page */
133 412 simons
        tlbtr = (((ta & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
134 410 simons
      else
135 412 simons
        tlbtr = ((ta + PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
136
printf("2: tlbtr = %.8lx\n", tlbtr);
137 410 simons
      break;
138
    case TLB_CODE_MINUS_ONE_PAGE:
139
      if ((ta - PAGE_SIZE) < (RAM_START + (RAM_SIZE/2)))
140
        /* Wrapp first page */
141 412 simons
        tlbtr = ((ta - PAGE_SIZE + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
142 410 simons
      else
143 412 simons
        tlbtr = ((ta - PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
144
printf("3: tlbtr = %.8lx\n", tlbtr);
145 410 simons
      break;
146
  }
147
 
148
  /* Set DTLB entry */
149
  mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
150
  mtspr (SPR_DTLBTR_BASE(way) + set, tlbtr);
151
}
152
 
153
 
154
/* ITLB miss exception handler */
155
void itlb_miss_handler (void)
156
{
157
 
158
 
159
}
160
 
161
/* Invalidate all entries in DTLB and enable DMMU */
162
void dmmu_enable (void)
163
{
164
  int i, j;
165
 
166
  /* Invalidate all entries in DTLB */
167
  for (i = 0; i < DTLB_WAYS; i++) {
168
    for (j = 0; j < DTLB_SETS; j++) {
169
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
170
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
171
    }
172
  }
173
 
174
  /* Register DTLB miss handler */
175
  excpt_dtlbmiss = (unsigned long)dtlb_miss_handler;
176
 
177
  /* Enable DMMU */
178
  lo_dmmu_en ();
179
}
180
 
181
/* Invalidate all entries in ITLB and enable IMMU */
182
void immu_enable (void)
183
{
184
  int i, j;
185
 
186
  /* Invalidate all entries in ITLB */
187
  for (i = 0; i < ITLB_WAYS; i++) {
188
    for (j = 0; j < ITLB_SETS; i++) {
189
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
190
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
191
    }
192
  }
193
 
194
  /* Register ITLB miss handler */
195
  excpt_itlbmiss = (unsigned long)itlb_miss_handler;
196
 
197
  /* Enable IMMU */
198
  lo_immu_en ();
199
}
200
 
201
void write_pattern(unsigned long start, unsigned long end)
202
{
203
  unsigned long add;
204
 
205
  add = start;
206
  while (add < end) {
207
    REG32(add) = add;
208
    add += PAGE_SIZE;
209
  }
210
 
211
}
212
 
213 412 simons
/* Valid bit test
214
   Set all ways of one set to be invalid, perform
215
   access so miss handler will set them to valid,
216
   try access again - there should be no miss exceptions */
217
int dtlb_valid_bit_test (int set)
218
{
219
  int i;
220
 
221
  /* Reset DTLB miss counter and EA */
222
  dtlb_miss_count = 0;
223
  dtlb_miss_ea = 0;
224
 
225
  /* Set dtlb permisions */
226
  dtlb_val = TLB_PR_NOLIMIT;
227
 
228
  /* Resetv DTLBMR for every way */
229
  for (i = 0; i < DTLB_WAYS; i++) {
230
    mtspr (SPR_DTLBMR_BASE(i) + set, 0);
231
  }
232
 
233
  /* Perform writes to address, that is not in DTLB */
234
  for (i = 0; i < DTLB_WAYS; i++) {
235
    REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) = i;
236
 
237
    /* Check if there was DTLB miss */
238
    ASSERT(dtlb_miss_count == (i + 1));
239
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
240
  }
241
 
242
  /* Reset DTLB miss counter and EA */
243
  dtlb_miss_count = 0;
244
  dtlb_miss_ea = 0;
245
 
246
  /* Perform reads to address, that is now in DTLB */
247
  for (i = 0; i < DTLB_WAYS; i++) {
248
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
249
 
250
    /* Check if there was DTLB miss */
251
    ASSERT(dtlb_miss_count == 0);
252
  }
253
 
254
  /* Reset valid bits */
255
  for (i = 0; i < DTLB_WAYS; i++) {
256
    mtspr (SPR_DTLBMR_BASE(i) + set, mfspr (SPR_DTLBMR_BASE(i) + set) & ~SPR_DTLBMR_V);
257
  }
258
 
259
  /* Perform reads to address, that is now in DTLB but is invalid */
260
  for (i = 0; i < DTLB_WAYS; i++) {
261
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
262
 
263
    /* Check if there was DTLB miss */
264
    ASSERT(dtlb_miss_count == (i + 1));
265
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
266
  }
267
 
268
  return 0;
269
}
270
 
271
 
272
 
273
 
274
 
275
 
276
 
277
 
278
 
279
 
280 410 simons
int main (void)
281
{
282 412 simons
  int i;
283 410 simons
 
284
  /* Enable DMMU */
285
  dmmu_enable();
286
 
287 412 simons
  /* Valid bit testing */
288
  for (i = 0; i < 15; i++)
289
    dtlb_valid_bit_test (DTLB_SETS - i - 1);
290
 
291 410 simons
  /* Write pattern */
292 412 simons
//  write_pattern(0x40000000, 0x40100000);
293 410 simons
 
294
  /* Enable IMMU */
295
//  immu_enable();
296
 
297
  exit(0);
298
  return 0;
299
}

powered by: WebSVN 2.1.0

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