40#include "debug/GPUPrefetch.hh"
41#include "debug/GPUTLB.hh"
59 assert(assoc <= size);
61 allocationPolicy =
p.allocationPolicy;
62 hasMemSidePort =
false;
64 tlb.assign(size, VegaTlbEntry());
66 freeList.resize(numSets);
67 entryList.resize(numSets);
70 for (
int way = 0; way < assoc; ++way) {
71 int x =
set * assoc + way;
72 freeList[
set].push_back(&
tlb.at(
x));
77 setMask = numSets - 1;
79 maxCoalescedReqs =
p.maxOutstandingReqs;
83 hitLatency =
p.hitLatency;
84 missLatency1 =
p.missLatency1;
85 missLatency2 =
p.missLatency2;
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",
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",
100 walker->setTLB(
this);
105 gpuDevice->getVM().registerTLB(
this);
116 if (if_name ==
"cpu_side_ports") {
118 panic(
"TLBCoalescer::getPort: unknown index %d\n", idx);
122 }
else if (if_name ==
"mem_side_ports") {
124 panic(
"TLBCoalescer::getPort: unknown index %d\n", idx);
131 panic(
"TLBCoalescer::getPort: unknown port %s\n", if_name);
138 DPRINTF(GPUTLB,
"GPUTLB: Raising page fault.\n");
146 return std::make_shared<PageFault>(
vaddr, code,
true,
mode,
true);
153 return (
vaddr & ~pageMask);
159 VegaTlbEntry *newEntry =
nullptr;
174 DPRINTF(GPUTLB,
"Inserted %#lx -> %#lx of size %#lx into set %d\n",
175 newEntry->vaddr, newEntry->paddr, entry.size(),
set);
180GpuTLB::EntryList::iterator
191 int page_size = (*entry)->size();
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);
226 DPRINTF(GPUTLB,
"Invalidating all entries.\n");
262 if (req->hasNoAddr()) {
270 VegaTlbEntry *entry =
lookup(alignedVaddr,
true);
279 stats.localNumTLBAccesses++;
282 stats.localNumTLBMisses++;
284 stats.localNumTLBHits++;
330 bool update_stats = !sender_state->
isPrefetch;
332 DPRINTF(GPUTLB,
"Translation req. for virt. page addr %#x\n",
335 int req_cnt = sender_state->
reqCnt.back();
340 stats.globalNumTLBAccesses += req_cnt;
347 auto entry =
tlbLookup(tmp_req, update_stats);
348 if (entry || pkt->
req->hasNoAddr()) {
351 if (pkt->
req->hasNoAddr()) {
353 new VegaTlbEntry(1 , 0, 0, 0, 0);
356 pkt->
req->setSystemReq(
false);
358 VegaTlbEntry *entry =
lookup(virt_page_addr,
false);
362 pkt->
req->setSystemReq(entry->pte.s);
365 new VegaTlbEntry(*entry);
372 stats.globalNumTLBHits += req_cnt;
376 stats.globalNumTLBMisses += req_cnt;
389 new TLBEvent(
this, virt_page_addr, lookup_outcome, pkt);
392 panic(
"Virtual Page Address %#x already has a return event\n",
399 DPRINTF(GPUTLB,
"schedule translationReturnEvent @ curTick %d\n",
421 bool badWrite = (!tlb_entry->writable());
427 fatal(
"Page fault on addr %lx PTE=%#lx", pkt->
req->getVaddr(),
428 (uint64_t)tlb_entry->pte);
435 DPRINTF(GPUTLB,
"WalkerResponse for %#lx. Entry: (%#lx, %#lx, %#lx)\n",
436 pkt->
req->getVaddr(), entry.vaddr, entry.paddr, entry.size());
442 Addr paddr = page_addr + (entry.vaddr &
mask(entry.logBytes));
443 pkt->
req->setPaddr(paddr);
444 pkt->
req->setSystemReq(entry.pte.s);
448 sender_state->
tlbEntry =
new VegaTlbEntry(entry);
470 VegaTlbEntry *local_entry, *new_entry;
472 int req_cnt = sender_state->
reqCnt.back();
473 bool update_stats = !sender_state->
isPrefetch;
481 DPRINTF(GPUTLB,
"Translation Done - TLB Hit for addr %#x\n",
485 DPRINTF(GPUTLB,
"Translation Done - TLB Miss for addr %#x\n",
495 local_entry = new_entry;
498 assert(new_entry->pte);
499 DPRINTF(GPUTLB,
"allocating entry w/ addr %#lx of size %#lx\n",
500 virt_page_addr, new_entry->size());
502 local_entry =
insert(virt_page_addr, *new_entry);
513 DPRINTF(GPUTLB,
"Entry found with vaddr %#x, doing protection checks "
514 "while paddr was %#x.\n", local_entry->vaddr,
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);
528 pkt->
req->setPaddr(paddr);
530 if (local_entry->uncacheable()) {
539 DPRINTF(GPUTLB,
"Scheduled %#lx for cleanup\n", virt_page_addr);
559 DPRINTF(GPUTLB,
"Triggered TLBEvent for addr %#x\n", virtPageAddr);
567 int req_cnt = tmp_sender_state->
reqCnt.back();
568 bool update_stats = !tmp_sender_state->
isPrefetch;
576 DPRINTF(GPUTLB,
"This is a TLB miss\n");
588 tmp_sender_state->
pasId = 0;
591 DPRINTF(GPUTLB,
"Failed sending translation request to "
592 "lower level TLB for addr %#x\n", virtPageAddr);
596 DPRINTF(GPUTLB,
"Sent translation request to lower level "
597 "TLB for addr %#x\n", virtPageAddr);
601 DPRINTF(GPUTLB,
"Last level TLB - start a page walk for "
602 "addr %#x\n", virtPageAddr);
618 DPRINTF(GPUTLB,
"Doing a page walk for address %#x\n",
633 panic(
"Unexpected TLB outcome %d", outcome);
646 return "trigger translationDoneEvent";
674 if (
tlb->outstandingReqs <
tlb->maxCoalescedReqs) {
675 assert(!
tlb->translationReturnEvent.count(virt_page_addr));
676 tlb->issueTLBLookup(pkt);
678 tlb->outstandingReqs++;
681 DPRINTF(GPUTLB,
"Reached maxCoalescedReqs number %d\n",
682 tlb->outstandingReqs);
683 tlb->stats.maxDownstreamReached++;
688 if (
tlb->outstandingReqs >
tlb->stats.outstandingReqsMax.value())
689 tlb->stats.outstandingReqsMax =
tlb->outstandingReqs;
711 VegaTlbEntry *local_entry, *new_entry;
714 DPRINTF(GPUTLB,
"Functional Translation Done - TLB hit for addr "
719 DPRINTF(GPUTLB,
"Functional Translation Done - TLB miss for addr "
729 local_entry = new_entry;
734 DPRINTF(GPUTLB,
"allocating entry w/ addr %#lx\n",
737 local_entry =
insert(virt_page_addr, *new_entry);
743 DPRINTF(GPUTLB,
"Entry found with vaddr %#x, doing protection checks "
744 "while paddr was %#x.\n", local_entry->vaddr,
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);
765 pkt->
req->setPaddr(paddr);
767 if (local_entry->uncacheable())
779 bool update_stats = !sender_state->
isPrefetch;
785 bool success =
tlb->tlbLookup(pkt->
req, update_stats);
791 tlb->stats.globalNumTLBAccesses++;
795 tlb->stats.globalNumTLBHits++;
797 tlb->stats.globalNumTLBMisses++;
802 if (
tlb->hasMemSidePort) {
804 tlb->memSidePort[0]->sendFunctional(pkt);
810 DPRINTF(GPUTLB,
"Doing a page walk for address %#x\n",
814 [[maybe_unused]]
Addr alignedVaddr =
815 tlb->pageAlign(virt_page_addr);
816 assert(alignedVaddr == virt_page_addr);
822 Addr base =
tlb->gpuDevice->getVM().getPageTableBase(1);
823 tlb->walker->setDevRequestor(
tlb->gpuDevice->vramRequestorId());
830 fatal(
"Translation fault in TLB at %d!", __LINE__);
838 Addr alignedPaddr =
tlb->pageAlign(paddr);
839 pkt->
req->setPaddr(paddr);
840 pkt->
req->setSystemReq(pte.s);
848 new VegaTlbEntry(1 ,
vaddr & (~
mask(logBytes)),
849 alignedPaddr, logBytes, pte);
861 alignedPaddr, logBytes, pte);
872 VegaTlbEntry *entry =
tlb->lookup(virt_page_addr, update_stats);
876 DPRINTF(GPUPrefetch,
"Functional Hit for vaddr %#x\n",
880 sender_state->
tlbEntry =
new VegaTlbEntry(*entry);
887 tlb->handleFuncTranslationReturn(pkt, tlb_outcome);
895 panic(
"recvReqRetry called");
918 DPRINTF(GPUTLB,
"MemSidePort recvTiming for virt_page_addr %#x\n",
921 TLBEvent *tlb_event =
tlb->translationReturnEvent[virt_page_addr];
936 panic(
"recvReqRetry called");
946 DPRINTF(GPUTLB,
"Deleting return event for %#lx\n", cleanup_addr);
950 delete old_tlb_event;
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.
Event(Priority p=Default_Pri, Flags f=0)
void makeTimingResponse()
SenderState * senderState
This packet's sender state.
RequestPtr req
A pointer to the original request.
Ports are used to interface objects to each other.
@ UNCACHEABLE
The request is to an uncacheable address.
virtual void recvReqRetry()
virtual bool recvTimingReq(PacketPtr pkt)
recvTiming receives a coalesced timing request from a TLBCoalescer and it calls issueTLBLookup() It o...
virtual AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
virtual void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
virtual bool recvTimingResp(PacketPtr pkt)
MemSidePort receives the packet back.
virtual void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
const char * description() const
Return a C string describing the event.
void updateOutcome(tlbOutcome _outcome)
tlbOutcome outcome
outcome can be TLB_HIT, TLB_MISS, or PAGE_WALK
TLBEvent(GpuTLB *_tlb, Addr _addr, tlbOutcome outcome, PacketPtr _pkt)
VegaTlbEntry * lookup(Addr va, bool update_lru=true)
EntryList::iterator lookupIt(Addr va, bool update_lru=true)
void walkerResponse(VegaTlbEntry &entry, PacketPtr pkt)
std::vector< CpuSidePort * > cpuSidePort
virtual void serialize(CheckpointOut &cp) const override
Serialize an object.
virtual void unserialize(CheckpointIn &cp) override
Unserialize an object.
void issueTLBLookup(PacketPtr pkt)
Do the TLB lookup for this coalesced request and schedule another event <TLB access latency> cycles l...
VegaTlbEntry * insert(Addr vpn, VegaTlbEntry &entry)
void translationReturn(Addr virtPageAddr, tlbOutcome outcome, PacketPtr pkt)
A TLBEvent is scheduled after the TLB lookup and helps us take the appropriate actions: (e....
void pagingProtectionChecks(PacketPtr pkt, VegaTlbEntry *tlb_entry, Mode mode)
Do Paging protection checks.
void handleFuncTranslationReturn(PacketPtr pkt, tlbOutcome outcome)
handleFuncTranslationReturn is called on a TLB hit, when a TLB miss returns or when a page fault retu...
std::unordered_map< Addr, TLBEvent * > translationReturnEvent
std::vector< MemSidePort * > memSidePort
std::vector< EntryList > freeList
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Addr pageAlign(Addr vaddr)
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.
std::queue< Addr > cleanupQueue
bool FA
true if this is a fully-associative TLB
bool allocationPolicy
Allocation Policy: true if we always allocate on a hit, false otherwise.
EventFunctionWrapper cleanupEvent
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...
std::vector< EntryList > entryList
An entryList per set is the equivalent of an LRU stack; it's used to guide replacement decisions.
void demapPage(Addr va, uint64_t asn)
GpuTLB(const VegaGPUTLBParams &p)
Fault createPagefault(Addr vaddr, Mode mode)
bool hasMemSidePort
if true, then this is not the last level TLB
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
static const Priority Maximum_Pri
Maximum priority.
void schedule(Event &event, Tick when)
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
classes that represnt vector/scalar operands in VEGA ISA.
Copyright (c) 2024 Arm Limited All rights reserved.
std::shared_ptr< FaultBase > Fault
T safe_cast(U &&ref_or_ptr)
std::shared_ptr< Request > RequestPtr
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
std::string csprintf(const char *format, const Args &...args)
constexpr decltype(nullptr) NoFault
GPU TranslationState: this currently is a somewhat bastardization of the usage of SenderState,...
std::vector< int > reqCnt
statistics::Scalar outstandingReqsMax
statistics::Scalar localNumTLBMisses
statistics::Formula localLatency
statistics::Formula localTLBMissRate
statistics::Scalar localCycles
statistics::Scalar globalNumTLBAccesses
statistics::Scalar accessCycles
statistics::Scalar localNumTLBAccesses
VegaTLBStats(statistics::Group *parent)
statistics::Formula globalTLBMissRate
statistics::Scalar globalNumTLBMisses
statistics::Scalar localNumTLBHits
statistics::Scalar pageTableCycles
statistics::Scalar globalNumTLBHits
statistics::Scalar maxDownstreamReached
const std::string & name()