tlb.cc (12749:223c83ed9979) tlb.cc (12808:f275fd1244ce)
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Nathan Binkert
30 * Steve Reinhardt
31 * Jaidev Patwardhan
32 * Zhengxing Li
33 * Deyuan Guo
34 */
35
36#include "arch/riscv/tlb.hh"
37
38#include <string>
39#include <vector>
40
41#include "arch/riscv/faults.hh"
42#include "arch/riscv/pagetable.hh"
43#include "arch/riscv/pra_constants.hh"
1/*
2 * Copyright (c) 2001-2005 The Regents of The University of Michigan
3 * Copyright (c) 2007 MIPS Technologies, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Nathan Binkert
30 * Steve Reinhardt
31 * Jaidev Patwardhan
32 * Zhengxing Li
33 * Deyuan Guo
34 */
35
36#include "arch/riscv/tlb.hh"
37
38#include <string>
39#include <vector>
40
41#include "arch/riscv/faults.hh"
42#include "arch/riscv/pagetable.hh"
43#include "arch/riscv/pra_constants.hh"
44#include "arch/riscv/system.hh"
44#include "arch/riscv/utility.hh"
45#include "base/inifile.hh"
46#include "base/str.hh"
47#include "base/trace.hh"
48#include "cpu/thread_context.hh"
49#include "debug/RiscvTLB.hh"
50#include "debug/TLB.hh"
51#include "mem/page_table.hh"
52#include "params/RiscvTLB.hh"
53#include "sim/full_system.hh"
54#include "sim/process.hh"
55
56using namespace std;
57using namespace RiscvISA;
58
59///////////////////////////////////////////////////////////////////////
60//
61// RISC-V TLB
62//
63
64TLB::TLB(const Params *p)
65 : BaseTLB(p), size(p->size), nlu(0)
66{
67 table = new PTE[size];
68 memset(table, 0, sizeof(PTE[size]));
69 smallPages = 0;
70}
71
72TLB::~TLB()
73{
74 if (table)
75 delete [] table;
76}
77
78// look up an entry in the TLB
79RiscvISA::PTE *
80TLB::lookup(Addr vpn, uint8_t asn) const
81{
82 // assume not found...
83 PTE *retval = nullptr;
84 PageTable::const_iterator i = lookupTable.find(vpn);
85 if (i != lookupTable.end()) {
86 while (i->first == vpn) {
87 int index = i->second;
88 PTE *pte = &table[index];
89
90 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
91 Addr Mask = pte->Mask;
92 Addr InvMask = ~Mask;
93 Addr VPN = pte->VPN;
94 if (((vpn & InvMask) == (VPN & InvMask)) &&
95 (pte->G || (asn == pte->asid))) {
96 // We have a VPN + ASID Match
97 retval = pte;
98 break;
99 }
100 ++i;
101 }
102 }
103
104 DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
105 retval ? "hit" : "miss", retval ? retval->PFN1 : 0);
106 return retval;
107}
108
109RiscvISA::PTE*
110TLB::getEntry(unsigned Index) const
111{
112 // Make sure that Index is valid
113 assert(Index<size);
114 return &table[Index];
115}
116
117int
118TLB::probeEntry(Addr vpn, uint8_t asn) const
119{
120 // assume not found...
121 int Ind = -1;
122 PageTable::const_iterator i = lookupTable.find(vpn);
123 if (i != lookupTable.end()) {
124 while (i->first == vpn) {
125 int index = i->second;
126 PTE *pte = &table[index];
127
128 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
129 Addr Mask = pte->Mask;
130 Addr InvMask = ~Mask;
131 Addr VPN = pte->VPN;
132 if (((vpn & InvMask) == (VPN & InvMask)) &&
133 (pte->G || (asn == pte->asid))) {
134 // We have a VPN + ASID Match
135 Ind = index;
136 break;
137 }
138 ++i;
139 }
140 }
141 DPRINTF(RiscvTLB,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
142 return Ind;
143}
144
145inline Fault
146TLB::checkCacheability(const RequestPtr &req)
147{
148 Addr VAddrUncacheable = 0xA0000000;
149 // In MIPS, cacheability is controlled by certain bits of the virtual
150 // address or by the TLB entry
151 if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
152 // mark request as uncacheable
153 req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
154 }
155 return NoFault;
156}
157
158void
159TLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
160{
161 smallPages = _smallPages;
162 if (Index > size) {
163 warn("Attempted to write at index (%d) beyond TLB size (%d)",
164 Index, size);
165 } else {
166 // Update TLB
167 DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
168 Index, pte.Mask << 11,
169 ((pte.VPN << 11) | pte.asid),
170 ((pte.PFN0 << 6) | (pte.C0 << 3) |
171 (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
172 ((pte.PFN1 <<6) | (pte.C1 << 3) |
173 (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
174 if (table[Index].V0 || table[Index].V1) {
175 // Previous entry is valid
176 PageTable::iterator i = lookupTable.find(table[Index].VPN);
177 lookupTable.erase(i);
178 }
179 table[Index]=pte;
180 // Update fast lookup table
181 lookupTable.insert(make_pair(table[Index].VPN, Index));
182 }
183}
184
185// insert a new TLB entry
186void
187TLB::insert(Addr addr, PTE &pte)
188{
189 fatal("TLB Insert not yet implemented\n");
190}
191
192void
193TLB::flushAll()
194{
195 DPRINTF(TLB, "flushAll\n");
196 memset(table, 0, sizeof(PTE[size]));
197 lookupTable.clear();
198 nlu = 0;
199}
200
201void
202TLB::serialize(CheckpointOut &cp) const
203{
204 SERIALIZE_SCALAR(size);
205 SERIALIZE_SCALAR(nlu);
206
207 for (int i = 0; i < size; i++) {
208 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
209 table[i].serialize(cp);
210 }
211}
212
213void
214TLB::unserialize(CheckpointIn &cp)
215{
216 UNSERIALIZE_SCALAR(size);
217 UNSERIALIZE_SCALAR(nlu);
218
219 for (int i = 0; i < size; i++) {
220 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
221 table[i].unserialize(cp);
222 if (table[i].V0 || table[i].V1) {
223 lookupTable.insert(make_pair(table[i].VPN, i));
224 }
225 }
226}
227
228void
229TLB::regStats()
230{
231 BaseTLB::regStats();
232
233 read_hits
234 .name(name() + ".read_hits")
235 .desc("DTB read hits")
236 ;
237
238 read_misses
239 .name(name() + ".read_misses")
240 .desc("DTB read misses")
241 ;
242
243
244 read_accesses
245 .name(name() + ".read_accesses")
246 .desc("DTB read accesses")
247 ;
248
249 write_hits
250 .name(name() + ".write_hits")
251 .desc("DTB write hits")
252 ;
253
254 write_misses
255 .name(name() + ".write_misses")
256 .desc("DTB write misses")
257 ;
258
259
260 write_accesses
261 .name(name() + ".write_accesses")
262 .desc("DTB write accesses")
263 ;
264
265 hits
266 .name(name() + ".hits")
267 .desc("DTB hits")
268 ;
269
270 misses
271 .name(name() + ".misses")
272 .desc("DTB misses")
273 ;
274
275 accesses
276 .name(name() + ".accesses")
277 .desc("DTB accesses")
278 ;
279
280 hits = read_hits + write_hits;
281 misses = read_misses + write_misses;
282 accesses = read_accesses + write_accesses;
283}
284
285Fault
286TLB::translateInst(const RequestPtr &req, ThreadContext *tc)
287{
45#include "arch/riscv/utility.hh"
46#include "base/inifile.hh"
47#include "base/str.hh"
48#include "base/trace.hh"
49#include "cpu/thread_context.hh"
50#include "debug/RiscvTLB.hh"
51#include "debug/TLB.hh"
52#include "mem/page_table.hh"
53#include "params/RiscvTLB.hh"
54#include "sim/full_system.hh"
55#include "sim/process.hh"
56
57using namespace std;
58using namespace RiscvISA;
59
60///////////////////////////////////////////////////////////////////////
61//
62// RISC-V TLB
63//
64
65TLB::TLB(const Params *p)
66 : BaseTLB(p), size(p->size), nlu(0)
67{
68 table = new PTE[size];
69 memset(table, 0, sizeof(PTE[size]));
70 smallPages = 0;
71}
72
73TLB::~TLB()
74{
75 if (table)
76 delete [] table;
77}
78
79// look up an entry in the TLB
80RiscvISA::PTE *
81TLB::lookup(Addr vpn, uint8_t asn) const
82{
83 // assume not found...
84 PTE *retval = nullptr;
85 PageTable::const_iterator i = lookupTable.find(vpn);
86 if (i != lookupTable.end()) {
87 while (i->first == vpn) {
88 int index = i->second;
89 PTE *pte = &table[index];
90
91 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
92 Addr Mask = pte->Mask;
93 Addr InvMask = ~Mask;
94 Addr VPN = pte->VPN;
95 if (((vpn & InvMask) == (VPN & InvMask)) &&
96 (pte->G || (asn == pte->asid))) {
97 // We have a VPN + ASID Match
98 retval = pte;
99 break;
100 }
101 ++i;
102 }
103 }
104
105 DPRINTF(TLB, "lookup %#x, asn %#x -> %s ppn %#x\n", vpn, (int)asn,
106 retval ? "hit" : "miss", retval ? retval->PFN1 : 0);
107 return retval;
108}
109
110RiscvISA::PTE*
111TLB::getEntry(unsigned Index) const
112{
113 // Make sure that Index is valid
114 assert(Index<size);
115 return &table[Index];
116}
117
118int
119TLB::probeEntry(Addr vpn, uint8_t asn) const
120{
121 // assume not found...
122 int Ind = -1;
123 PageTable::const_iterator i = lookupTable.find(vpn);
124 if (i != lookupTable.end()) {
125 while (i->first == vpn) {
126 int index = i->second;
127 PTE *pte = &table[index];
128
129 /* 1KB TLB Lookup code - from MIPS ARM Volume III - Rev. 2.50 */
130 Addr Mask = pte->Mask;
131 Addr InvMask = ~Mask;
132 Addr VPN = pte->VPN;
133 if (((vpn & InvMask) == (VPN & InvMask)) &&
134 (pte->G || (asn == pte->asid))) {
135 // We have a VPN + ASID Match
136 Ind = index;
137 break;
138 }
139 ++i;
140 }
141 }
142 DPRINTF(RiscvTLB,"VPN: %x, asid: %d, Result of TLBP: %d\n",vpn,asn,Ind);
143 return Ind;
144}
145
146inline Fault
147TLB::checkCacheability(const RequestPtr &req)
148{
149 Addr VAddrUncacheable = 0xA0000000;
150 // In MIPS, cacheability is controlled by certain bits of the virtual
151 // address or by the TLB entry
152 if ((req->getVaddr() & VAddrUncacheable) == VAddrUncacheable) {
153 // mark request as uncacheable
154 req->setFlags(Request::UNCACHEABLE | Request::STRICT_ORDER);
155 }
156 return NoFault;
157}
158
159void
160TLB::insertAt(PTE &pte, unsigned Index, int _smallPages)
161{
162 smallPages = _smallPages;
163 if (Index > size) {
164 warn("Attempted to write at index (%d) beyond TLB size (%d)",
165 Index, size);
166 } else {
167 // Update TLB
168 DPRINTF(TLB, "TLB[%d]: %x %x %x %x\n",
169 Index, pte.Mask << 11,
170 ((pte.VPN << 11) | pte.asid),
171 ((pte.PFN0 << 6) | (pte.C0 << 3) |
172 (pte.D0 << 2) | (pte.V0 <<1) | pte.G),
173 ((pte.PFN1 <<6) | (pte.C1 << 3) |
174 (pte.D1 << 2) | (pte.V1 <<1) | pte.G));
175 if (table[Index].V0 || table[Index].V1) {
176 // Previous entry is valid
177 PageTable::iterator i = lookupTable.find(table[Index].VPN);
178 lookupTable.erase(i);
179 }
180 table[Index]=pte;
181 // Update fast lookup table
182 lookupTable.insert(make_pair(table[Index].VPN, Index));
183 }
184}
185
186// insert a new TLB entry
187void
188TLB::insert(Addr addr, PTE &pte)
189{
190 fatal("TLB Insert not yet implemented\n");
191}
192
193void
194TLB::flushAll()
195{
196 DPRINTF(TLB, "flushAll\n");
197 memset(table, 0, sizeof(PTE[size]));
198 lookupTable.clear();
199 nlu = 0;
200}
201
202void
203TLB::serialize(CheckpointOut &cp) const
204{
205 SERIALIZE_SCALAR(size);
206 SERIALIZE_SCALAR(nlu);
207
208 for (int i = 0; i < size; i++) {
209 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
210 table[i].serialize(cp);
211 }
212}
213
214void
215TLB::unserialize(CheckpointIn &cp)
216{
217 UNSERIALIZE_SCALAR(size);
218 UNSERIALIZE_SCALAR(nlu);
219
220 for (int i = 0; i < size; i++) {
221 ScopedCheckpointSection sec(cp, csprintf("PTE%d", i));
222 table[i].unserialize(cp);
223 if (table[i].V0 || table[i].V1) {
224 lookupTable.insert(make_pair(table[i].VPN, i));
225 }
226 }
227}
228
229void
230TLB::regStats()
231{
232 BaseTLB::regStats();
233
234 read_hits
235 .name(name() + ".read_hits")
236 .desc("DTB read hits")
237 ;
238
239 read_misses
240 .name(name() + ".read_misses")
241 .desc("DTB read misses")
242 ;
243
244
245 read_accesses
246 .name(name() + ".read_accesses")
247 .desc("DTB read accesses")
248 ;
249
250 write_hits
251 .name(name() + ".write_hits")
252 .desc("DTB write hits")
253 ;
254
255 write_misses
256 .name(name() + ".write_misses")
257 .desc("DTB write misses")
258 ;
259
260
261 write_accesses
262 .name(name() + ".write_accesses")
263 .desc("DTB write accesses")
264 ;
265
266 hits
267 .name(name() + ".hits")
268 .desc("DTB hits")
269 ;
270
271 misses
272 .name(name() + ".misses")
273 .desc("DTB misses")
274 ;
275
276 accesses
277 .name(name() + ".accesses")
278 .desc("DTB accesses")
279 ;
280
281 hits = read_hits + write_hits;
282 misses = read_misses + write_misses;
283 accesses = read_accesses + write_accesses;
284}
285
286Fault
287TLB::translateInst(const RequestPtr &req, ThreadContext *tc)
288{
288 if (FullSystem)
289 panic("translateInst not implemented in RISC-V.\n");
289 if (FullSystem) {
290 /**
291 * check if we simulate a bare metal system
292 * if so, we have no tlb, phys addr == virt addr
293 */
294 if (static_cast<RiscvSystem *>(tc->getSystemPtr())->isBareMetal())
295 req->setFlags(Request::PHYSICAL);
290
296
291 Process * p = tc->getProcessPtr();
297 if (req->getFlags() & Request::PHYSICAL) {
298 /**
299 * we simply set the virtual address to physical address
300 */
301 req->setPaddr(req->getVaddr());
302 return checkCacheability(req);
303 } else {
304 /**
305 * as we currently support bare metal only, we throw a panic,
306 * if it is not a bare metal system
307 */
308 panic("translateInst not implemented in RISC-V.\n");
309 }
310 } else {
311 Process * p = tc->getProcessPtr();
292
312
293 Fault fault = p->pTable->translate(req);
294 if (fault != NoFault)
295 return fault;
313 Fault fault = p->pTable->translate(req);
314 if (fault != NoFault)
315 return fault;
296
316
297 return NoFault;
317 return NoFault;
318 }
298}
299
300Fault
301TLB::translateData(const RequestPtr &req, ThreadContext *tc, bool write)
302{
319}
320
321Fault
322TLB::translateData(const RequestPtr &req, ThreadContext *tc, bool write)
323{
303 if (FullSystem)
304 panic("translateData not implemented in RISC-V.\n");
324 if (FullSystem) {
325 /**
326 * check if we simulate a bare metal system
327 * if so, we have no tlb, phys addr == virt addr
328 */
329 if (static_cast<RiscvSystem *>(tc->getSystemPtr())->isBareMetal())
330 req->setFlags(Request::PHYSICAL);
305
331
306 // In the O3 CPU model, sometimes a memory access will be speculatively
307 // executed along a branch that will end up not being taken where the
308 // address is invalid. In that case, return a fault rather than trying
309 // to translate it (which will cause a panic). Since RISC-V allows
310 // unaligned memory accesses, this should only happen if the request's
311 // length is long enough to wrap around from the end of the memory to the
312 // start.
313 assert(req->getSize() > 0);
314 if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
315 return make_shared<GenericPageTableFault>(req->getVaddr());
332 if (req->getFlags() & Request::PHYSICAL) {
333 /**
334 * we simply set the virtual address to physical address
335 */
336 req->setPaddr(req->getVaddr());
337 return checkCacheability(req);
338 } else {
339 /**
340 * as we currently support bare metal only, we throw a panic,
341 * if it is not a bare metal system
342 */
343 panic("translateData not implemented in RISC-V.\n");
344 }
345 } else {
346 // In the O3 CPU model, sometimes a memory access will be speculatively
347 // executed along a branch that will end up not being taken where the
348 // address is invalid. In that case, return a fault rather than trying
349 // to translate it (which will cause a panic). Since RISC-V allows
350 // unaligned memory accesses, this should only happen if the request's
351 // length is long enough to wrap around from the end of the memory to
352 // the start.
353 assert(req->getSize() > 0);
354 if (req->getVaddr() + req->getSize() - 1 < req->getVaddr())
355 return make_shared<GenericPageTableFault>(req->getVaddr());
316
356
317 Process * p = tc->getProcessPtr();
357 Process * p = tc->getProcessPtr();
318
358
319 Fault fault = p->pTable->translate(req);
320 if (fault != NoFault)
321 return fault;
359 Fault fault = p->pTable->translate(req);
360 if (fault != NoFault)
361 return fault;
322
362
323 return NoFault;
363 return NoFault;
364 }
324}
325
326Fault
327TLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode)
328{
329 if (mode == Execute)
330 return translateInst(req, tc);
331 else
332 return translateData(req, tc, mode == Write);
333}
334
335void
336TLB::translateTiming(const RequestPtr &req, ThreadContext *tc,
337 Translation *translation, Mode mode)
338{
339 assert(translation);
340 translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
341}
342
343Fault
344TLB::finalizePhysical(const RequestPtr &req,
345 ThreadContext *tc, Mode mode) const
346{
347 return NoFault;
348}
349
350
351RiscvISA::PTE &
352TLB::index(bool advance)
353{
354 PTE *pte = &table[nlu];
355
356 if (advance)
357 nextnlu();
358
359 return *pte;
360}
361
362RiscvISA::TLB *
363RiscvTLBParams::create()
364{
365 return new TLB(this);
366}
365}
366
367Fault
368TLB::translateAtomic(const RequestPtr &req, ThreadContext *tc, Mode mode)
369{
370 if (mode == Execute)
371 return translateInst(req, tc);
372 else
373 return translateData(req, tc, mode == Write);
374}
375
376void
377TLB::translateTiming(const RequestPtr &req, ThreadContext *tc,
378 Translation *translation, Mode mode)
379{
380 assert(translation);
381 translation->finish(translateAtomic(req, tc, mode), req, tc, mode);
382}
383
384Fault
385TLB::finalizePhysical(const RequestPtr &req,
386 ThreadContext *tc, Mode mode) const
387{
388 return NoFault;
389}
390
391
392RiscvISA::PTE &
393TLB::index(bool advance)
394{
395 PTE *pte = &table[nlu];
396
397 if (advance)
398 nextnlu();
399
400 return *pte;
401}
402
403RiscvISA::TLB *
404RiscvTLBParams::create()
405{
406 return new TLB(this);
407}