Go to the documentation of this file.
38 #include "debug/GPUTLB.hh"
46 TLBProbesPerCycle(
p.probesPerCycle),
47 coalescingWindow(
p.coalescingWindow),
48 disableCoalescing(
p.disableCoalescing),
50 "Probe the TLB below",
52 cleanupEvent([
this]{ processCleanupEvent(); },
53 "Cleanup issuedTranslationsTable hashmap",
58 for (
size_t i = 0;
i <
p.port_cpu_side_ports_connection_count; ++
i) {
64 for (
size_t i = 0;
i <
p.port_mem_side_ports_connection_count; ++
i) {
73 if (if_name ==
"cpu_side_ports") {
75 panic(
"TLBCoalescer::getPort: unknown index %d\n", idx);
79 }
else if (if_name ==
"mem_side_ports") {
81 panic(
"TLBCoalescer::getPort: unknown index %d\n", idx);
86 panic(
"TLBCoalescer::getPort: unknown port %s\n", if_name);
103 safe_cast<GpuTranslationState*>(incoming_pkt->
senderState);
106 safe_cast<GpuTranslationState*>(coalesced_pkt->
senderState);
116 if (incoming_virt_page_addr != coalesced_virt_page_addr)
125 if (incoming_mode != coalesced_mode)
132 coalesced_state->
reqCnt.back() += incoming_state->
reqCnt.back();
146 DPRINTF(GPUTLB,
"Update phys. addr. for %d coalesced reqs for page %#x\n",
152 TheISA::TlbEntry *tlb_entry = sender_state->
tlbEntry;
154 Addr first_entry_vaddr = tlb_entry->vaddr;
155 Addr first_entry_paddr = tlb_entry->paddr;
156 int page_size = tlb_entry->size();
157 bool uncacheable = tlb_entry->uncacheable;
158 int first_hit_level = sender_state->
hitLevel;
163 Addr phys_page_paddr = pkt->
req->getPaddr();
164 phys_page_paddr &= ~(page_size - 1);
169 safe_cast<GpuTranslationState*>(
175 sender_state->
reqCnt.pop_back();
184 Addr paddr = phys_page_paddr;
185 paddr |= (local_pkt->
req->getVaddr() & (page_size - 1));
186 local_pkt->
req->setPaddr(paddr);
195 new TheISA::TlbEntry(
p->pid(), first_entry_vaddr,
196 first_entry_paddr,
false,
false);
201 sender_state->
hitLevel = first_hit_level;
205 sender_state->
ports.pop_back();
235 bool didCoalesce =
false;
237 int coalescedReq_cnt = 0;
243 sender_state->
ports.push_back(
this);
245 bool update_stats = !sender_state->
isPrefetch;
255 if (!sender_state->
reqCnt.empty())
256 req_cnt = sender_state->
reqCnt.back();
258 sender_state->
reqCnt.push_back(req_cnt);
262 req_cnt = sender_state->
reqCnt.back();
263 DPRINTF(GPUTLB,
"receiving pkt w/ req_cnt %d\n", req_cnt);
287 for (
int i = 0;
i < coalescedReq_cnt; ++
i) {
293 DPRINTF(GPUTLB,
"Coalesced req %i w/ tick_index %d has %d reqs\n",
305 if (!coalescedReq_cnt || !didCoalesce) {
310 new_array.push_back(pkt);
313 DPRINTF(GPUTLB,
"coalescerFIFO[%d] now has %d coalesced reqs after "
314 "push\n", tick_index,
331 panic(
"recvReqRetry called");
341 bool update_stats = !sender_state->
isPrefetch;
344 coalescer->stats.uncoalescedAccesses++;
351 int map_count = coalescer->issuedTranslationsTable.count(virt_page_addr);
354 DPRINTF(GPUTLB,
"Warning! Functional access to addr %#x sees timing "
355 "req. pending\n", virt_page_addr);
358 coalescer->memSidePort[0]->sendFunctional(pkt);
374 coalescer->updatePhysAddresses(pkt);
383 if (!coalescer->probeTLBEvent.scheduled())
384 coalescer->schedule(coalescer->probeTLBEvent,
385 curTick() + coalescer->clockPeriod());
391 fatal(
"Memory side recvFunctional() not implemented in TLB coalescer.\n");
412 bool rejected =
false;
418 DPRINTF(GPUTLB,
"triggered TLBCoalescer %s\n", __func__);
422 int coalescedReq_cnt = iter->second.size();
424 int vector_index = 0;
426 DPRINTF(GPUTLB,
"coalescedReq_cnt is %d for tick_index %d\n",
427 coalescedReq_cnt, iter->first);
429 while (
i < coalescedReq_cnt) {
431 PacketPtr first_packet = iter->second[vector_index][0];
442 DPRINTF(GPUTLB,
"Cannot issue - There are pending reqs for "
443 "page %#x\n", virt_page_addr);
452 if (!
memSidePort[0]->sendTimingReq(first_packet)) {
453 DPRINTF(GPUTLB,
"Failed to send TLB request for page %#x\n",
462 safe_cast<GpuTranslationState*>
465 bool update_stats = !tmp_sender_state->
isPrefetch;
471 int req_cnt = tmp_sender_state->
reqCnt.back();
474 DPRINTF(GPUTLB,
"%s sending pkt w/ req_cnt %d\n",
479 int pkt_cnt = iter->second[vector_index].size();
483 DPRINTF(GPUTLB,
"Successfully sent TLB request for page %#x",
488 = iter->second[vector_index];
491 iter->second.erase(iter->second.begin() + vector_index);
493 if (iter->second.empty())
494 assert(
i == coalescedReq_cnt);
504 if (iter->second.empty()) {
520 DPRINTF(GPUTLB,
"Cleanup - Delete coalescer entry with key %#x\n",
526 : statistics::
Group(parent),
527 ADD_STAT(uncoalescedAccesses,
"Number of uncoalesced TLB accesses"),
528 ADD_STAT(coalescedAccesses,
"Number of coalesced TLB accesses"),
529 ADD_STAT(queuingCycles,
"Number of cycles spent in queue"),
531 "Number of cycles spent in queue for all incoming reqs"),
532 ADD_STAT(localLatency,
"Avg. latency over all incoming pkts")
statistics::Scalar queuingCycles
Tick curTick()
The universal simulation clock.
#define fatal(...)
This implements a cprintf based fatal() function.
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
virtual bool recvTimingReq(PacketPtr pkt)
Receive a timing request from the peer.
virtual void recvReqRetry()
void processCleanupEvent()
RequestPtr req
A pointer to the original request.
CoalescingTable issuedTranslationsTable
std::queue< Addr > cleanupQueue
void schedule(Event &event, Tick when)
std::string csprintf(const char *format, const Args &...args)
std::vector< MemSidePort * > memSidePort
void processProbeTLBEvent()
virtual void recvFunctional(PacketPtr pkt)
virtual bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
TLBCoalescer(const Params &p)
TLB TranslationState: this currently is a somewhat bastardization of the usage of SenderState,...
std::vector< ResponsePort * > ports
void updatePhysAddresses(PacketPtr pkt)
virtual std::string name() const
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
virtual void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
static const Priority Maximum_Pri
Maximum priority.
virtual AddrRangeList getAddrRanges() const
Get a list of the non-overlapping address ranges the owner is responsible for.
statistics::Formula localLatency
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
std::vector< CpuSidePort * > cpuSidePort
static constexpr T roundDown(const T &val, const U &align)
This function is used to align addresses in memory.
EventFunctionWrapper cleanupEvent
The cleanupEvent is scheduled after a TLBEvent triggers in order to free memory and do the required c...
bool canCoalesce(PacketPtr pkt1, PacketPtr pkt2)
CoalescingFIFO coalescerFIFO
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
SenderState * senderState
This packet's sender state.
statistics::Scalar localqueuingCycles
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
virtual Process * getProcessPtr()=0
EventFunctionWrapper probeTLBEvent
This event issues the TLB probes.
A ResponsePort is a specialization of a port.
statistics::Scalar uncoalescedAccesses
statistics::Scalar coalescedAccesses
void makeTimingResponse()
gem5::TLBCoalescer::TLBCoalescerStats stats
TLBCoalescerParams Params
@ UNCACHEABLE
The request is to an uncacheable address.
TLBCoalescerStats(statistics::Group *parent)
virtual void recvFunctional(PacketPtr pkt)
Receive a functional request packet from the peer.
static const Priority CPU_Tick_Pri
CPU ticks must come after other associated CPU events (such as writebacks).
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::vector< int > reqCnt
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
bool scheduled() const
Determine if the current event is scheduled.
#define panic(...)
This implements a cprintf based panic() function.
Generated on Wed May 4 2022 12:13:35 for gem5 by doxygen 1.8.17