tlb.cc (3811:ee71d61347f1) tlb.cc (3823:1c8f87aa103e)
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31#include "arch/sparc/asi.hh"
32#include "arch/sparc/miscregfile.hh"
33#include "arch/sparc/tlb.hh"
34#include "base/trace.hh"
35#include "cpu/thread_context.hh"
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Ali Saidi
29 */
30
31#include "arch/sparc/asi.hh"
32#include "arch/sparc/miscregfile.hh"
33#include "arch/sparc/tlb.hh"
34#include "base/trace.hh"
35#include "cpu/thread_context.hh"
36#include "cpu/base.hh"
37#include "mem/packet_access.hh"
38#include "mem/request.hh"
36#include "sim/builder.hh"
37
38/* @todo remove some of the magic constants. -- ali
39 * */
40namespace SparcISA
41{
42
43TLB::TLB(const std::string &name, int s)
44 : SimObject(name), size(s)
45{
46 // To make this work you'll have to change the hypervisor and OS
47 if (size > 64)
48 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries.");
49
50 tlb = new TlbEntry[size];
51 memset(tlb, 0, sizeof(TlbEntry) * size);
52}
53
54void
55TLB::clearUsedBits()
56{
57 MapIter i;
58 for (i = lookupTable.begin(); i != lookupTable.end();) {
59 TlbEntry *t = i->second;
60 if (!t->pte.locked()) {
61 t->used = false;
62 usedEntries--;
63 }
64 }
65}
66
67
68void
69TLB::insert(Addr va, int partition_id, int context_id, bool real,
70 const PageTableEntry& PTE)
71{
72
73
74 MapIter i;
75 TlbEntry *new_entry;
76
77 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n",
78 va, partition_id, context_id, (int)real);
79
80 int x = -1;
81 for (x = 0; x < size; x++) {
82 if (!tlb[x].valid || !tlb[x].used) {
83 new_entry = &tlb[x];
84 break;
85 }
86 }
87
88 // Update the last ently if their all locked
89 if (x == -1)
90 x = size - 1;
91
92 assert(PTE.valid());
93 new_entry->range.va = va;
94 new_entry->range.size = PTE.size();
95 new_entry->range.partitionId = partition_id;
96 new_entry->range.contextId = context_id;
97 new_entry->range.real = real;
98 new_entry->pte = PTE;
99 new_entry->used = true;;
100 new_entry->valid = true;
101 usedEntries++;
102
103
104 // Demap any entry that conflicts
105 i = lookupTable.find(new_entry->range);
106 if (i != lookupTable.end()) {
107 i->second->valid = false;
108 if (i->second->used) {
109 i->second->used = false;
110 usedEntries--;
111 }
112 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n");
113 lookupTable.erase(i);
114 }
115
116 lookupTable.insert(new_entry->range, new_entry);;
117
118 // If all entries have there used bit set, clear it on them all, but the
119 // one we just inserted
120 if (usedEntries == size) {
121 clearUsedBits();
122 new_entry->used = true;
123 usedEntries++;
124 }
125
126}
127
128
129TlbEntry*
130TLB::lookup(Addr va, int partition_id, bool real, int context_id)
131{
132 MapIter i;
133 TlbRange tr;
134 TlbEntry *t;
135
136 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n",
137 va, partition_id, context_id, real);
138 // Assemble full address structure
139 tr.va = va;
140 tr.size = va + MachineBytes;
141 tr.contextId = context_id;
142 tr.partitionId = partition_id;
143 tr.real = real;
144
145 // Try to find the entry
146 i = lookupTable.find(tr);
147 if (i == lookupTable.end()) {
148 DPRINTF(TLB, "TLB: No valid entry found\n");
149 return NULL;
150 }
151 DPRINTF(TLB, "TLB: Valid entry found\n");
152
153 // Mark the entries used bit and clear other used bits in needed
154 t = i->second;
155 if (!t->used) {
156 t->used = true;
157 usedEntries++;
158 if (usedEntries == size) {
159 clearUsedBits();
160 t->used = true;
161 usedEntries++;
162 }
163 }
164
165 return t;
166}
167
168
169void
170TLB::demapPage(Addr va, int partition_id, bool real, int context_id)
171{
172 TlbRange tr;
173 MapIter i;
174
175 // Assemble full address structure
176 tr.va = va;
177 tr.size = va + MachineBytes;
178 tr.contextId = context_id;
179 tr.partitionId = partition_id;
180 tr.real = real;
181
182 // Demap any entry that conflicts
183 i = lookupTable.find(tr);
184 if (i != lookupTable.end()) {
185 i->second->valid = false;
186 if (i->second->used) {
187 i->second->used = false;
188 usedEntries--;
189 }
190 lookupTable.erase(i);
191 }
192}
193
194void
195TLB::demapContext(int partition_id, int context_id)
196{
197 int x;
198 for (x = 0; x < size; x++) {
199 if (tlb[x].range.contextId == context_id &&
200 tlb[x].range.partitionId == partition_id) {
201 tlb[x].valid = false;
202 if (tlb[x].used) {
203 tlb[x].used = false;
204 usedEntries--;
205 }
206 lookupTable.erase(tlb[x].range);
207 }
208 }
209}
210
211void
212TLB::demapAll(int partition_id)
213{
214 int x;
215 for (x = 0; x < size; x++) {
216 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
217 tlb[x].valid = false;
218 if (tlb[x].used) {
219 tlb[x].used = false;
220 usedEntries--;
221 }
222 lookupTable.erase(tlb[x].range);
223 }
224 }
225}
226
227void
228TLB::invalidateAll()
229{
230 int x;
231 for (x = 0; x < size; x++) {
232 tlb[x].valid = false;
233 }
234 usedEntries = 0;
235}
236
237uint64_t
238TLB::TteRead(int entry) {
239 assert(entry < size);
240 return tlb[entry].pte();
241}
242
243uint64_t
244TLB::TagRead(int entry) {
245 assert(entry < size);
246 uint64_t tag;
247
248 tag = tlb[entry].range.contextId | tlb[entry].range.va |
249 (uint64_t)tlb[entry].range.partitionId << 61;
250 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0;
251 tag |= (uint64_t)~tlb[entry].pte._size() << 56;
252 return tag;
253}
254
255bool
256TLB::validVirtualAddress(Addr va, bool am)
257{
258 if (am)
259 return true;
260 if (va >= StartVAddrHole && va <= EndVAddrHole)
261 return false;
262 return true;
263}
264
265void
266TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
267 bool se, FaultTypes ft, int asi)
268{
269 uint64_t sfsr;
270 sfsr = tc->readMiscReg(reg);
271
272 if (sfsr & 0x1)
273 sfsr = 0x3;
274 else
275 sfsr = 1;
276
277 if (write)
278 sfsr |= 1 << 2;
279 sfsr |= ct << 4;
280 if (se)
281 sfsr |= 1 << 6;
282 sfsr |= ft << 7;
283 sfsr |= asi << 16;
284 tc->setMiscReg(reg, sfsr);
285}
286
287
288void
289ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct,
290 bool se, FaultTypes ft, int asi)
291{
292 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n",
293 (int)write, ct, ft, asi);
294 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi);
295}
296
297void
298DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
299 bool se, FaultTypes ft, int asi)
300{
301 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n",
302 a, (int)write, ct, ft, asi);
303 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi);
304 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a);
305}
306
307
308Fault
309ITB::translate(RequestPtr &req, ThreadContext *tc)
310{
311 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
312 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
313 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1;
314 uint64_t tl = tc->readMiscReg(MISCREG_TL);
315 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
316 bool addr_mask = pstate >> 3 & 0x1;
317 bool priv = pstate >> 2 & 0x1;
318 Addr vaddr = req->getVaddr();
319 int context;
320 ContextType ct;
321 int asi;
322 bool real = false;
323 TlbEntry *e;
324
325 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
326 vaddr, req->getSize());
327
328 assert(req->getAsi() == ASI_IMPLICIT);
329
330 if (tl > 0) {
331 asi = ASI_N;
332 ct = Nucleus;
333 context = 0;
334 } else {
335 asi = ASI_P;
336 ct = Primary;
337 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
338 }
339
340 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) {
341 req->setPaddr(req->getVaddr() & PAddrImplMask);
342 return NoFault;
343 }
344
345 // If the asi is unaligned trap
346 if (vaddr & 0x7) {
347 writeSfsr(tc, false, ct, false, OtherFault, asi);
348 return new MemAddressNotAligned;
349 }
350
351 if (addr_mask)
352 vaddr = vaddr & VAddrAMask;
353
354 if (!validVirtualAddress(vaddr, addr_mask)) {
355 writeSfsr(tc, false, ct, false, VaOutOfRange, asi);
356 return new InstructionAccessException;
357 }
358
359 if (lsuIm) {
360 e = lookup(req->getVaddr(), part_id, true);
361 real = true;
362 context = 0;
363 } else {
364 e = lookup(vaddr, part_id, false, context);
365 }
366
367 if (e == NULL || !e->valid) {
368 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
369 vaddr & ~BytesInPageMask | context);
370 if (real)
371 return new InstructionRealTranslationMiss;
372 else
373 return new FastInstructionAccessMMUMiss;
374 }
375
376 // were not priviledged accesing priv page
377 if (!priv && e->pte.priv()) {
378 writeSfsr(tc, false, ct, false, PrivViolation, asi);
379 return new InstructionAccessException;
380 }
381
382 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
383 req->getVaddr() & e->pte.size());
384 return NoFault;
385}
386
387
388
389Fault
390DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
391{
392 /* @todo this could really use some profiling and fixing to make it faster! */
393 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
394 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
395 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1;
396 uint64_t tl = tc->readMiscReg(MISCREG_TL);
397 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
398 bool hpriv = hpstate >> 2 & 0x1;
399 bool red = hpstate >> 5 >> 0x1;
400 bool addr_mask = pstate >> 3 & 0x1;
401 bool priv = pstate >> 2 & 0x1;
402 bool implicit = false;
403 bool real = false;
404 Addr vaddr = req->getVaddr();
405 Addr size = req->getSize();
406 ContextType ct;
407 int context;
408 ASI asi;
409
410 TlbEntry *e;
411
412 asi = (ASI)req->getAsi();
413 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
414 vaddr, size, asi);
415
416 if (asi == ASI_IMPLICIT)
417 implicit = true;
418
419 if (implicit) {
420 if (tl > 0) {
421 asi = ASI_N;
422 ct = Nucleus;
423 context = 0;
424 } else {
425 asi = ASI_P;
426 ct = Primary;
427 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
428 }
429 } else if (!hpriv && !red) {
39#include "sim/builder.hh"
40
41/* @todo remove some of the magic constants. -- ali
42 * */
43namespace SparcISA
44{
45
46TLB::TLB(const std::string &name, int s)
47 : SimObject(name), size(s)
48{
49 // To make this work you'll have to change the hypervisor and OS
50 if (size > 64)
51 fatal("SPARC T1 TLB registers don't support more than 64 TLB entries.");
52
53 tlb = new TlbEntry[size];
54 memset(tlb, 0, sizeof(TlbEntry) * size);
55}
56
57void
58TLB::clearUsedBits()
59{
60 MapIter i;
61 for (i = lookupTable.begin(); i != lookupTable.end();) {
62 TlbEntry *t = i->second;
63 if (!t->pte.locked()) {
64 t->used = false;
65 usedEntries--;
66 }
67 }
68}
69
70
71void
72TLB::insert(Addr va, int partition_id, int context_id, bool real,
73 const PageTableEntry& PTE)
74{
75
76
77 MapIter i;
78 TlbEntry *new_entry;
79
80 DPRINTF(TLB, "TLB: Inserting TLB Entry; va=%#x, pid=%d cid=%d r=%d\n",
81 va, partition_id, context_id, (int)real);
82
83 int x = -1;
84 for (x = 0; x < size; x++) {
85 if (!tlb[x].valid || !tlb[x].used) {
86 new_entry = &tlb[x];
87 break;
88 }
89 }
90
91 // Update the last ently if their all locked
92 if (x == -1)
93 x = size - 1;
94
95 assert(PTE.valid());
96 new_entry->range.va = va;
97 new_entry->range.size = PTE.size();
98 new_entry->range.partitionId = partition_id;
99 new_entry->range.contextId = context_id;
100 new_entry->range.real = real;
101 new_entry->pte = PTE;
102 new_entry->used = true;;
103 new_entry->valid = true;
104 usedEntries++;
105
106
107 // Demap any entry that conflicts
108 i = lookupTable.find(new_entry->range);
109 if (i != lookupTable.end()) {
110 i->second->valid = false;
111 if (i->second->used) {
112 i->second->used = false;
113 usedEntries--;
114 }
115 DPRINTF(TLB, "TLB: Found conflicting entry, deleting it\n");
116 lookupTable.erase(i);
117 }
118
119 lookupTable.insert(new_entry->range, new_entry);;
120
121 // If all entries have there used bit set, clear it on them all, but the
122 // one we just inserted
123 if (usedEntries == size) {
124 clearUsedBits();
125 new_entry->used = true;
126 usedEntries++;
127 }
128
129}
130
131
132TlbEntry*
133TLB::lookup(Addr va, int partition_id, bool real, int context_id)
134{
135 MapIter i;
136 TlbRange tr;
137 TlbEntry *t;
138
139 DPRINTF(TLB, "TLB: Looking up entry va=%#x pid=%d cid=%d r=%d\n",
140 va, partition_id, context_id, real);
141 // Assemble full address structure
142 tr.va = va;
143 tr.size = va + MachineBytes;
144 tr.contextId = context_id;
145 tr.partitionId = partition_id;
146 tr.real = real;
147
148 // Try to find the entry
149 i = lookupTable.find(tr);
150 if (i == lookupTable.end()) {
151 DPRINTF(TLB, "TLB: No valid entry found\n");
152 return NULL;
153 }
154 DPRINTF(TLB, "TLB: Valid entry found\n");
155
156 // Mark the entries used bit and clear other used bits in needed
157 t = i->second;
158 if (!t->used) {
159 t->used = true;
160 usedEntries++;
161 if (usedEntries == size) {
162 clearUsedBits();
163 t->used = true;
164 usedEntries++;
165 }
166 }
167
168 return t;
169}
170
171
172void
173TLB::demapPage(Addr va, int partition_id, bool real, int context_id)
174{
175 TlbRange tr;
176 MapIter i;
177
178 // Assemble full address structure
179 tr.va = va;
180 tr.size = va + MachineBytes;
181 tr.contextId = context_id;
182 tr.partitionId = partition_id;
183 tr.real = real;
184
185 // Demap any entry that conflicts
186 i = lookupTable.find(tr);
187 if (i != lookupTable.end()) {
188 i->second->valid = false;
189 if (i->second->used) {
190 i->second->used = false;
191 usedEntries--;
192 }
193 lookupTable.erase(i);
194 }
195}
196
197void
198TLB::demapContext(int partition_id, int context_id)
199{
200 int x;
201 for (x = 0; x < size; x++) {
202 if (tlb[x].range.contextId == context_id &&
203 tlb[x].range.partitionId == partition_id) {
204 tlb[x].valid = false;
205 if (tlb[x].used) {
206 tlb[x].used = false;
207 usedEntries--;
208 }
209 lookupTable.erase(tlb[x].range);
210 }
211 }
212}
213
214void
215TLB::demapAll(int partition_id)
216{
217 int x;
218 for (x = 0; x < size; x++) {
219 if (!tlb[x].pte.locked() && tlb[x].range.partitionId == partition_id) {
220 tlb[x].valid = false;
221 if (tlb[x].used) {
222 tlb[x].used = false;
223 usedEntries--;
224 }
225 lookupTable.erase(tlb[x].range);
226 }
227 }
228}
229
230void
231TLB::invalidateAll()
232{
233 int x;
234 for (x = 0; x < size; x++) {
235 tlb[x].valid = false;
236 }
237 usedEntries = 0;
238}
239
240uint64_t
241TLB::TteRead(int entry) {
242 assert(entry < size);
243 return tlb[entry].pte();
244}
245
246uint64_t
247TLB::TagRead(int entry) {
248 assert(entry < size);
249 uint64_t tag;
250
251 tag = tlb[entry].range.contextId | tlb[entry].range.va |
252 (uint64_t)tlb[entry].range.partitionId << 61;
253 tag |= tlb[entry].range.real ? ULL(1) << 60 : 0;
254 tag |= (uint64_t)~tlb[entry].pte._size() << 56;
255 return tag;
256}
257
258bool
259TLB::validVirtualAddress(Addr va, bool am)
260{
261 if (am)
262 return true;
263 if (va >= StartVAddrHole && va <= EndVAddrHole)
264 return false;
265 return true;
266}
267
268void
269TLB::writeSfsr(ThreadContext *tc, int reg, bool write, ContextType ct,
270 bool se, FaultTypes ft, int asi)
271{
272 uint64_t sfsr;
273 sfsr = tc->readMiscReg(reg);
274
275 if (sfsr & 0x1)
276 sfsr = 0x3;
277 else
278 sfsr = 1;
279
280 if (write)
281 sfsr |= 1 << 2;
282 sfsr |= ct << 4;
283 if (se)
284 sfsr |= 1 << 6;
285 sfsr |= ft << 7;
286 sfsr |= asi << 16;
287 tc->setMiscReg(reg, sfsr);
288}
289
290
291void
292ITB::writeSfsr(ThreadContext *tc, bool write, ContextType ct,
293 bool se, FaultTypes ft, int asi)
294{
295 DPRINTF(TLB, "TLB: ITB Fault: w=%d ct=%d ft=%d asi=%d\n",
296 (int)write, ct, ft, asi);
297 TLB::writeSfsr(tc, MISCREG_MMU_ITLB_SFSR, write, ct, se, ft, asi);
298}
299
300void
301DTB::writeSfr(ThreadContext *tc, Addr a, bool write, ContextType ct,
302 bool se, FaultTypes ft, int asi)
303{
304 DPRINTF(TLB, "TLB: DTB Fault: A=%#x w=%d ct=%d ft=%d asi=%d\n",
305 a, (int)write, ct, ft, asi);
306 TLB::writeSfsr(tc, MISCREG_MMU_DTLB_SFSR, write, ct, se, ft, asi);
307 tc->setMiscReg(MISCREG_MMU_DTLB_SFAR, a);
308}
309
310
311Fault
312ITB::translate(RequestPtr &req, ThreadContext *tc)
313{
314 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
315 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
316 bool lsuIm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 2 & 0x1;
317 uint64_t tl = tc->readMiscReg(MISCREG_TL);
318 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
319 bool addr_mask = pstate >> 3 & 0x1;
320 bool priv = pstate >> 2 & 0x1;
321 Addr vaddr = req->getVaddr();
322 int context;
323 ContextType ct;
324 int asi;
325 bool real = false;
326 TlbEntry *e;
327
328 DPRINTF(TLB, "TLB: ITB Request to translate va=%#x size=%d\n",
329 vaddr, req->getSize());
330
331 assert(req->getAsi() == ASI_IMPLICIT);
332
333 if (tl > 0) {
334 asi = ASI_N;
335 ct = Nucleus;
336 context = 0;
337 } else {
338 asi = ASI_P;
339 ct = Primary;
340 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
341 }
342
343 if ( hpstate >> 2 & 0x1 || hpstate >> 5 & 0x1 ) {
344 req->setPaddr(req->getVaddr() & PAddrImplMask);
345 return NoFault;
346 }
347
348 // If the asi is unaligned trap
349 if (vaddr & 0x7) {
350 writeSfsr(tc, false, ct, false, OtherFault, asi);
351 return new MemAddressNotAligned;
352 }
353
354 if (addr_mask)
355 vaddr = vaddr & VAddrAMask;
356
357 if (!validVirtualAddress(vaddr, addr_mask)) {
358 writeSfsr(tc, false, ct, false, VaOutOfRange, asi);
359 return new InstructionAccessException;
360 }
361
362 if (lsuIm) {
363 e = lookup(req->getVaddr(), part_id, true);
364 real = true;
365 context = 0;
366 } else {
367 e = lookup(vaddr, part_id, false, context);
368 }
369
370 if (e == NULL || !e->valid) {
371 tc->setMiscReg(MISCREG_MMU_ITLB_TAG_ACCESS,
372 vaddr & ~BytesInPageMask | context);
373 if (real)
374 return new InstructionRealTranslationMiss;
375 else
376 return new FastInstructionAccessMMUMiss;
377 }
378
379 // were not priviledged accesing priv page
380 if (!priv && e->pte.priv()) {
381 writeSfsr(tc, false, ct, false, PrivViolation, asi);
382 return new InstructionAccessException;
383 }
384
385 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
386 req->getVaddr() & e->pte.size());
387 return NoFault;
388}
389
390
391
392Fault
393DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
394{
395 /* @todo this could really use some profiling and fixing to make it faster! */
396 uint64_t hpstate = tc->readMiscReg(MISCREG_HPSTATE);
397 uint64_t pstate = tc->readMiscReg(MISCREG_PSTATE);
398 bool lsuDm = tc->readMiscReg(MISCREG_MMU_LSU_CTRL) >> 3 & 0x1;
399 uint64_t tl = tc->readMiscReg(MISCREG_TL);
400 uint64_t part_id = tc->readMiscReg(MISCREG_MMU_PART_ID);
401 bool hpriv = hpstate >> 2 & 0x1;
402 bool red = hpstate >> 5 >> 0x1;
403 bool addr_mask = pstate >> 3 & 0x1;
404 bool priv = pstate >> 2 & 0x1;
405 bool implicit = false;
406 bool real = false;
407 Addr vaddr = req->getVaddr();
408 Addr size = req->getSize();
409 ContextType ct;
410 int context;
411 ASI asi;
412
413 TlbEntry *e;
414
415 asi = (ASI)req->getAsi();
416 DPRINTF(TLB, "TLB: DTB Request to translate va=%#x size=%d asi=%#x\n",
417 vaddr, size, asi);
418
419 if (asi == ASI_IMPLICIT)
420 implicit = true;
421
422 if (implicit) {
423 if (tl > 0) {
424 asi = ASI_N;
425 ct = Nucleus;
426 context = 0;
427 } else {
428 asi = ASI_P;
429 ct = Primary;
430 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
431 }
432 } else if (!hpriv && !red) {
430 if (tl > 0) {
433 if (tl > 0 || AsiIsNucleus(asi)) {
431 ct = Nucleus;
432 context = 0;
433 } else if (AsiIsSecondary(asi)) {
434 ct = Secondary;
435 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT);
436 } else {
437 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
438 ct = Primary; //???
439 }
440
441 // We need to check for priv level/asi priv
442 if (!priv && !AsiIsUnPriv(asi)) {
443 // It appears that context should be Nucleus in these cases?
444 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
445 return new PrivilegedAction;
446 }
447 if (priv && AsiIsHPriv(asi)) {
448 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
449 return new DataAccessException;
450 }
451
452 }
453
454 // If the asi is unaligned trap
455 if (vaddr & size-1) {
456 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
457 return new MemAddressNotAligned;
458 }
459
460 if (addr_mask)
461 vaddr = vaddr & VAddrAMask;
462
463 if (!validVirtualAddress(vaddr, addr_mask)) {
464 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi);
465 return new DataAccessException;
466 }
467
468 if (!implicit) {
469 if (AsiIsLittle(asi))
470 panic("Little Endian ASIs not supported\n");
471 if (AsiIsBlock(asi))
472 panic("Block ASIs not supported\n");
473 if (AsiIsNoFault(asi))
474 panic("No Fault ASIs not supported\n");
475 if (AsiIsTwin(asi))
476 panic("Twin ASIs not supported\n");
477 if (AsiIsPartialStore(asi))
478 panic("Partial Store ASIs not supported\n");
434 ct = Nucleus;
435 context = 0;
436 } else if (AsiIsSecondary(asi)) {
437 ct = Secondary;
438 context = tc->readMiscReg(MISCREG_MMU_S_CONTEXT);
439 } else {
440 context = tc->readMiscReg(MISCREG_MMU_P_CONTEXT);
441 ct = Primary; //???
442 }
443
444 // We need to check for priv level/asi priv
445 if (!priv && !AsiIsUnPriv(asi)) {
446 // It appears that context should be Nucleus in these cases?
447 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
448 return new PrivilegedAction;
449 }
450 if (priv && AsiIsHPriv(asi)) {
451 writeSfr(tc, vaddr, write, Nucleus, false, IllegalAsi, asi);
452 return new DataAccessException;
453 }
454
455 }
456
457 // If the asi is unaligned trap
458 if (vaddr & size-1) {
459 writeSfr(tc, vaddr, false, ct, false, OtherFault, asi);
460 return new MemAddressNotAligned;
461 }
462
463 if (addr_mask)
464 vaddr = vaddr & VAddrAMask;
465
466 if (!validVirtualAddress(vaddr, addr_mask)) {
467 writeSfr(tc, vaddr, false, ct, true, VaOutOfRange, asi);
468 return new DataAccessException;
469 }
470
471 if (!implicit) {
472 if (AsiIsLittle(asi))
473 panic("Little Endian ASIs not supported\n");
474 if (AsiIsBlock(asi))
475 panic("Block ASIs not supported\n");
476 if (AsiIsNoFault(asi))
477 panic("No Fault ASIs not supported\n");
478 if (AsiIsTwin(asi))
479 panic("Twin ASIs not supported\n");
480 if (AsiIsPartialStore(asi))
481 panic("Partial Store ASIs not supported\n");
482
479 if (AsiIsMmu(asi))
480 goto handleMmuRegAccess;
483 if (AsiIsMmu(asi))
484 goto handleMmuRegAccess;
481
482 if (AsiIsScratchPad(asi))
483 goto handleScratchRegAccess;
485 if (AsiIsScratchPad(asi))
486 goto handleScratchRegAccess;
487
488 if (!AsiIsReal(asi) && !AsiIsNucleus(asi))
489 panic("Accessing ASI %#X. Should we?\n", asi);
484 }
485
486 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) {
487 real = true;
488 context = 0;
489 };
490
491 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
492 req->setPaddr(req->getVaddr() & PAddrImplMask);
493 return NoFault;
494 }
495
496 e = lookup(req->getVaddr(), part_id, real, context);
497
498 if (e == NULL || !e->valid) {
499 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
500 vaddr & ~BytesInPageMask | context);
501 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
502 if (real)
503 return new DataRealTranslationMiss;
504 else
505 return new FastDataAccessMMUMiss;
506
507 }
508
509
510 if (write && !e->pte.writable()) {
511 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
512 return new FastDataAccessProtection;
513 }
514
515 if (e->pte.nofault() && !AsiIsNoFault(asi)) {
516 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
517 return new DataAccessException;
518 }
519
520 if (e->pte.sideffect())
521 req->setFlags(req->getFlags() | UNCACHEABLE);
522
523
524 if (!priv && e->pte.priv()) {
525 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
526 return new DataAccessException;
527 }
528
529 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
530 req->getVaddr() & e->pte.size());
531 return NoFault;
532 /** Normal flow ends here. */
533
534handleScratchRegAccess:
535 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
536 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
537 return new DataAccessException;
538 }
539handleMmuRegAccess:
540 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
541 req->setMmapedIpr(true);
542 req->setPaddr(req->getVaddr());
543 return NoFault;
544};
545
546Tick
547DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
548{
490 }
491
492 if ((!lsuDm && !hpriv) || AsiIsReal(asi)) {
493 real = true;
494 context = 0;
495 };
496
497 if (hpriv && (implicit || (!AsiIsAsIfUser(asi) && !AsiIsReal(asi)))) {
498 req->setPaddr(req->getVaddr() & PAddrImplMask);
499 return NoFault;
500 }
501
502 e = lookup(req->getVaddr(), part_id, real, context);
503
504 if (e == NULL || !e->valid) {
505 tc->setMiscReg(MISCREG_MMU_DTLB_TAG_ACCESS,
506 vaddr & ~BytesInPageMask | context);
507 DPRINTF(TLB, "TLB: DTB Failed to find matching TLB entry\n");
508 if (real)
509 return new DataRealTranslationMiss;
510 else
511 return new FastDataAccessMMUMiss;
512
513 }
514
515
516 if (write && !e->pte.writable()) {
517 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), OtherFault, asi);
518 return new FastDataAccessProtection;
519 }
520
521 if (e->pte.nofault() && !AsiIsNoFault(asi)) {
522 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), LoadFromNfo, asi);
523 return new DataAccessException;
524 }
525
526 if (e->pte.sideffect())
527 req->setFlags(req->getFlags() | UNCACHEABLE);
528
529
530 if (!priv && e->pte.priv()) {
531 writeSfr(tc, vaddr, write, ct, e->pte.sideffect(), PrivViolation, asi);
532 return new DataAccessException;
533 }
534
535 req->setPaddr(e->pte.paddr() & ~e->pte.size() |
536 req->getVaddr() & e->pte.size());
537 return NoFault;
538 /** Normal flow ends here. */
539
540handleScratchRegAccess:
541 if (vaddr > 0x38 || (vaddr >= 0x20 && vaddr < 0x30 && !hpriv)) {
542 writeSfr(tc, vaddr, write, Primary, true, IllegalAsi, asi);
543 return new DataAccessException;
544 }
545handleMmuRegAccess:
546 DPRINTF(TLB, "TLB: DTB Translating MM IPR access\n");
547 req->setMmapedIpr(true);
548 req->setPaddr(req->getVaddr());
549 return NoFault;
550};
551
552Tick
553DTB::doMmuRegRead(ThreadContext *tc, Packet *pkt)
554{
549 panic("need to implement DTB::doMmuRegRead()\n");
555 Addr va = pkt->getAddr();
556 ASI asi = (ASI)pkt->req->getAsi();
557
558 DPRINTF(IPR, "Memory Mapped IPR Read: asi=%#X a=%#x\n",
559 (uint32_t)pkt->req->getAsi(), pkt->getAddr());
560
561 switch (asi) {
562 case ASI_LSU_CONTROL_REG:
563 assert(va == 0);
564 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_LSU_CTRL));
565 break;
566 case ASI_MMU:
567 switch (va) {
568 case 0x8:
569 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_P_CONTEXT));
570 break;
571 case 0x10:
572 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_S_CONTEXT));
573 break;
574 default:
575 goto doMmuReadError;
576 }
577 break;
578 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
579 assert(va == 0);
580 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0));
581 break;
582 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
583 assert(va == 0);
584 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1));
585 break;
586 case ASI_DMMU_CTXT_ZERO_CONFIG:
587 assert(va == 0);
588 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG));
589 break;
590 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
591 assert(va == 0);
592 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0));
593 break;
594 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
595 assert(va == 0);
596 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1));
597 break;
598 case ASI_IMMU_CTXT_ZERO_CONFIG:
599 assert(va == 0);
600 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG));
601 break;
602 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
603 assert(va == 0);
604 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0));
605 break;
606 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
607 assert(va == 0);
608 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1));
609 break;
610 case ASI_DMMU_CTXT_NONZERO_CONFIG:
611 assert(va == 0);
612 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG));
613 break;
614 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
615 assert(va == 0);
616 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0));
617 break;
618 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
619 assert(va == 0);
620 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1));
621 break;
622 case ASI_IMMU_CTXT_NONZERO_CONFIG:
623 assert(va == 0);
624 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG));
625 break;
626 case ASI_HYP_SCRATCHPAD:
627 case ASI_SCRATCHPAD:
628 pkt->set(tc->readMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3)));
629 break;
630 case ASI_DMMU:
631 switch (va) {
632 case 0x80:
633 pkt->set(tc->readMiscRegWithEffect(MISCREG_MMU_PART_ID));
634 break;
635 default:
636 goto doMmuReadError;
637 }
638 break;
639 default:
640doMmuReadError:
641 panic("need to impl DTB::doMmuRegRead() got asi=%#x, va=%#x\n",
642 (uint32_t)asi, va);
643 }
644 pkt->result = Packet::Success;
645 return tc->getCpuPtr()->cycles(1);
550}
551
552Tick
553DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
554{
646}
647
648Tick
649DTB::doMmuRegWrite(ThreadContext *tc, Packet *pkt)
650{
555 panic("need to implement DTB::doMmuRegWrite()\n");
651 uint64_t data = gtoh(pkt->get<uint64_t>());
652 Addr va = pkt->getAddr();
653 ASI asi = (ASI)pkt->req->getAsi();
654
655 DPRINTF(IPR, "Memory Mapped IPR Write: asi=#%X a=%#x d=%#X\n",
656 (uint32_t)asi, va, data);
657
658 switch (asi) {
659 case ASI_LSU_CONTROL_REG:
660 assert(va == 0);
661 tc->setMiscRegWithEffect(MISCREG_MMU_LSU_CTRL, data);
662 break;
663 case ASI_MMU:
664 switch (va) {
665 case 0x8:
666 tc->setMiscRegWithEffect(MISCREG_MMU_P_CONTEXT, data);
667 break;
668 case 0x10:
669 tc->setMiscRegWithEffect(MISCREG_MMU_S_CONTEXT, data);
670 break;
671 default:
672 goto doMmuWriteError;
673 }
674 break;
675 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS0:
676 assert(va == 0);
677 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS0, data);
678 break;
679 case ASI_DMMU_CTXT_ZERO_TSB_BASE_PS1:
680 assert(va == 0);
681 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_TSB_PS1, data);
682 break;
683 case ASI_DMMU_CTXT_ZERO_CONFIG:
684 assert(va == 0);
685 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_C0_CONFIG, data);
686 break;
687 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS0:
688 assert(va == 0);
689 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS0, data);
690 break;
691 case ASI_IMMU_CTXT_ZERO_TSB_BASE_PS1:
692 assert(va == 0);
693 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_TSB_PS1, data);
694 break;
695 case ASI_IMMU_CTXT_ZERO_CONFIG:
696 assert(va == 0);
697 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_C0_CONFIG, data);
698 break;
699 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS0:
700 assert(va == 0);
701 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS0, data);
702 break;
703 case ASI_DMMU_CTXT_NONZERO_TSB_BASE_PS1:
704 assert(va == 0);
705 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_TSB_PS1, data);
706 break;
707 case ASI_DMMU_CTXT_NONZERO_CONFIG:
708 assert(va == 0);
709 tc->setMiscRegWithEffect(MISCREG_MMU_DTLB_CX_CONFIG, data);
710 break;
711 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS0:
712 assert(va == 0);
713 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS0, data);
714 break;
715 case ASI_IMMU_CTXT_NONZERO_TSB_BASE_PS1:
716 assert(va == 0);
717 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_TSB_PS1, data);
718 break;
719 case ASI_IMMU_CTXT_NONZERO_CONFIG:
720 assert(va == 0);
721 tc->setMiscRegWithEffect(MISCREG_MMU_ITLB_CX_CONFIG, data);
722 break;
723 case ASI_HYP_SCRATCHPAD:
724 case ASI_SCRATCHPAD:
725 tc->setMiscRegWithEffect(MISCREG_SCRATCHPAD_R0 + (va >> 3), data);
726 break;
727 case ASI_DMMU:
728 switch (va) {
729 case 0x80:
730 tc->setMiscRegWithEffect(MISCREG_MMU_PART_ID, data);
731 break;
732 default:
733 goto doMmuWriteError;
734 }
735 break;
736 default:
737doMmuWriteError:
738 panic("need to impl DTB::doMmuRegWrite() got asi=%#x, va=%#x d=%#x\n",
739 (uint32_t)pkt->req->getAsi(), pkt->getAddr(), data);
740 }
741 pkt->result = Packet::Success;
742 return tc->getCpuPtr()->cycles(1);
556}
557
558void
559TLB::serialize(std::ostream &os)
560{
561 panic("Need to implement serialize tlb for SPARC\n");
562}
563
564void
565TLB::unserialize(Checkpoint *cp, const std::string &section)
566{
567 panic("Need to implement unserialize tlb for SPARC\n");
568}
569
570
571DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
572
573BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
574
575 Param<int> size;
576
577END_DECLARE_SIM_OBJECT_PARAMS(ITB)
578
579BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
580
581 INIT_PARAM_DFLT(size, "TLB size", 48)
582
583END_INIT_SIM_OBJECT_PARAMS(ITB)
584
585
586CREATE_SIM_OBJECT(ITB)
587{
588 return new ITB(getInstanceName(), size);
589}
590
591REGISTER_SIM_OBJECT("SparcITB", ITB)
592
593BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
594
595 Param<int> size;
596
597END_DECLARE_SIM_OBJECT_PARAMS(DTB)
598
599BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
600
601 INIT_PARAM_DFLT(size, "TLB size", 64)
602
603END_INIT_SIM_OBJECT_PARAMS(DTB)
604
605
606CREATE_SIM_OBJECT(DTB)
607{
608 return new DTB(getInstanceName(), size);
609}
610
611REGISTER_SIM_OBJECT("SparcDTB", DTB)
612}
743}
744
745void
746TLB::serialize(std::ostream &os)
747{
748 panic("Need to implement serialize tlb for SPARC\n");
749}
750
751void
752TLB::unserialize(Checkpoint *cp, const std::string &section)
753{
754 panic("Need to implement unserialize tlb for SPARC\n");
755}
756
757
758DEFINE_SIM_OBJECT_CLASS_NAME("SparcTLB", TLB)
759
760BEGIN_DECLARE_SIM_OBJECT_PARAMS(ITB)
761
762 Param<int> size;
763
764END_DECLARE_SIM_OBJECT_PARAMS(ITB)
765
766BEGIN_INIT_SIM_OBJECT_PARAMS(ITB)
767
768 INIT_PARAM_DFLT(size, "TLB size", 48)
769
770END_INIT_SIM_OBJECT_PARAMS(ITB)
771
772
773CREATE_SIM_OBJECT(ITB)
774{
775 return new ITB(getInstanceName(), size);
776}
777
778REGISTER_SIM_OBJECT("SparcITB", ITB)
779
780BEGIN_DECLARE_SIM_OBJECT_PARAMS(DTB)
781
782 Param<int> size;
783
784END_DECLARE_SIM_OBJECT_PARAMS(DTB)
785
786BEGIN_INIT_SIM_OBJECT_PARAMS(DTB)
787
788 INIT_PARAM_DFLT(size, "TLB size", 64)
789
790END_INIT_SIM_OBJECT_PARAMS(DTB)
791
792
793CREATE_SIM_OBJECT(DTB)
794{
795 return new DTB(getInstanceName(), size);
796}
797
798REGISTER_SIM_OBJECT("SparcDTB", DTB)
799}