gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
fdp.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022-2023 The University of Edinburgh
3 * Copyright (c) 2025 Arm Limited
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are
17 * met: redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer;
19 * redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution;
22 * neither the name of the copyright holders nor the names of its
23 * contributors may be used to endorse or promote products derived from
24 * this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
40
41#include <utility>
42
43#include "debug/HWPrefetch.hh"
44#include "mem/cache/base.hh"
45#include "params/FetchDirectedPrefetcher.hh"
46
47namespace gem5
48{
49
50namespace prefetch
51{
52
54 const FetchDirectedPrefetcherParams &p)
55 : Base(p),
56 cpu(p.cpu),
57 cache(nullptr),
58 markReqAsPrefetch(p.mark_req_as_prefetch),
59 squashPrefetches(p.squash_prefetches),
61 pfqSize(p.pfq_size),
62 tqSize(p.tq_size),
63 cacheSnoop(p.cache_snoop),
64 stats(this, p.pfq_size, p.tq_size)
65{}
66
67void
69{
70 const Addr start_blk_addr = blockAddress(ft->startAddress());
71 const Addr end_blk_addr = blockAddress(ft->endAddress());
72
73 for (Addr blk_addr = start_blk_addr; blk_addr <= end_blk_addr;
74 blk_addr += blkSize) {
75
76 // Check if the address is already in the prefetch queue
77 auto it = std::find(pfq.begin(), pfq.end(), blk_addr);
78 if (it != pfq.end()) {
79 DPRINTF(HWPrefetch, "%#x already in prefetch_queue\n", blk_addr);
80 stats.pfInPFQ++;
81 continue;
82 }
83
84 it = std::find(translationq.begin(), translationq.end(), blk_addr);
85 if (it != translationq.end()) {
86 DPRINTF(HWPrefetch, "%#x already in translation queue\n",
87 blk_addr);
88 stats.pfInTQ++;
89 continue;
90 }
91
92 stats.pfIdentified++;
93
94 if (translationq.size() >= tqSize) {
95 DPRINTF(HWPrefetch, "Translation queue full, dropping %#x\n",
96 blk_addr);
97 stats.tqDrops++;
98 continue;
99 }
100 // TODO add also check for pfq to save unnecessary translations
101 // Maybe merge the two queues
102 translationq.emplace_back(*this, blk_addr, ft->getTid(), ft->ftNum());
103 DPRINTF(HWPrefetch, "Start translation for %#x, reqID=%i, ctxID=%i\n",
104 blk_addr, translationq.back().req->requestorId(),
105 translationq.back().req->contextId());
106 translationq.back().startTranslation();
107 stats.tqInserts++;
108 stats.tqSizeDistAtNotify.sample(translationq.size());
109 stats.pfqSizeDistAtNotify.sample(pfq.size());
110 }
111}
112
113void
115{
116 if (!squashPrefetches) {
117 return;
118 }
119
120 // Mark any in-flight translations associated with the fetch
121 // target as canceled. This will block them from progressing to
122 // the `pfq` when translation is complete. We cannot simply remove
123 // them from the `translationq` as the asynchronous
124 // `translationComplete` callback assumes the `translationq` still
125 // contains the entry.
126 for (auto &pr : translationq) {
127 if (pr.ftn == ft->ftNum()) {
128 pr.markCanceled();
129 stats.pfSquashed++;
130 }
131 }
132
133 // Remove any existing prefetch requests that belong to this fetch
134 // target.
135 auto it = pfq.begin();
136 while (it != pfq.end()) {
137 if (it->ftn == ft->ftNum()) {
138 it = pfq.erase(it);
139 stats.pfSquashed++;
140 } else {
141 ++it;
142 }
143 }
144}
145
146void
148{
149 auto it = translationq.begin();
150 while (it != translationq.end()) {
151 if (&(*it) == pfr) {
152 break;
153 }
154 ++it;
155 }
156 assert(it != translationq.end());
157 warn_if_once(cacheSnoop && (cache == nullptr),
158 "Cache is not set. Cache snooping will not work!\n");
159
160 if (failed) {
161 DPRINTF(HWPrefetch, "Translation of %#x failed\n", it->addr);
162 stats.translationFail++;
163 } else {
164 DPRINTF(HWPrefetch, "Translation of %#x succeeded\n", it->addr);
165 stats.translationSuccess++;
166
167 if (it->isCanceled()) {
168 DPRINTF(HWPrefetch,
169 "Drop Packet. Canceled by notifyFTQRemove during "
170 "translation.\n");
171 } else if (it->req->isUncacheable()) {
172 DPRINTF(HWPrefetch, "Drop uncacheable requests.\n");
173 } else if (cacheSnoop && cache &&
174 (cache->inCache(it->req->getPaddr(), it->req->isSecure()) ||
175 (cache->inMissQueue(it->req->getPaddr(),
176 it->req->isSecure())))) {
177 stats.pfInCache++;
178 DPRINTF(HWPrefetch, "Drop Packet. In Cache / MSHR\n");
179 } else {
180 if (pfq.size() < pfqSize) {
181 it->createPkt();
182 it->readyTime = curTick() + latency;
183 stats.pfPacketsCreated++;
184 DPRINTF(HWPrefetch,
185 "Addr:%#x Add packet to PFQ. pkt PA:%#x, "
186 "PFQ sz:%i\n",
187 it->addr, it->pkt->getAddr(), pfq.size());
188
189 stats.pfCandidatesAdded++;
190 pfq.push_back(*it);
191 stats.pfqInserts++;
192 } else {
193 DPRINTF(HWPrefetch, "Prefetch queue full, dropping %#x\n",
194 it->addr);
195 stats.pfqDrops++;
196 }
197 }
198 }
199 translationq.erase(it);
200 stats.tqPops++;
201}
202
205{
206 if (pfq.size() == 0) {
207 return nullptr;
208 }
209 PacketPtr pkt = pfq.front().pkt;
210
211 DPRINTF(HWPrefetch, "Issue Prefetch to: pkt:%#x, PC:%#x, PFQ size:%i\n",
212 pkt->getAddr(), pfq.front().addr, pfq.size());
213
214 pfq.pop_front();
215 stats.pfqPops++;
216
217 prefetchStats.pfIssued++;
218 return pkt;
219}
220
222 FetchDirectedPrefetcher &_owner, uint64_t _addr, ThreadID tid,
223 o3::FTSeqNum _ftn)
224 : owner(_owner),
225 addr(_addr),
226 ftn(_ftn),
227 req(nullptr),
228 pkt(nullptr),
230 canceled(false)
231{
232 req = std::make_shared<Request>(addr, owner.blkSize, Request::INST_FETCH,
233 owner.requestorId, addr,
234 owner.cpu->getContext(tid)->contextId());
235 if (owner.markReqAsPrefetch) {
236 req->setFlags(Request::PREFETCH);
237 }
238 assert(req);
239}
240
241void
248
249void
251{
252 assert(owner.mmu != nullptr);
253 auto tc = owner.system->threads[req->contextId()];
254 owner.mmu->translateTiming(req, tc, this, BaseMMU::Execute);
255}
256
257void
259 const RequestPtr &req,
260 ThreadContext *tc,
262{
263 bool failed = (fault != NoFault);
264 owner.translationComplete(this, failed);
265}
266
267void
269{
271
272 if (cpu == nullptr) {
273 warn("FetchDirectedPrefetcher: No CPU to listen from registered\n");
274 return;
275 }
276 typedef ProbeListenerArgFunc<o3::FetchTargetPtr> FetchTargetListener;
277 listeners.push_back(cpu->getProbeManager()->connect<FetchTargetListener>(
278 "FTQInsert",
279 [this](const o3::FetchTargetPtr &ft) { notifyFTQInsert(ft); }));
280
281 listeners.push_back(cpu->getProbeManager()->connect<FetchTargetListener>(
282 "FTQRemove",
283 [this](const o3::FetchTargetPtr &ft) { notifyFTQRemove(ft); }));
284}
285
287 int tq_size)
288 : statistics::Group(parent),
289 ADD_STAT(fdipInsertions, statistics::units::Count::get(),
290 "Number of notifications from an insertion in the FTQ"),
291 ADD_STAT(pfIdentified, statistics::units::Count::get(),
292 "Number of prefetches identified."),
293 ADD_STAT(pfSquashed, statistics::units::Count::get(),
294 "Number of prefetches squashed."),
295 ADD_STAT(pfInPFQ, statistics::units::Count::get(),
296 "Number of prefetches hit in the prefetch queue"),
297 ADD_STAT(pfInTQ, statistics::units::Count::get(),
298 "Number of prefetches hit in the translation queue"),
299 ADD_STAT(pfInCache, statistics::units::Count::get(),
300 "Number of prefetches hit in in cache"),
302 "Number of prefetches hit in cache but prefetched"),
304 "Number of prefetch packets created"),
306 "Number of prefetch candidates added to the prefetch queue"),
308 "Number of prefetches that failed translation"),
310 "Number of prefetches that succeeded translation"),
312 "Distribution of the prefetch queue size at the time of "
313 "notification of a new fetch target"),
315 "Distribution of the translation queue size at the time of "
316 "notification of a new fetch target"),
317 ADD_STAT(pfqInserts, statistics::units::Count::get(),
318 "Number of insertions into the prefetch candidate queue"),
319 ADD_STAT(pfqPops, statistics::units::Count::get(),
320 "Number of uses into the prefetch candidate queue"),
321 ADD_STAT(pfqDrops, statistics::units::Count::get(),
322 "Number of drops into the prefetch candidate queue"),
323 ADD_STAT(tqInserts, statistics::units::Count::get(),
324 "Number of insertions into the prefetch translation queue"),
325 ADD_STAT(tqPops, statistics::units::Count::get(),
326 "Number of uses into the prefetch translation queue"),
327 ADD_STAT(tqDrops, statistics::units::Count::get(),
328 "Number of drops into the prefetch translation queue")
329{
330 pfqSizeDistAtNotify.init(0, pfq_size, 4);
331 tqSizeDistAtNotify.init(0, tq_size, 4);
332}
333
334} // namespace prefetch
335} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
Tick cyclesToTicks(Cycles c) const
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
ProbeListenerArgFunc generates a listener for the class of Arg and a lambda callback function that is...
Definition probe.hh:352
@ INST_FETCH
The request was an instruction fetch.
Definition request.hh:115
@ PREFETCH
The request is a prefetch.
Definition request.hh:164
ThreadContext is the external interface to all thread state for anything outside of the CPU.
Base(const BasePrefetcherParams &p)
Definition base.cc:101
unsigned blkSize
The block size of the parent cache.
Definition base.hh:288
void regProbeListeners() override
Register probe points for this object.
Definition base.cc:271
gem5::prefetch::Base::StatGroup prefetchStats
Addr blockAddress(Addr a) const
Determine the address of the block in which a lays.
Definition base.cc:201
std::list< PrefetchRequest > pfq
The prefetch queue.
Definition fdp.hh:178
void translationComplete(PrefetchRequest *pf_req, const bool failed)
A translation has completed and can now be added to the PFQ.
Definition fdp.cc:147
const unsigned int tqSize
Translation queue size: Maximum number of outstanding translations.
Definition fdp.hh:113
const bool markReqAsPrefetch
Mark memory requests as prefetches.
Definition fdp.hh:101
gem5::prefetch::FetchDirectedPrefetcher::Stats stats
const bool cacheSnoop
Probe the cache before a prefetch gets inserted into the PFQ.
Definition fdp.hh:116
void notifyFTQRemove(const o3::FetchTargetPtr &ft)
Notifies the prefetcher that a fetch target was removed from the FTQ.
Definition fdp.cc:114
BaseCPU * cpu
Pointer to the CPU object that contains the FTQ.
Definition fdp.hh:95
std::list< PrefetchRequest > translationq
Definition fdp.hh:179
const unsigned int pfqSize
Prefetch queue size: Maximum number of queued prefetches.
Definition fdp.hh:110
const bool squashPrefetches
Squash prefetches in case its fetch target is removed from the FTQ.
Definition fdp.hh:104
const unsigned int latency
The latency of the prefetcher.
Definition fdp.hh:107
void regProbeListeners() override
Base class overrides.
Definition fdp.cc:268
BaseCache * cache
Pointer to the cache it is attached to.
Definition fdp.hh:98
FetchDirectedPrefetcher(const FetchDirectedPrefetcherParams &p)
Definition fdp.cc:53
std::vector< ProbeListenerPtr<> > listeners
Array of probe listeners.
Definition fdp.hh:92
PacketPtr getPacket() override
Gets a packet from the prefetch queue to be prefetched.
Definition fdp.cc:204
void notifyFTQInsert(const o3::FetchTargetPtr &ft)
Notifies the prefetcher that a new fetch target was inserted into the FTQ.
Definition fdp.cc:68
Statistics container.
Definition group.hh:93
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
#define warn_if_once(cond,...)
Definition logging.hh:322
#define warn(...)
Definition logging.hh:288
Declares a basic cache interface BaseCache.
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 0 > p
Bitfield< 14 > pr
Definition misc.hh:116
InstSeqNum FTSeqNum
Definition ftq.hh:67
std::shared_ptr< FetchTarget > FetchTargetPtr
Definition bac.hh:62
Units for Stats.
Definition units.hh:113
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
std::shared_ptr< FaultBase > Fault
Definition types.hh:249
int16_t ThreadID
Thread index/ID type.
Definition types.hh:235
std::shared_ptr< Request > RequestPtr
Definition request.hh:94
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
const Tick MaxTick
Definition types.hh:60
Packet * PacketPtr
constexpr decltype(nullptr) NoFault
Definition types.hh:253
The prefetch queue entry objects.
Definition fdp.hh:120
PrefetchRequest(FetchDirectedPrefetcher &_owner, uint64_t _addr, ThreadID tid, o3::FTSeqNum ftn)
Definition fdp.cc:221
Tick readyTime
The time when the prefetch is ready to be sent to the cache.
Definition fdp.hh:138
bool canceled
Marks a Prefetch Request as canceled if notifyFTQRemove was called during translation.
Definition fdp.hh:143
void startTranslation()
Issues the translation request.
Definition fdp.cc:250
const uint64_t addr
The virtual address.
Definition fdp.hh:128
RequestPtr req
The request and packet that will be sent to the cache.
Definition fdp.hh:134
const o3::FTSeqNum ftn
The fetch target number that created this request.
Definition fdp.hh:131
FetchDirectedPrefetcher & owner
Owner of the packet.
Definition fdp.hh:125
void finish(const Fault &fault, const RequestPtr &req, ThreadContext *tc, BaseMMU::Mode mode) override
Definition fdp.cc:258
void createPkt()
Creates the packet that is send to the memory.
Definition fdp.cc:242
Stats(statistics::Group *parent, int pfq_size, int tq_size)
Definition fdp.cc:286
statistics::Distribution pfqSizeDistAtNotify
Definition fdp.hh:210
statistics::Distribution tqSizeDistAtNotify
Definition fdp.hh:211

Generated on Mon Oct 27 2025 04:13:03 for gem5 by doxygen 1.14.0