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 413

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 413 markom
#define FLASH_START 0x00000000
10
#define FLASH_SIZE  0x00200000
11
#define RAM_START   0x40000000
12
#define RAM_SIZE    0x00200000
13 410 simons
 
14
/* What is the last address in ram that is used by this program */
15 413 markom
#define TEXT_END_ADD (FLASH_START + (FLASH_SIZE / 2))
16
#define DATA_END_ADD (RAM_START + (RAM_SIZE / 2))
17 410 simons
 
18
/* MMU page size */
19
#define PAGE_SIZE 4096
20
 
21
/* Number of DTLB sets used (power of 2, max is 256) */
22
#define DTLB_SETS 16
23
 
24
/* Number of DTLB ways (1, 2, 3 etc., max is 4). */
25
#define DTLB_WAYS 2
26
 
27
/* Number of ITLB sets used (power of 2, max is 256) */
28
#define ITLB_SETS 16
29
 
30
/* Number of ITLB ways (1, 2, 3 etc., max is 4). */
31
#define ITLB_WAYS 2
32
 
33
/* TLB mode codes */
34
#define TLB_CODE_ONE_TO_ONE     0x00000000
35
#define TLB_CODE_PLUS_ONE_PAGE  0x10000000
36
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
37
 
38 412 simons
#define TLB_CODE_MASK   0xfffff000
39
#define TLB_PR_MASK     0x00000fff
40
#define TLB_PR_NOLIMIT  ( SPR_DTLBTR_CI   | \
41
                          SPR_DTLBTR_URE  | \
42
                          SPR_DTLBTR_UWE  | \
43
                          SPR_DTLBTR_SRE  | \
44
                          SPR_DTLBTR_SWE  )
45 410 simons
 
46 412 simons
/* fails if x is false */
47
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
48
 
49 413 markom
#define TEST_JUMP(x) 
50
 
51 410 simons
/* Extern functions */
52
extern void lo_dmmu_en (void);
53
extern void lo_immu_en (void);
54
 
55
/* Global variables */
56
extern unsigned long ram_end;
57
 
58
/* DTLB mode status */
59
unsigned long dtlb_val;
60
 
61
/* ITLB mode status */
62
unsigned long itlb_val;
63
 
64 412 simons
/* DTLB miss counter */
65
int dtlb_miss_count;
66
 
67
/* ITLB miss counter */
68
int itlb_miss_count;
69
 
70
/* EA of last DTLB miss exception */
71
unsigned long dtlb_miss_ea;
72
 
73
/* EA of last ITLB miss exception */
74
unsigned long itlb_miss_ea;
75
 
76 410 simons
/*inline static
77
unsigned int dtlb_write_entry (int way, int entry, unsigned int val)
78
{
79
  mtspr (SPR_DTLBMR_BASE(way) + entry, val);
80
}
81
*/
82
 
83 412 simons
void fail (char *func, int line)
84
{
85
#ifndef __FUNCTION__
86
#define __FUNCTION__ "?"
87
#endif
88
  printf ("Test failed in %s:%i\n", func, line);
89
  report(0xeeeeeeee);
90
  exit (1);
91
}
92
 
93 410 simons
/* DTLB miss exception handler */
94
void dtlb_miss_handler (void)
95
{
96
  unsigned long ea, ta, tlbtr;
97
  int set, way = 0;
98
  int i;
99
 
100
  /* Get EA that cause the exception */
101
  ea = mfspr (SPR_EEAR_BASE);
102 412 simons
 
103 410 simons
  /* Find TLB set and LRU way */
104
  set = (ea / PAGE_SIZE) % DTLB_SETS;
105
  for (i = 0; i < DTLB_WAYS; i++) {
106
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_LRU) == 0) {
107
      way = i;
108
      break;
109
    }
110
  }
111
 
112 412 simons
printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
113 410 simons
 
114 413 markom
  if ((RAM_START <= ea) && (ea < DATA_END_ADD)) {
115 410 simons
    /* If this is acces to data of this program set one to one translation */
116
    mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
117 412 simons
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | TLB_PR_NOLIMIT);
118 410 simons
    return;
119
  }
120
 
121 412 simons
  /* Update DTLB miss counter and EA */
122
  dtlb_miss_count++;
123
  dtlb_miss_ea = ea;
124
 
125 410 simons
  /* Whatever access is in progress, translated address have to point to physical RAM */
126 413 markom
  ta = (ea & ((RAM_SIZE/2) - 1)) + DATA_END_ADD;
127 412 simons
printf("ta = %.8lx\n", ta);
128 410 simons
 
129
  /* Set appropriate TLB entry */
130
  switch (dtlb_val & TLB_CODE_MASK) {
131
    case TLB_CODE_ONE_TO_ONE:
132 412 simons
      tlbtr = (ta & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
133
printf("1: tlbtr = %.8lx\n", tlbtr);
134 410 simons
      break;
135
    case TLB_CODE_PLUS_ONE_PAGE:
136
      if ((ta + PAGE_SIZE) >= (RAM_START + RAM_SIZE))
137
        /* Wrapp last page */
138 412 simons
        tlbtr = (((ta & ((RAM_SIZE/2) - 1)) + RAM_START + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
139 410 simons
      else
140 412 simons
        tlbtr = ((ta + PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
141
printf("2: tlbtr = %.8lx\n", tlbtr);
142 410 simons
      break;
143
    case TLB_CODE_MINUS_ONE_PAGE:
144
      if ((ta - PAGE_SIZE) < (RAM_START + (RAM_SIZE/2)))
145
        /* Wrapp first page */
146 412 simons
        tlbtr = ((ta - PAGE_SIZE + (RAM_SIZE/2)) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
147 410 simons
      else
148 412 simons
        tlbtr = ((ta - PAGE_SIZE) & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
149
printf("3: tlbtr = %.8lx\n", tlbtr);
150 410 simons
      break;
151
  }
152
 
153
  /* Set DTLB entry */
154
  mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
155
  mtspr (SPR_DTLBTR_BASE(way) + set, tlbtr);
156
}
157
 
158
 
159
/* ITLB miss exception handler */
160
void itlb_miss_handler (void)
161
{
162 413 markom
  unsigned long ea, ta, tlbtr;
163
  int set, way = 0;
164
  int i;
165 410 simons
 
166 413 markom
  /* Get EA that cause the exception */
167
  ea = mfspr (SPR_EEAR_BASE);
168 410 simons
 
169 413 markom
  /* Find TLB set and LRU way */
170
  set = (ea / PAGE_SIZE) % ITLB_SETS;
171
  for (i = 0; i < ITLB_WAYS; i++) {
172
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_LRU) == 0) {
173
      way = i;
174
      break;
175
    }
176
  }
177
 
178
printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
179
 
180
  if ((FLASH_START <= ea) && (ea < TEXT_END_ADD)) {
181
    /* If this is acces to data of this program set one to one translation */
182
    mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
183
    mtspr (SPR_ITLBTR_BASE(way) + set, (ea & SPR_ITLBTR_PPN) | TLB_PR_NOLIMIT);
184
    return;
185
  }
186
 
187
  /* Update ITLB miss counter and EA */
188
  itlb_miss_count++;
189
  itlb_miss_ea = ea;
190
 
191
  /* Whatever access is in progress, translated address have to point to physical RAM */
192
  ta = (ea & ((FLASH_SIZE/2) - 1)) + TEXT_END_ADD;
193
printf("ta = %.8lx\n", ta);
194
 
195
  /* Set appropriate TLB entry */
196
  switch (itlb_val & TLB_CODE_MASK) {
197
    case TLB_CODE_ONE_TO_ONE:
198
      tlbtr = (ta & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
199
printf("1: tlbtr = %.8lx\n", tlbtr);
200
      break;
201
    case TLB_CODE_PLUS_ONE_PAGE:
202
      if ((ta + PAGE_SIZE) >= (FLASH_START + FLASH_SIZE))
203
        /* Wrapp last page */
204
        tlbtr = (((ta & ((FLASH_SIZE/2) - 1)) + TEXT_END_ADD) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
205
      else
206
        tlbtr = ((ta + PAGE_SIZE) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
207
printf("2: tlbtr = %.8lx\n", tlbtr);
208
      break;
209
    case TLB_CODE_MINUS_ONE_PAGE:
210
      if ((ta - PAGE_SIZE) < TEXT_END_ADD)
211
        /* Wrapp first page */
212
        tlbtr = ((ta - PAGE_SIZE + (FLASH_SIZE/2)) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
213
      else
214
        tlbtr = ((ta - PAGE_SIZE) & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
215
printf("3: tlbtr = %.8lx\n", tlbtr);
216
      break;
217
  }
218
 
219
  /* Set ITLB entry */
220
  mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
221
  mtspr (SPR_ITLBTR_BASE(way) + set, tlbtr);
222 410 simons
}
223
 
224
/* Invalidate all entries in DTLB and enable DMMU */
225
void dmmu_enable (void)
226
{
227
  int i, j;
228
 
229
  /* Invalidate all entries in DTLB */
230
  for (i = 0; i < DTLB_WAYS; i++) {
231
    for (j = 0; j < DTLB_SETS; j++) {
232
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
233
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
234
    }
235
  }
236
 
237
  /* Register DTLB miss handler */
238
  excpt_dtlbmiss = (unsigned long)dtlb_miss_handler;
239
 
240
  /* Enable DMMU */
241
  lo_dmmu_en ();
242
}
243
 
244
/* Invalidate all entries in ITLB and enable IMMU */
245
void immu_enable (void)
246
{
247
  int i, j;
248
 
249
  /* Invalidate all entries in ITLB */
250
  for (i = 0; i < ITLB_WAYS; i++) {
251
    for (j = 0; j < ITLB_SETS; i++) {
252
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
253
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
254
    }
255
  }
256
 
257
  /* Register ITLB miss handler */
258
  excpt_itlbmiss = (unsigned long)itlb_miss_handler;
259
 
260
  /* Enable IMMU */
261
  lo_immu_en ();
262
}
263
 
264
void write_pattern(unsigned long start, unsigned long end)
265
{
266
  unsigned long add;
267
 
268
  add = start;
269
  while (add < end) {
270
    REG32(add) = add;
271
    add += PAGE_SIZE;
272
  }
273
 
274
}
275
 
276 412 simons
/* Valid bit test
277
   Set all ways of one set to be invalid, perform
278
   access so miss handler will set them to valid,
279
   try access again - there should be no miss exceptions */
280
int dtlb_valid_bit_test (int set)
281
{
282
  int i;
283
 
284
  /* Reset DTLB miss counter and EA */
285
  dtlb_miss_count = 0;
286
  dtlb_miss_ea = 0;
287
 
288
  /* Set dtlb permisions */
289
  dtlb_val = TLB_PR_NOLIMIT;
290
 
291
  /* Resetv DTLBMR for every way */
292
  for (i = 0; i < DTLB_WAYS; i++) {
293
    mtspr (SPR_DTLBMR_BASE(i) + set, 0);
294
  }
295
 
296
  /* Perform writes to address, that is not in DTLB */
297
  for (i = 0; i < DTLB_WAYS; i++) {
298
    REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) = i;
299
 
300
    /* Check if there was DTLB miss */
301
    ASSERT(dtlb_miss_count == (i + 1));
302
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
303
  }
304
 
305
  /* Reset DTLB miss counter and EA */
306
  dtlb_miss_count = 0;
307
  dtlb_miss_ea = 0;
308
 
309
  /* Perform reads to address, that is now in DTLB */
310
  for (i = 0; i < DTLB_WAYS; i++) {
311
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
312
 
313
    /* Check if there was DTLB miss */
314
    ASSERT(dtlb_miss_count == 0);
315
  }
316
 
317
  /* Reset valid bits */
318
  for (i = 0; i < DTLB_WAYS; i++) {
319
    mtspr (SPR_DTLBMR_BASE(i) + set, mfspr (SPR_DTLBMR_BASE(i) + set) & ~SPR_DTLBMR_V);
320
  }
321
 
322
  /* Perform reads to address, that is now in DTLB but is invalid */
323
  for (i = 0; i < DTLB_WAYS; i++) {
324
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
325
 
326
    /* Check if there was DTLB miss */
327
    ASSERT(dtlb_miss_count == (i + 1));
328
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
329
  }
330
 
331
  return 0;
332
}
333
 
334 413 markom
/* Valid bit test
335
   Set all ways of one set to be invalid, perform
336
   access so miss handler will set them to valid,
337
   try access again - there should be no miss exceptions */
338
int itlb_valid_bit_test (int set)
339
{
340
  int i;
341 412 simons
 
342 413 markom
  /* Reset ITLB miss counter and EA */
343
  itlb_miss_count = 0;
344
  itlb_miss_ea = 0;
345
 
346
  /* Set itlb permisions */
347
  itlb_val = TLB_PR_NOLIMIT;
348 412 simons
 
349 413 markom
  /* Resetv ITLBMR for every way */
350
  for (i = 0; i < ITLB_WAYS; i++) {
351
    mtspr (SPR_ITLBMR_BASE(i) + set, 0);
352
  }
353 412 simons
 
354 413 markom
  /* Perform jumps to address, that is not in ITLB */
355
  for (i = 0; i < ITLB_WAYS; i++) {
356
    TEST_JUMP(FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
357
 
358
    /* Check if there was ITLB miss */
359
    ASSERT(itlb_miss_count == (i + 1));
360
    ASSERT(itlb_miss_ea == (FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
361
  }
362 412 simons
 
363 413 markom
  /* Reset ITLB miss counter and EA */
364
  itlb_miss_count = 0;
365
  itlb_miss_ea = 0;
366
 
367
  /* Perform jumps to address, that is now in ITLB */
368
  for (i = 0; i < ITLB_WAYS; i++) {
369
    TEST_JUMP(FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
370
 
371
    /* Check if there was ITLB miss */
372
    ASSERT(itlb_miss_count == 0);
373
  }
374
 
375
  /* Reset valid bits */
376
  for (i = 0; i < ITLB_WAYS; i++) {
377
    mtspr (SPR_ITLBMR_BASE(i) + set, mfspr (SPR_ITLBMR_BASE(i) + set) & ~SPR_ITLBMR_V);
378
  }
379
 
380
  /* Perform jumps to address, that is now in ITLB but is invalid */
381
  for (i = 0; i < ITLB_WAYS; i++) {
382
    TEST_JUMP(FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE));
383
 
384
    /* Check if there was ITLB miss */
385
    ASSERT(itlb_miss_count == (i + 1));
386
    ASSERT(itlb_miss_ea == (FLASH_START + FLASH_SIZE + (i*ITLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
387
  }
388
 
389
  return 0;
390
}
391
 
392 410 simons
int main (void)
393
{
394 412 simons
  int i;
395 410 simons
 
396
  /* Enable DMMU */
397
  dmmu_enable();
398
 
399 412 simons
  /* Valid bit testing */
400
  for (i = 0; i < 15; i++)
401
    dtlb_valid_bit_test (DTLB_SETS - i - 1);
402 413 markom
 
403
  /* Valid bit testing */
404
  for (i = 0; i < 15; i++)
405
    itlb_valid_bit_test (ITLB_SETS - i - 1);
406 412 simons
 
407 410 simons
  /* Write pattern */
408 412 simons
//  write_pattern(0x40000000, 0x40100000);
409 410 simons
 
410
  /* Enable IMMU */
411
//  immu_enable();
412
 
413
  exit(0);
414
  return 0;
415
}

powered by: WebSVN 2.1.0

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