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

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.25/] [sim/] [mmu.c] - Blame information for rev 168

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

Line No. Rev Author Line
1 8 hellwig
/*
2
 * mmu.c -- MMU simulation
3
 */
4
 
5
 
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <string.h>
9
#include <setjmp.h>
10
 
11
#include "common.h"
12
#include "console.h"
13
#include "error.h"
14
#include "except.h"
15
#include "cpu.h"
16
#include "mmu.h"
17
#include "memory.h"
18
 
19
 
20
static Bool debugUse = false;
21
static Bool debugWrite = false;
22
 
23
 
24
static TLB_Entry tlb[TLB_SIZE];
25
static Word tlbIndex;
26
static Word tlbEntryHi;
27
static Word tlbEntryLo;
28 78 hellwig
static Word mmuBadAddr;
29 168 hellwig
static Word mmuBadAccs;
30 8 hellwig
 
31
 
32
static int assoc(Word page) {
33
  int n, i;
34
 
35
  n = -1;
36
  for (i = 0; i < TLB_SIZE; i++) {
37
    if (tlb[i].page == page) {
38
      n = i;
39
    }
40
  }
41
  return n;
42
}
43
 
44
 
45 168 hellwig
static Word v2p(Word vAddr, Bool userMode, Bool writing, int accsWidth) {
46 8 hellwig
  Word pAddr;
47
  Word page, offset;
48
  int index;
49
 
50
  if (debugUse) {
51
    cPrintf("**** vAddr = 0x%08X", vAddr);
52
  }
53
  if ((vAddr & 0x80000000) != 0 && userMode) {
54
    /* trying to access a privileged address from user mode */
55 168 hellwig
    mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
56 78 hellwig
    mmuBadAddr = vAddr;
57 8 hellwig
    throwException(EXC_PRV_ADDRESS);
58
  }
59
  if ((vAddr & 0xC0000000) == 0xC0000000) {
60
    /* unmapped address space */
61 166 hellwig
    /* simulate delay introduced by assoc when using mapped
62
       addresses but not experienced with unmapped addresses */
63
    assoc(0);
64 8 hellwig
    pAddr = vAddr & ~0xC0000000;
65
  } else {
66
    /* mapped address space */
67
    page = vAddr & PAGE_MASK;
68
    offset = vAddr & OFFSET_MASK;
69
    index = assoc(page);
70
    if (index == -1) {
71
      /* TLB miss exception */
72 168 hellwig
      mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
73 78 hellwig
      mmuBadAddr = vAddr;
74 8 hellwig
      tlbEntryHi = page;
75
      throwException(EXC_TLB_MISS);
76
    }
77
    if (!tlb[index].valid) {
78
      /* TLB invalid exception */
79 168 hellwig
      mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
80 78 hellwig
      mmuBadAddr = vAddr;
81 8 hellwig
      tlbEntryHi = page;
82
      throwException(EXC_TLB_INVALID);
83
    }
84
    if (!tlb[index].write && writing) {
85
      /* TLB write exception */
86 168 hellwig
      mmuBadAccs = (writing ? MMU_ACCS_WRITE : MMU_ACCS_READ) | accsWidth;
87 78 hellwig
      mmuBadAddr = vAddr;
88 8 hellwig
      tlbEntryHi = page;
89
      throwException(EXC_TLB_WRITE);
90
    }
91
    pAddr = tlb[index].frame | offset;
92
  }
93
  if (debugUse) {
94
    cPrintf(", pAddr = 0x%08X ****\n", pAddr);
95
  }
96
  return pAddr;
97
}
98
 
99
 
100
Word mmuReadWord(Word vAddr, Bool userMode) {
101
  if ((vAddr & 3) != 0) {
102
    /* throw illegal address exception */
103 168 hellwig
    mmuBadAccs = MMU_ACCS_READ | MMU_ACCS_WORD;
104 78 hellwig
    mmuBadAddr = vAddr;
105 8 hellwig
    throwException(EXC_ILL_ADDRESS);
106
  }
107 168 hellwig
  return memoryReadWord(v2p(vAddr, userMode, false, MMU_ACCS_WORD));
108 8 hellwig
}
109
 
110
 
111
Half mmuReadHalf(Word vAddr, Bool userMode) {
112
  if ((vAddr & 1) != 0) {
113
    /* throw illegal address exception */
114 168 hellwig
    mmuBadAccs = MMU_ACCS_READ | MMU_ACCS_HALF;
115 78 hellwig
    mmuBadAddr = vAddr;
116 8 hellwig
    throwException(EXC_ILL_ADDRESS);
117
  }
118 168 hellwig
  return memoryReadHalf(v2p(vAddr, userMode, false, MMU_ACCS_HALF));
119 8 hellwig
}
120
 
121
 
122
Byte mmuReadByte(Word vAddr, Bool userMode) {
123 168 hellwig
  return memoryReadByte(v2p(vAddr, userMode, false, MMU_ACCS_BYTE));
124 8 hellwig
}
125
 
126
 
127
void mmuWriteWord(Word vAddr, Word data, Bool userMode) {
128
  if ((vAddr & 3) != 0) {
129
    /* throw illegal address exception */
130 168 hellwig
    mmuBadAccs = MMU_ACCS_WRITE | MMU_ACCS_WORD;
131 78 hellwig
    mmuBadAddr = vAddr;
132 8 hellwig
    throwException(EXC_ILL_ADDRESS);
133
  }
134 168 hellwig
  memoryWriteWord(v2p(vAddr, userMode, true, MMU_ACCS_WORD), data);
135 8 hellwig
}
136
 
137
 
138
void mmuWriteHalf(Word vAddr, Half data, Bool userMode) {
139
  if ((vAddr & 1) != 0) {
140
    /* throw illegal address exception */
141 168 hellwig
    mmuBadAccs = MMU_ACCS_WRITE | MMU_ACCS_HALF;
142 78 hellwig
    mmuBadAddr = vAddr;
143 8 hellwig
    throwException(EXC_ILL_ADDRESS);
144
  }
145 168 hellwig
  memoryWriteHalf(v2p(vAddr, userMode, true, MMU_ACCS_HALF), data);
146 8 hellwig
}
147
 
148
 
149
void mmuWriteByte(Word vAddr, Byte data, Bool userMode) {
150 168 hellwig
  memoryWriteByte(v2p(vAddr, userMode, true, MMU_ACCS_BYTE), data);
151 8 hellwig
}
152
 
153
 
154
Word mmuGetIndex(void) {
155
  return tlbIndex;
156
}
157
 
158
 
159
void mmuSetIndex(Word value) {
160
  tlbIndex = value & TLB_MASK;
161
}
162
 
163
 
164
Word mmuGetEntryHi(void) {
165
  return tlbEntryHi;
166
}
167
 
168
 
169
void mmuSetEntryHi(Word value) {
170
  tlbEntryHi = value & PAGE_MASK;
171
}
172
 
173
 
174
Word mmuGetEntryLo(void) {
175
  return tlbEntryLo;
176
}
177
 
178
 
179
void mmuSetEntryLo(Word value) {
180
  tlbEntryLo = value & (PAGE_MASK | TLB_WRITE | TLB_VALID);
181
}
182
 
183
 
184
Word mmuGetBadAddr(void) {
185 78 hellwig
  return mmuBadAddr;
186 8 hellwig
}
187
 
188
 
189
void mmuSetBadAddr(Word value) {
190 78 hellwig
  mmuBadAddr = value;
191 8 hellwig
}
192
 
193
 
194 168 hellwig
Word mmuGetBadAccs(void) {
195
  return mmuBadAccs;
196
}
197
 
198
 
199
void mmuSetBadAccs(Word value) {
200
  mmuBadAccs = value;
201
}
202
 
203
 
204 8 hellwig
void mmuTbs(void) {
205
  int index;
206
 
207
  index = assoc(tlbEntryHi & PAGE_MASK);
208
  if (index == -1) {
209
    tlbIndex = 0x80000000;
210
  } else {
211
    tlbIndex = index;
212
  }
213
}
214
 
215
 
216
void mmuTbwr(void) {
217
  int index;
218
 
219
  /* choose a random index, but don't touch fixed entries */
220
  do {
221
    index = rand() & TLB_MASK;
222
  } while (index < TLB_FIXED);
223
  tlb[index].page = tlbEntryHi & PAGE_MASK;
224
  tlb[index].frame = tlbEntryLo & PAGE_MASK;
225
  tlb[index].write = tlbEntryLo & TLB_WRITE ? true : false;
226
  tlb[index].valid = tlbEntryLo & TLB_VALID ? true : false;
227
  if (debugWrite) {
228
    cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
229
            index, tlb[index].page, tlb[index].frame,
230
            tlb[index].write ? 'w' : '-',
231
            tlb[index].valid ? 'v' : '-');
232
  }
233
}
234
 
235
 
236
void mmuTbri(void) {
237
  int index;
238
 
239
  index = tlbIndex & TLB_MASK;
240
  tlbEntryHi = tlb[index].page;
241
  tlbEntryLo = tlb[index].frame;
242
  if (tlb[index].write) {
243
    tlbEntryLo |= TLB_WRITE;
244
  }
245
  if (tlb[index].valid) {
246
    tlbEntryLo |= TLB_VALID;
247
  }
248
}
249
 
250
 
251
void mmuTbwi(void) {
252
  int index;
253
 
254
  index = tlbIndex & TLB_MASK;
255
  tlb[index].page = tlbEntryHi & PAGE_MASK;
256
  tlb[index].frame = tlbEntryLo & PAGE_MASK;
257
  tlb[index].write = tlbEntryLo & TLB_WRITE ? true : false;
258
  tlb[index].valid = tlbEntryLo & TLB_VALID ? true : false;
259
  if (debugWrite) {
260
    cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
261
            index, tlb[index].page, tlb[index].frame,
262
            tlb[index].write ? 'w' : '-',
263
            tlb[index].valid ? 'v' : '-');
264
  }
265
}
266
 
267
 
268
TLB_Entry mmuGetTLB(int index) {
269
  return tlb[index & TLB_MASK];
270
}
271
 
272
 
273
void mmuSetTLB(int index, TLB_Entry tlbEntry) {
274
  index &= TLB_MASK;
275
  tlb[index] = tlbEntry;
276
  if (debugWrite) {
277
    cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
278
            index, tlb[index].page, tlb[index].frame,
279
            tlb[index].write ? 'w' : '-',
280
            tlb[index].valid ? 'v' : '-');
281
  }
282
}
283
 
284
 
285
void mmuReset(void) {
286
  int i;
287
 
288
  cPrintf("Resetting MMU...\n");
289
  for (i = 0; i < TLB_SIZE; i++) {
290
    tlb[i].page = rand() & PAGE_MASK;
291
    tlb[i].frame = rand() & PAGE_MASK;
292
    tlb[i].write = rand() & 0x1000 ? true : false;
293
    tlb[i].valid = rand() & 0x1000 ? true : false;
294
    if (debugWrite) {
295
      cPrintf("**** TLB[%02d] <- 0x%08X 0x%08X %c %c ****\n",
296
              i, tlb[i].page, tlb[i].frame,
297
              tlb[i].write ? 'w' : '-',
298
              tlb[i].valid ? 'v' : '-');
299
    }
300
  }
301
  tlbIndex = rand() & TLB_MASK;
302
  tlbEntryHi = rand() & PAGE_MASK;
303
  tlbEntryLo = rand() & (PAGE_MASK | TLB_WRITE | TLB_VALID);
304 78 hellwig
  mmuBadAddr = rand();
305 168 hellwig
  mmuBadAccs = rand() & MMU_ACCS_MASK;
306 8 hellwig
}
307
 
308
 
309
void mmuInit(void) {
310
  mmuReset();
311
}
312
 
313
 
314
void mmuExit(void) {
315
}

powered by: WebSVN 2.1.0

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