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

Subversion Repositories eco32

[/] [eco32/] [trunk/] [sim/] [mmu.c] - Blame information for rev 12

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

powered by: WebSVN 2.1.0

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