gem5 v25.0.0.1
Loading...
Searching...
No Matches
tlb.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Advanced Micro Devices, Inc.
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 met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
33
34#include <cmath>
35#include <cstring>
36
40#include "debug/GPUPrefetch.hh"
41#include "debug/GPUTLB.hh"
43
44namespace gem5
45{
46namespace VegaISA
47{
48
49// we have no limit for the number of translations we send
50// downstream as we depend on the limit of the coalescer
51// above us
52GpuTLB::GpuTLB(const VegaGPUTLBParams &p)
54 gpuDevice(p.gpu_device), size(p.size), stats(this),
55 cleanupEvent([this]{ cleanup(); }, name(), false,
57{
58 assoc = p.assoc;
59 assert(assoc <= size);
60 numSets = size/assoc;
61 allocationPolicy = p.allocationPolicy;
62 hasMemSidePort = false;
63
64 tlb.assign(size, VegaTlbEntry());
65
66 freeList.resize(numSets);
67 entryList.resize(numSets);
68
69 for (int set = 0; set < numSets; ++set) {
70 for (int way = 0; way < assoc; ++way) {
71 int x = set * assoc + way;
72 freeList[set].push_back(&tlb.at(x));
73 }
74 }
75
76 FA = (size == assoc);
77 setMask = numSets - 1;
78
79 maxCoalescedReqs = p.maxOutstandingReqs;
80
81
82 outstandingReqs = 0;
83 hitLatency = p.hitLatency;
84 missLatency1 = p.missLatency1;
85 missLatency2 = p.missLatency2;
86
87 // create the response ports based on the number of connected ports
88 for (size_t i = 0; i < p.port_cpu_side_ports_connection_count; ++i) {
89 cpuSidePort.push_back(new CpuSidePort(csprintf("%s-port%d",
90 name(), i), this, i));
91 }
92
93 // create the requestor ports based on the number of connected ports
94 for (size_t i = 0; i < p.port_mem_side_ports_connection_count; ++i) {
95 memSidePort.push_back(new MemSidePort(csprintf("%s-port%d",
96 name(), i), this, i));
97 }
98
99 // assuming one walker per TLB, set our walker's TLB to this TLB.
100 walker->setTLB(this);
101
102 // gpuDevice should be non-null in full system only and is set by GpuTLB
103 // params from the config file.
104 if (gpuDevice) {
105 gpuDevice->getVM().registerTLB(this);
106 }
107}
108
110{
111}
112
113Port &
114GpuTLB::getPort(const std::string &if_name, PortID idx)
115{
116 if (if_name == "cpu_side_ports") {
117 if (idx >= static_cast<PortID>(cpuSidePort.size())) {
118 panic("TLBCoalescer::getPort: unknown index %d\n", idx);
119 }
120
121 return *cpuSidePort[idx];
122 } else if (if_name == "mem_side_ports") {
123 if (idx >= static_cast<PortID>(memSidePort.size())) {
124 panic("TLBCoalescer::getPort: unknown index %d\n", idx);
125 }
126
127 hasMemSidePort = true;
128
129 return *memSidePort[idx];
130 } else {
131 panic("TLBCoalescer::getPort: unknown port %s\n", if_name);
132 }
133}
134
135Fault
137{
138 DPRINTF(GPUTLB, "GPUTLB: Raising page fault.\n");
139 ExceptionCode code;
140 if (mode == BaseMMU::Read)
142 else if (mode == BaseMMU::Write)
144 else
146 return std::make_shared<PageFault>(vaddr, code, true, mode, true);
147}
148
149Addr
151{
152 Addr pageMask = mask(VegaISA::PageShift);
153 return (vaddr & ~pageMask);
154}
155
156VegaTlbEntry*
157GpuTLB::insert(Addr vpn, VegaTlbEntry &entry)
158{
159 VegaTlbEntry *newEntry = nullptr;
160
161 int set = (entry.vaddr >> VegaISA::PageShift) & setMask;
162
163 if (!freeList[set].empty()) {
164 newEntry = freeList[set].front();
165 freeList[set].pop_front();
166 } else {
167 newEntry = entryList[set].back();
168 entryList[set].pop_back();
169 }
170
171 *newEntry = entry;
172 entryList[set].push_front(newEntry);
173
174 DPRINTF(GPUTLB, "Inserted %#lx -> %#lx of size %#lx into set %d\n",
175 newEntry->vaddr, newEntry->paddr, entry.size(), set);
176
177 return newEntry;
178}
179
180GpuTLB::EntryList::iterator
181GpuTLB::lookupIt(Addr va, bool update_lru)
182{
183 int set = (va >> VegaISA::PageShift) & setMask;
184
185 if (FA) {
186 assert(!set);
187 }
188
189 auto entry = entryList[set].begin();
190 for (; entry != entryList[set].end(); ++entry) {
191 int page_size = (*entry)->size();
192
193 if ((*entry)->vaddr <= va && (*entry)->vaddr + page_size > va) {
194 DPRINTF(GPUTLB, "Matched vaddr %#x to entry starting at %#x "
195 "with size %#x.\n", va, (*entry)->vaddr, page_size);
196
197 if (update_lru) {
198 entryList[set].push_front(*entry);
199 entryList[set].erase(entry);
200 entry = entryList[set].begin();
201 }
202
203 break;
204 }
205 }
206
207 return entry;
208}
209
210VegaTlbEntry*
211GpuTLB::lookup(Addr va, bool update_lru)
212{
213 int set = (va >> VegaISA::PageShift) & setMask;
214
215 auto entry = lookupIt(va, update_lru);
216
217 if (entry == entryList[set].end())
218 return nullptr;
219 else
220 return *entry;
221}
222
223void
225{
226 DPRINTF(GPUTLB, "Invalidating all entries.\n");
227
228 for (int i = 0; i < numSets; ++i) {
229 while (!entryList[i].empty()) {
230 VegaTlbEntry *entry = entryList[i].front();
231 entryList[i].pop_front();
232 freeList[i].push_back(entry);
233 }
234 }
235}
236
237void
239{
240
241 int set = (va >> VegaISA::PageShift) & setMask;
242 auto entry = lookupIt(va, false);
243
244 if (entry != entryList[set].end()) {
245 freeList[set].push_back(*entry);
246 entryList[set].erase(entry);
247 }
248}
249
250
251
259VegaTlbEntry *
260GpuTLB::tlbLookup(const RequestPtr &req, bool update_stats)
261{
262 if (req->hasNoAddr()) {
263 return NULL;
264 }
265 Addr vaddr = req->getVaddr();
266 Addr alignedVaddr = pageAlign(vaddr);
267 DPRINTF(GPUTLB, "TLB Lookup for vaddr %#x.\n", vaddr);
268
269 //update LRU stack on a hit
270 VegaTlbEntry *entry = lookup(alignedVaddr, true);
271
272 if (!update_stats) {
273 // functional tlb access for memory initialization
274 // i.e., memory seeding or instr. seeding -> don't update
275 // TLB and stats
276 return entry;
277 }
278
279 stats.localNumTLBAccesses++;
280
281 if (!entry) {
282 stats.localNumTLBMisses++;
283 } else {
284 stats.localNumTLBHits++;
285 }
286
287 return entry;
288}
289
290Walker*
292{
293 return walker;
294}
295
296
297void
301
302void
306
311
312void
314{
315 assert(pkt);
316 assert(pkt->senderState);
317
324 Addr virt_page_addr = roundDown(pkt->req->getVaddr(),
326
327 GpuTranslationState *sender_state =
329
330 bool update_stats = !sender_state->isPrefetch;
331
332 DPRINTF(GPUTLB, "Translation req. for virt. page addr %#x\n",
333 virt_page_addr);
334
335 int req_cnt = sender_state->reqCnt.back();
336
337 if (update_stats) {
338 stats.accessCycles -= (curCycle() * req_cnt);
339 stats.localCycles -= curCycle();
340 stats.globalNumTLBAccesses += req_cnt;
341 }
342
343 tlbOutcome lookup_outcome = TLB_MISS;
344 const RequestPtr &tmp_req = pkt->req;
345
346 // Access the TLB and figure out if it's a hit or a miss.
347 auto entry = tlbLookup(tmp_req, update_stats);
348 if (entry || pkt->req->hasNoAddr()) {
349 // Put the entry in SenderState
350 lookup_outcome = TLB_HIT;
351 if (pkt->req->hasNoAddr()) {
352 sender_state->tlbEntry =
353 new VegaTlbEntry(1 /* VMID */, 0, 0, 0, 0);
354 // set false because we shouldn't go to
355 // host memory for a memtime request
356 pkt->req->setSystemReq(false);
357 } else {
358 VegaTlbEntry *entry = lookup(virt_page_addr, false);
359 assert(entry);
360
361 // Set if this is a system request
362 pkt->req->setSystemReq(entry->pte.s);
363
364 sender_state->tlbEntry =
365 new VegaTlbEntry(*entry);
366 }
367
368 if (update_stats) {
369 // the reqCnt has an entry per level, so its size tells us
370 // which level we are in
371 sender_state->hitLevel = sender_state->reqCnt.size();
372 stats.globalNumTLBHits += req_cnt;
373 }
374 } else {
375 if (update_stats)
376 stats.globalNumTLBMisses += req_cnt;
377 }
378
379 /*
380 * We now know the TLB lookup outcome (if it's a hit or a miss), as
381 * well as the TLB access latency.
382 *
383 * We create and schedule a new TLBEvent which will help us take the
384 * appropriate actions (e.g., update TLB on a hit, send request to
385 * lower level TLB on a miss, or start a page walk if this was the
386 * last-level TLB)
387 */
388 TLBEvent *tlb_event =
389 new TLBEvent(this, virt_page_addr, lookup_outcome, pkt);
390
391 if (translationReturnEvent.count(virt_page_addr)) {
392 panic("Virtual Page Address %#x already has a return event\n",
393 virt_page_addr);
394 }
395
396 translationReturnEvent[virt_page_addr] = tlb_event;
397 assert(tlb_event);
398
399 DPRINTF(GPUTLB, "schedule translationReturnEvent @ curTick %d\n",
401
403}
404
406 tlbOutcome tlb_outcome, PacketPtr _pkt)
407 : Event(CPU_Tick_Pri), tlb(_tlb), virtPageAddr(_addr),
408 outcome(tlb_outcome), pkt(_pkt)
409{
410}
411
416void
417GpuTLB::pagingProtectionChecks(PacketPtr pkt, VegaTlbEntry * tlb_entry,
418 Mode mode)
419{
420 // Do paging protection checks.
421 bool badWrite = (!tlb_entry->writable());
422
423 if (mode == BaseMMU::Write && badWrite) {
424 // The page must have been present to get into the TLB in
425 // the first place. We'll assume the reserved bits are
426 // fine even though we're not checking them.
427 fatal("Page fault on addr %lx PTE=%#lx", pkt->req->getVaddr(),
428 (uint64_t)tlb_entry->pte);
429 }
430}
431
432void
433GpuTLB::walkerResponse(VegaTlbEntry& entry, PacketPtr pkt)
434{
435 DPRINTF(GPUTLB, "WalkerResponse for %#lx. Entry: (%#lx, %#lx, %#lx)\n",
436 pkt->req->getVaddr(), entry.vaddr, entry.paddr, entry.size());
437
438 Addr virt_page_addr = roundDown(pkt->req->getVaddr(),
440
441 Addr page_addr = entry.pte.ppn << VegaISA::PageShift;
442 Addr paddr = page_addr + (entry.vaddr & mask(entry.logBytes));
443 pkt->req->setPaddr(paddr);
444 pkt->req->setSystemReq(entry.pte.s);
445
446 GpuTranslationState *sender_state =
448 sender_state->tlbEntry = new VegaTlbEntry(entry);
449
450 handleTranslationReturn(virt_page_addr, TLB_MISS, pkt);
451}
452
458void
460 tlbOutcome tlb_outcome, PacketPtr pkt)
461{
462 assert(pkt);
463 Addr vaddr = pkt->req->getVaddr();
464
465 GpuTranslationState *sender_state =
467
468 Mode mode = sender_state->tlbMode;
469
470 VegaTlbEntry *local_entry, *new_entry;
471
472 int req_cnt = sender_state->reqCnt.back();
473 bool update_stats = !sender_state->isPrefetch;
474
475 if (update_stats) {
476 stats.accessCycles += (req_cnt * curCycle());
477 stats.localCycles += curCycle();
478 }
479
480 if (tlb_outcome == TLB_HIT) {
481 DPRINTF(GPUTLB, "Translation Done - TLB Hit for addr %#x\n",
482 vaddr);
483 local_entry = safe_cast<VegaTlbEntry *>(sender_state->tlbEntry);
484 } else {
485 DPRINTF(GPUTLB, "Translation Done - TLB Miss for addr %#x\n",
486 vaddr);
487
493 new_entry = safe_cast<VegaTlbEntry *>(sender_state->tlbEntry);
494 assert(new_entry);
495 local_entry = new_entry;
496
497 if (allocationPolicy) {
498 assert(new_entry->pte);
499 DPRINTF(GPUTLB, "allocating entry w/ addr %#lx of size %#lx\n",
500 virt_page_addr, new_entry->size());
501
502 local_entry = insert(virt_page_addr, *new_entry);
503 }
504
505 assert(local_entry);
506 }
507
513 DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks "
514 "while paddr was %#x.\n", local_entry->vaddr,
515 local_entry->paddr);
516
517 pagingProtectionChecks(pkt, local_entry, mode);
518 int page_size = local_entry->size();
519 Addr paddr = local_entry->paddr + (vaddr & (page_size - 1));
520 DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr);
521
522 // Since this packet will be sent through the cpu side port, it must be
523 // converted to a response pkt if it is not one already
524 if (pkt->isRequest()) {
525 pkt->makeTimingResponse();
526 }
527
528 pkt->req->setPaddr(paddr);
529
530 if (local_entry->uncacheable()) {
531 pkt->req->setFlags(Request::UNCACHEABLE);
532 }
533
534 //send packet back to coalescer
535 cpuSidePort[0]->sendTimingResp(pkt);
536 //schedule cleanup event
537 cleanupQueue.push(virt_page_addr);
538
539 DPRINTF(GPUTLB, "Scheduled %#lx for cleanup\n", virt_page_addr);
540
541 // schedule this only once per cycle.
542 // The check is required because we might have multiple translations
543 // returning the same cycle
544 // this is a maximum priority event and must be on the same cycle
545 // as the cleanup event in TLBCoalescer to avoid a race with
546 // IssueProbeEvent caused by TLBCoalescer::MemSidePort::recvReqRetry
547 if (!cleanupEvent.scheduled())
549}
550
555void
557 PacketPtr pkt)
558{
559 DPRINTF(GPUTLB, "Triggered TLBEvent for addr %#x\n", virtPageAddr);
560
561 assert(translationReturnEvent[virtPageAddr]);
562 assert(pkt);
563
564 GpuTranslationState *tmp_sender_state =
566
567 int req_cnt = tmp_sender_state->reqCnt.back();
568 bool update_stats = !tmp_sender_state->isPrefetch;
569
570
571 if (outcome == TLB_HIT) {
572 handleTranslationReturn(virtPageAddr, TLB_HIT, pkt);
573
574 } else if (outcome == TLB_MISS) {
575
576 DPRINTF(GPUTLB, "This is a TLB miss\n");
577 if (hasMemSidePort) {
578 // the one cyle added here represent the delay from when we get
579 // the reply back till when we propagate it to the coalescer
580 // above.
581
587 tmp_sender_state->deviceId = 1;
588 tmp_sender_state->pasId = 0;
589
590 if (!memSidePort[0]->sendTimingReq(pkt)) {
591 DPRINTF(GPUTLB, "Failed sending translation request to "
592 "lower level TLB for addr %#x\n", virtPageAddr);
593
594 memSidePort[0]->retries.push_back(pkt);
595 } else {
596 DPRINTF(GPUTLB, "Sent translation request to lower level "
597 "TLB for addr %#x\n", virtPageAddr);
598 }
599 } else {
600 //this is the last level TLB. Start a page walk
601 DPRINTF(GPUTLB, "Last level TLB - start a page walk for "
602 "addr %#x\n", virtPageAddr);
603
604 if (update_stats)
605 stats.pageTableCycles -= (req_cnt*curCycle());
606
607 TLBEvent *tlb_event = translationReturnEvent[virtPageAddr];
608 assert(tlb_event);
609 tlb_event->updateOutcome(PAGE_WALK);
610 schedule(tlb_event,
612 }
613 } else if (outcome == PAGE_WALK) {
614 if (update_stats)
615 stats.pageTableCycles += (req_cnt*curCycle());
616
617 // Need to access the page table and update the TLB
618 DPRINTF(GPUTLB, "Doing a page walk for address %#x\n",
619 virtPageAddr);
620
621 Addr base = gpuDevice->getVM().getPageTableBase(1);
622 Addr vaddr = pkt->req->getVaddr();
623 walker->setDevRequestor(gpuDevice->vramRequestorId());
624
625 // Do page table walk
626 walker->startTiming(pkt, base, vaddr, BaseMMU::Mode::Read);
627 } else if (outcome == MISS_RETURN) {
631 handleTranslationReturn(virtPageAddr, TLB_MISS, pkt);
632 } else {
633 panic("Unexpected TLB outcome %d", outcome);
634 }
635}
636
637void
639{
640 tlb->translationReturn(virtPageAddr, outcome, pkt);
641}
642
643const char*
645{
646 return "trigger translationDoneEvent";
647}
648
649void
651{
652 outcome = _outcome;
653}
654
655Addr
660
667bool
669{
670 bool ret = false;
671 [[maybe_unused]] Addr virt_page_addr = roundDown(pkt->req->getVaddr(),
673
674 if (tlb->outstandingReqs < tlb->maxCoalescedReqs) {
675 assert(!tlb->translationReturnEvent.count(virt_page_addr));
676 tlb->issueTLBLookup(pkt);
677 // update number of outstanding translation requests
678 tlb->outstandingReqs++;
679 ret = true;
680 } else {
681 DPRINTF(GPUTLB, "Reached maxCoalescedReqs number %d\n",
682 tlb->outstandingReqs);
683 tlb->stats.maxDownstreamReached++;
684 ret = false;
685
686 }
687
688 if (tlb->outstandingReqs > tlb->stats.outstandingReqsMax.value())
689 tlb->stats.outstandingReqsMax = tlb->outstandingReqs;
690
691 return ret;
692}
693
702void
704{
705 GpuTranslationState *sender_state =
707
708 Mode mode = sender_state->tlbMode;
709 Addr vaddr = pkt->req->getVaddr();
710
711 VegaTlbEntry *local_entry, *new_entry;
712
713 if (tlb_outcome == TLB_HIT) {
714 DPRINTF(GPUTLB, "Functional Translation Done - TLB hit for addr "
715 "%#x\n", vaddr);
716
717 local_entry = safe_cast<VegaTlbEntry *>(sender_state->tlbEntry);
718 } else {
719 DPRINTF(GPUTLB, "Functional Translation Done - TLB miss for addr "
720 "%#x\n", vaddr);
721
727 new_entry = safe_cast<VegaTlbEntry *>(sender_state->tlbEntry);
728 assert(new_entry);
729 local_entry = new_entry;
730
731 if (allocationPolicy) {
732 Addr virt_page_addr = roundDown(vaddr, VegaISA::PageBytes);
733
734 DPRINTF(GPUTLB, "allocating entry w/ addr %#lx\n",
735 virt_page_addr);
736
737 local_entry = insert(virt_page_addr, *new_entry);
738 }
739
740 assert(local_entry);
741 }
742
743 DPRINTF(GPUTLB, "Entry found with vaddr %#x, doing protection checks "
744 "while paddr was %#x.\n", local_entry->vaddr,
745 local_entry->paddr);
746
758 if (!sender_state->isPrefetch && sender_state->tlbEntry)
759 pagingProtectionChecks(pkt, local_entry, mode);
760
761 int page_size = local_entry->size();
762 Addr paddr = local_entry->paddr + (vaddr & (page_size - 1));
763 DPRINTF(GPUTLB, "Translated %#x -> %#x.\n", vaddr, paddr);
764
765 pkt->req->setPaddr(paddr);
766
767 if (local_entry->uncacheable())
768 pkt->req->setFlags(Request::UNCACHEABLE);
769}
770
771// This is used for atomic translations. Need to
772// make it all happen during the same cycle.
773void
775{
776 GpuTranslationState *sender_state =
778
779 bool update_stats = !sender_state->isPrefetch;
780
781 Addr virt_page_addr = roundDown(pkt->req->getVaddr(),
783
784 // do the TLB lookup without updating the stats
785 bool success = tlb->tlbLookup(pkt->req, update_stats);
786 tlbOutcome tlb_outcome = success ? TLB_HIT : TLB_MISS;
787
788 // functional mode means no coalescing
789 // global metrics are the same as the local metrics
790 if (update_stats) {
791 tlb->stats.globalNumTLBAccesses++;
792
793 if (success) {
794 sender_state->hitLevel = sender_state->reqCnt.size();
795 tlb->stats.globalNumTLBHits++;
796 } else {
797 tlb->stats.globalNumTLBMisses++;
798 }
799 }
800
801 if (!success) {
802 if (tlb->hasMemSidePort) {
803 // there is a TLB below -> propagate down the TLB hierarchy
804 tlb->memSidePort[0]->sendFunctional(pkt);
805 // If no valid translation from a prefetch, then just return
806 if (sender_state->isPrefetch && !pkt->req->hasPaddr())
807 return;
808 } else {
809 // Need to access the page table and update the TLB
810 DPRINTF(GPUTLB, "Doing a page walk for address %#x\n",
811 virt_page_addr);
812
813 Addr vaddr = pkt->req->getVaddr();
814 [[maybe_unused]] Addr alignedVaddr =
815 tlb->pageAlign(virt_page_addr);
816 assert(alignedVaddr == virt_page_addr);
817
818 unsigned logBytes;
819 PageTableEntry pte;
820
821 // Initialize walker state for VMID
822 Addr base = tlb->gpuDevice->getVM().getPageTableBase(1);
823 tlb->walker->setDevRequestor(tlb->gpuDevice->vramRequestorId());
824
825 // Do page table walk
826 Fault fault = tlb->walker->startFunctional(base, vaddr, pte,
827 logBytes,
829 if (fault != NoFault) {
830 fatal("Translation fault in TLB at %d!", __LINE__);
831 }
832
833 // PPN is already shifted by fragment so we only shift by native
834 // page size. Fragment is still used via logBytes to select lower
835 // bits from vaddr.
836 Addr page_addr = pte.ppn << PageShift;
837 Addr paddr = page_addr + (vaddr & mask(logBytes));
838 Addr alignedPaddr = tlb->pageAlign(paddr);
839 pkt->req->setPaddr(paddr);
840 pkt->req->setSystemReq(pte.s);
841
842 if (!sender_state->isPrefetch) {
843 assert(paddr);
844
845 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", vaddr, paddr);
846
847 sender_state->tlbEntry =
848 new VegaTlbEntry(1 /* VMID */, vaddr & (~mask(logBytes)),
849 alignedPaddr, logBytes, pte);
850 } else {
851 // If this was a prefetch, then do the normal thing if it
852 // was a successful translation. Otherwise, send an empty
853 // TLB entry back so that it can be figured out as empty
854 // and handled accordingly.
855 if (paddr) {
856 DPRINTF(GPUTLB, "Mapping %#x to %#x\n", vaddr, paddr);
857
858 sender_state->tlbEntry =
859 new VegaTlbEntry(1 /* VMID */,
860 vaddr & (~mask(logBytes)),
861 alignedPaddr, logBytes, pte);
862 } else {
863 DPRINTF(GPUPrefetch, "Prefetch failed %#x\n", vaddr);
864
865 sender_state->tlbEntry = nullptr;
866
867 return;
868 }
869 }
870 }
871 } else {
872 VegaTlbEntry *entry = tlb->lookup(virt_page_addr, update_stats);
873 assert(entry);
874
875 if (sender_state->isPrefetch) {
876 DPRINTF(GPUPrefetch, "Functional Hit for vaddr %#x\n",
877 entry->vaddr);
878 }
879
880 sender_state->tlbEntry = new VegaTlbEntry(*entry);
881 }
882
883 // This is the function that would populate pkt->req with the paddr of
884 // the translation. But if no translation happens (i.e Prefetch fails)
885 // then the early returns in the above code wiill keep this function
886 // from executing.
887 tlb->handleFuncTranslationReturn(pkt, tlb_outcome);
888}
889
890void
892{
893 // The CPUSidePort never sends anything but replies. No retries
894 // expected.
895 panic("recvReqRetry called");
896}
897
900{
901 // currently not checked by the requestor
902 AddrRangeList ranges;
903
904 return ranges;
905}
906
912bool
914{
915 Addr virt_page_addr = roundDown(pkt->req->getVaddr(),
917
918 DPRINTF(GPUTLB, "MemSidePort recvTiming for virt_page_addr %#x\n",
919 virt_page_addr);
920
921 TLBEvent *tlb_event = tlb->translationReturnEvent[virt_page_addr];
922 assert(tlb_event);
923 assert(virt_page_addr == tlb_event->getTLBEventVaddr());
924
925 tlb_event->updateOutcome(MISS_RETURN);
926 tlb->schedule(tlb_event, curTick()+tlb->clockPeriod());
927
928 return true;
929}
930
931void
933{
934 // No retries should reach the TLB. The retries
935 // should only reach the TLBCoalescer.
936 panic("recvReqRetry called");
937}
938
939void
941{
942 while (!cleanupQueue.empty()) {
943 Addr cleanup_addr = cleanupQueue.front();
944 cleanupQueue.pop();
945
946 DPRINTF(GPUTLB, "Deleting return event for %#lx\n", cleanup_addr);
947
948 // delete TLBEvent
949 TLBEvent * old_tlb_event = translationReturnEvent[cleanup_addr];
950 delete old_tlb_event;
951 translationReturnEvent.erase(cleanup_addr);
952
953 // update number of outstanding requests
955 }
956
960 for (int i = 0; i < cpuSidePort.size(); ++i) {
961 cpuSidePort[i]->sendRetryReq();
962 }
963}
964
966 : statistics::Group(parent),
967 ADD_STAT(maxDownstreamReached, "Number of refused translation requests"),
968 ADD_STAT(outstandingReqsMax, "Maximum count in coalesced request queue"),
969 ADD_STAT(localNumTLBAccesses, "Number of TLB accesses"),
970 ADD_STAT(localNumTLBHits, "Number of TLB hits"),
971 ADD_STAT(localNumTLBMisses, "Number of TLB misses"),
972 ADD_STAT(localTLBMissRate, "TLB miss rate"),
973 ADD_STAT(globalNumTLBAccesses, "Number of TLB accesses"),
974 ADD_STAT(globalNumTLBHits, "Number of TLB hits"),
975 ADD_STAT(globalNumTLBMisses, "Number of TLB misses"),
976 ADD_STAT(globalTLBMissRate, "TLB miss rate"),
977 ADD_STAT(accessCycles, "Cycles spent accessing this TLB level"),
978 ADD_STAT(pageTableCycles, "Cycles spent accessing the page table"),
979 ADD_STAT(localCycles, "Number of cycles spent in queue for all "
980 "incoming reqs"),
981 ADD_STAT(localLatency, "Avg. latency over incoming coalesced reqs")
982{
985
987}
988
989} // namespace VegaISA
990} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
ClockedObject(const ClockedObjectParams &p)
Cycles curCycle() const
Determine the current cycle, corresponding to a tick aligned to a clock edge.
Tick cyclesToTicks(Cycles c) const
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
Event(Priority p=Default_Pri, Flags f=0)
Definition eventq.hh:407
void makeTimingResponse()
Definition packet.hh:1080
SenderState * senderState
This packet's sender state.
Definition packet.hh:545
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
bool isRequest() const
Definition packet.hh:597
Ports are used to interface objects to each other.
Definition port.hh:62
@ UNCACHEABLE
The request is to an uncacheable address.
Definition request.hh:125
virtual bool recvTimingReq(PacketPtr pkt)
recvTiming receives a coalesced timing request from a TLBCoalescer and it calls issueTLBLookup() It o...
Definition tlb.cc:668
virtual AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
Definition tlb.cc:899
virtual void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
Definition tlb.cc:774
virtual bool recvTimingResp(PacketPtr pkt)
MemSidePort receives the packet back.
Definition tlb.cc:913
virtual void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition tlb.cc:932
const char * description() const
Return a C string describing the event.
Definition tlb.cc:644
void updateOutcome(tlbOutcome _outcome)
Definition tlb.cc:650
tlbOutcome outcome
outcome can be TLB_HIT, TLB_MISS, or PAGE_WALK
Definition tlb.hh:295
TLBEvent(GpuTLB *_tlb, Addr _addr, tlbOutcome outcome, PacketPtr _pkt)
Definition tlb.cc:405
VegaTlbEntry * lookup(Addr va, bool update_lru=true)
Definition tlb.cc:211
EntryList::iterator lookupIt(Addr va, bool update_lru=true)
Definition tlb.cc:181
void walkerResponse(VegaTlbEntry &entry, PacketPtr pkt)
Definition tlb.cc:433
std::vector< CpuSidePort * > cpuSidePort
Definition tlb.hh:261
virtual void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition tlb.cc:298
virtual void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition tlb.cc:303
void issueTLBLookup(PacketPtr pkt)
Do the TLB lookup for this coalesced request and schedule another event <TLB access latency> cycles l...
Definition tlb.cc:313
VegaTlbEntry * insert(Addr vpn, VegaTlbEntry &entry)
Definition tlb.cc:157
void translationReturn(Addr virtPageAddr, tlbOutcome outcome, PacketPtr pkt)
A TLBEvent is scheduled after the TLB lookup and helps us take the appropriate actions: (e....
Definition tlb.cc:556
void pagingProtectionChecks(PacketPtr pkt, VegaTlbEntry *tlb_entry, Mode mode)
Do Paging protection checks.
Definition tlb.cc:417
void handleFuncTranslationReturn(PacketPtr pkt, tlbOutcome outcome)
handleFuncTranslationReturn is called on a TLB hit, when a TLB miss returns or when a page fault retu...
Definition tlb.cc:703
enum BaseMMU::Mode Mode
Definition tlb.hh:68
std::unordered_map< Addr, TLBEvent * > translationReturnEvent
Definition tlb.hh:310
std::vector< MemSidePort * > memSidePort
Definition tlb.hh:263
Walker * getWalker()
Definition tlb.cc:291
std::vector< EntryList > freeList
Definition tlb.hh:140
void invalidateAll()
Definition tlb.cc:224
Walker * walker
Definition tlb.hh:109
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition tlb.cc:114
AMDGPUDevice * gpuDevice
Definition tlb.hh:110
Addr pageAlign(Addr vaddr)
Definition tlb.cc:150
void handleTranslationReturn(Addr addr, tlbOutcome outcome, PacketPtr pkt)
handleTranslationReturn is called on a TLB hit, when a TLB miss returns or when a page fault returns.
Definition tlb.cc:459
std::queue< Addr > cleanupQueue
Definition tlb.hh:314
bool FA
true if this is a fully-associative TLB
Definition tlb.hh:119
bool allocationPolicy
Allocation Policy: true if we always allocate on a hit, false otherwise.
Definition tlb.hh:126
EventFunctionWrapper cleanupEvent
Definition tlb.hh:320
gem5::VegaISA::GpuTLB::VegaTLBStats stats
VegaTlbEntry * tlbLookup(const RequestPtr &req, bool update_stats)
TLB_lookup will only perform a TLB lookup returning the TLB entry on a TLB hit and nullptr on a TLB m...
Definition tlb.cc:260
std::vector< EntryList > entryList
An entryList per set is the equivalent of an LRU stack; it's used to guide replacement decisions.
Definition tlb.hh:149
void demapPage(Addr va, uint64_t asn)
Definition tlb.cc:238
GpuTLB(const VegaGPUTLBParams &p)
Definition tlb.cc:52
Fault createPagefault(Addr vaddr, Mode mode)
Definition tlb.cc:136
bool hasMemSidePort
if true, then this is not the last level TLB
Definition tlb.hh:131
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition addr_range.hh:64
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
Definition intmath.hh:279
static const Priority Maximum_Pri
Maximum priority.
Definition eventq.hh:244
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
Definition eventq.hh:207
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
Bitfield< 8 > va
Bitfield< 59, 56 > tlb
classes that represnt vector/scalar operands in VEGA ISA.
Definition faults.cc:39
Bitfield< 4 > x
Definition pagetable.hh:61
const Addr PageShift
Definition page_size.hh:41
const Addr PageBytes
Definition page_size.hh:42
Bitfield< 54 > p
Definition pagetable.hh:70
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
T safe_cast(U &&ref_or_ptr)
Definition cast.hh:74
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
Packet * PacketPtr
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
constexpr decltype(nullptr) NoFault
Definition types.hh:253
GPU TranslationState: this currently is a somewhat bastardization of the usage of SenderState,...
statistics::Scalar outstandingReqsMax
Definition tlb.hh:162
statistics::Scalar localNumTLBMisses
Definition tlb.hh:168
statistics::Formula localLatency
Definition tlb.hh:185
statistics::Formula localTLBMissRate
Definition tlb.hh:169
statistics::Scalar localCycles
Definition tlb.hh:184
statistics::Scalar globalNumTLBAccesses
Definition tlb.hh:174
statistics::Scalar accessCycles
Definition tlb.hh:180
statistics::Scalar localNumTLBAccesses
Definition tlb.hh:166
VegaTLBStats(statistics::Group *parent)
Definition tlb.cc:965
statistics::Formula globalTLBMissRate
Definition tlb.hh:177
statistics::Scalar globalNumTLBMisses
Definition tlb.hh:176
statistics::Scalar localNumTLBHits
Definition tlb.hh:167
statistics::Scalar pageTableCycles
Definition tlb.hh:181
statistics::Scalar globalNumTLBHits
Definition tlb.hh:175
statistics::Scalar maxDownstreamReached
Definition tlb.hh:161
const std::string & name()
Definition trace.cc:48

Generated on Sat Oct 18 2025 08:06:40 for gem5 by doxygen 1.14.0