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);
165 VegaTlbEntry *newEntry =
nullptr;
167 int set =
getSet(entry.vaddr, entry.logBytes);
180 DPRINTF(GPUTLB,
"Inserted %#lx -> %#lx of size %#lx into set %d\n",
181 newEntry->vaddr, newEntry->paddr, entry.size(),
set);
186GpuTLB::EntryList::iterator
197 int page_size = (*entry)->size();
199 if ((*entry)->vaddr <=
va && (*entry)->vaddr + page_size >
va &&
200 ps == (*entry)->logBytes) {
201 DPRINTF(GPUTLB,
"Matched vaddr %#x to entry starting at %#x "
202 "with size %#x.\n",
va, (*entry)->vaddr, page_size);
236 DPRINTF(GPUTLB,
"Invalidating all entries.\n");
250 DPRINTF(GPUTLB,
"Demapping vaddr %#x.\n",
va);
274 if (req->hasNoAddr()) {
282 VegaTlbEntry *entry =
lookup(alignedVaddr,
true);
291 stats.localNumTLBAccesses++;
294 stats.localNumTLBMisses++;
296 stats.localNumTLBHits++;
342 bool update_stats = !sender_state->
isPrefetch;
344 DPRINTF(GPUTLB,
"Translation req. for virt. page addr %#x\n",
347 int req_cnt = sender_state->
reqCnt.back();
352 stats.globalNumTLBAccesses += req_cnt;
359 auto entry =
tlbLookup(tmp_req, update_stats);
360 if (entry || pkt->
req->hasNoAddr()) {
363 if (pkt->
req->hasNoAddr()) {
365 new VegaTlbEntry(1 , 0, 0, 0, 0);
368 pkt->
req->setSystemReq(
false);
370 VegaTlbEntry *entry =
lookup(virt_page_addr,
false);
374 pkt->
req->setSystemReq(entry->pte.s);
377 new VegaTlbEntry(*entry);
384 stats.globalNumTLBHits += req_cnt;
388 stats.globalNumTLBMisses += req_cnt;
401 new TLBEvent(
this, virt_page_addr, lookup_outcome, pkt);
404 panic(
"Virtual Page Address %#x already has a return event\n",
411 DPRINTF(GPUTLB,
"schedule translationReturnEvent @ curTick %d\n",
433 bool badWrite = (!tlb_entry->writable());
439 fatal(
"Page fault on addr %lx PTE=%#lx", pkt->
req->getVaddr(),
440 (uint64_t)tlb_entry->pte);
447 DPRINTF(GPUTLB,
"WalkerResponse for %#lx. Entry: (%#lx, %#lx, %#lx)\n",
448 pkt->
req->getVaddr(), entry.vaddr, entry.paddr, entry.size());
454 Addr paddr = page_addr + (entry.vaddr &
mask(entry.logBytes));
455 pkt->
req->setPaddr(paddr);
456 pkt->
req->setSystemReq(entry.pte.s);
460 sender_state->
tlbEntry =
new VegaTlbEntry(entry);
482 VegaTlbEntry *local_entry, *new_entry;
484 int req_cnt = sender_state->
reqCnt.back();
485 bool update_stats = !sender_state->
isPrefetch;
493 DPRINTF(GPUTLB,
"Translation Done - TLB Hit for addr %#x\n",
497 DPRINTF(GPUTLB,
"Translation Done - TLB Miss for addr %#x\n",
507 local_entry = new_entry;
510 assert(new_entry->pte);
511 DPRINTF(GPUTLB,
"allocating entry w/ addr %#lx of size %#lx\n",
512 virt_page_addr, new_entry->size());
514 local_entry =
insert(virt_page_addr, *new_entry);
525 DPRINTF(GPUTLB,
"Entry found with vaddr %#x, doing protection checks "
526 "while paddr was %#x.\n", local_entry->vaddr,
530 int page_size = local_entry->size();
531 Addr paddr = local_entry->paddr + (
vaddr & (page_size - 1));
532 DPRINTF(GPUTLB,
"Translated %#x -> %#x.\n",
vaddr, paddr);
540 pkt->
req->setPaddr(paddr);
542 if (local_entry->uncacheable()) {
551 DPRINTF(GPUTLB,
"Scheduled %#lx for cleanup\n", virt_page_addr);
571 DPRINTF(GPUTLB,
"Triggered TLBEvent for addr %#x\n", virtPageAddr);
579 int req_cnt = tmp_sender_state->
reqCnt.back();
580 bool update_stats = !tmp_sender_state->
isPrefetch;
588 DPRINTF(GPUTLB,
"This is a TLB miss\n");
600 tmp_sender_state->
pasId = 0;
603 DPRINTF(GPUTLB,
"Failed sending translation request to "
604 "lower level TLB for addr %#x\n", virtPageAddr);
608 DPRINTF(GPUTLB,
"Sent translation request to lower level "
609 "TLB for addr %#x\n", virtPageAddr);
613 DPRINTF(GPUTLB,
"Last level TLB - start a page walk for "
614 "addr %#x\n", virtPageAddr);
630 DPRINTF(GPUTLB,
"Doing a page walk for address %#x\n",
645 panic(
"Unexpected TLB outcome %d", outcome);
658 return "trigger translationDoneEvent";
686 if (
tlb->outstandingReqs <
tlb->maxCoalescedReqs) {
687 assert(!
tlb->translationReturnEvent.count(virt_page_addr));
688 tlb->issueTLBLookup(pkt);
690 tlb->outstandingReqs++;
693 DPRINTF(GPUTLB,
"Reached maxCoalescedReqs number %d\n",
694 tlb->outstandingReqs);
695 tlb->stats.maxDownstreamReached++;
700 if (
tlb->outstandingReqs >
tlb->stats.outstandingReqsMax.value())
701 tlb->stats.outstandingReqsMax =
tlb->outstandingReqs;
723 VegaTlbEntry *local_entry, *new_entry;
726 DPRINTF(GPUTLB,
"Functional Translation Done - TLB hit for addr "
731 DPRINTF(GPUTLB,
"Functional Translation Done - TLB miss for addr "
741 local_entry = new_entry;
746 DPRINTF(GPUTLB,
"allocating entry w/ addr %#lx\n",
749 local_entry =
insert(virt_page_addr, *new_entry);
755 DPRINTF(GPUTLB,
"Entry found with vaddr %#x, doing protection checks "
756 "while paddr was %#x.\n", local_entry->vaddr,
773 int page_size = local_entry->size();
774 Addr paddr = local_entry->paddr + (
vaddr & (page_size - 1));
775 DPRINTF(GPUTLB,
"Translated %#x -> %#x.\n",
vaddr, paddr);
777 pkt->
req->setPaddr(paddr);
779 if (local_entry->uncacheable())
791 bool update_stats = !sender_state->
isPrefetch;
797 bool success =
tlb->tlbLookup(pkt->
req, update_stats);
803 tlb->stats.globalNumTLBAccesses++;
807 tlb->stats.globalNumTLBHits++;
809 tlb->stats.globalNumTLBMisses++;
814 if (
tlb->hasMemSidePort) {
816 tlb->memSidePort[0]->sendFunctional(pkt);
822 DPRINTF(GPUTLB,
"Doing a page walk for address %#x\n",
826 [[maybe_unused]]
Addr alignedVaddr =
827 tlb->pageAlign(virt_page_addr);
828 assert(alignedVaddr == virt_page_addr);
834 Addr base =
tlb->gpuDevice->getVM().getPageTableBase(1);
835 tlb->walker->setDevRequestor(
tlb->gpuDevice->vramRequestorId());
842 fatal(
"Translation fault in TLB at %d!", __LINE__);
850 Addr alignedPaddr =
tlb->pageAlign(paddr);
851 pkt->
req->setPaddr(paddr);
852 pkt->
req->setSystemReq(pte.s);
860 new VegaTlbEntry(1 ,
vaddr & (~
mask(logBytes)),
861 alignedPaddr, logBytes, pte);
873 alignedPaddr, logBytes, pte);
884 VegaTlbEntry *entry =
tlb->lookup(virt_page_addr, update_stats);
888 DPRINTF(GPUPrefetch,
"Functional Hit for vaddr %#x\n",
892 sender_state->
tlbEntry =
new VegaTlbEntry(*entry);
899 tlb->handleFuncTranslationReturn(pkt, tlb_outcome);
907 panic(
"recvReqRetry called");
930 DPRINTF(GPUTLB,
"MemSidePort recvTiming for virt_page_addr %#x\n",
933 TLBEvent *tlb_event =
tlb->translationReturnEvent[virt_page_addr];
948 panic(
"recvReqRetry called");
958 DPRINTF(GPUTLB,
"Deleting return event for %#lx\n", cleanup_addr);
962 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)
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.
int getSet(Addr va, unsigned int page_shift)
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)
const std::array< unsigned int, 2 > logPageShiftList
Fault createPagefault(Addr vaddr, Mode mode)
bool hasMemSidePort
if true, then this is not the last level TLB
EntryList::iterator lookupIt(Addr va, unsigned int ps, bool update_lru=true)
#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()