gem5  v22.1.0.0
pif.cc
Go to the documentation of this file.
1 
30 
31 #include <utility>
32 
33 #include "debug/HWPrefetch.hh"
35 #include "params/PIFPrefetcher.hh"
36 
37 namespace gem5
38 {
39 
41 namespace prefetch
42 {
43 
44 PIF::PIF(const PIFPrefetcherParams &p)
45  : Queued(p),
46  precSize(p.prec_spatial_region_bits),
47  succSize(p.succ_spatial_region_bits),
48  maxCompactorEntries(p.compactor_entries),
49  historyBuffer(p.history_buffer_size),
50  index(p.index_assoc, p.index_entries, p.index_indexing_policy,
51  p.index_replacement_policy),
52  streamAddressBuffer(p.stream_address_buffer_entries),
53  listenersPC()
54 {
55 }
56 
58  unsigned int prec_size, unsigned int succ_size)
59 {
60  trigger = addr;
61  prec.resize(prec_size, false);
62  succ.resize(succ_size, false);
63 }
64 
65 Addr
67  unsigned int log_blk_size) const
68 {
69  const Addr target_blk = target >> log_blk_size;
70  const Addr trigger_blk = trigger >> log_blk_size;
71 
72  return target_blk > trigger_blk ?
73  target_blk - trigger_blk : trigger_blk - target_blk;
74 }
75 
76 bool
78  unsigned int log_blk_size, bool update)
79 {
80  Addr blk_distance = distanceFromTrigger(pc, log_blk_size);
81 
82  bool hit = (pc > trigger) ?
83  (succ.size() > blk_distance) : (prec.size() > blk_distance);
84  if (hit && update) {
85  if (pc > trigger) {
86  succ[blk_distance] = true;
87  } else if (pc < trigger) {
88  prec[blk_distance] = true;
89  }
90  }
91  return hit;
92 }
93 
94 bool
96  unsigned int log_blk_size) const
97 {
98  Addr blk_distance = distanceFromTrigger(target, log_blk_size);
99  bool hit = false;
100  if (target > trigger) {
101  hit = blk_distance < succ.size() && succ[blk_distance];
102  } else if (target < trigger) {
103  hit = blk_distance < prec.size() && prec[blk_distance];
104  } else {
105  hit = true;
106  }
107  return hit;
108 }
109 
110 void
112  std::vector<AddrPriority> &addresses) const
113 {
114  // Calculate the addresses of the instruction blocks that are encoded
115  // by the bit vector and issue prefetch requests for these addresses.
116  // Predictions are made by traversing the bit vector from left to right
117  // as this typically predicts the accesses in the order they will be
118  // issued in the core.
119  const Addr trigger_blk = trigger >> log_blk_size;
120  for (int i = prec.size()-1; i >= 0; i--) {
121  // Address from the preceding blocks to issue a prefetch
122  if (prec[i]) {
123  const Addr prec_addr = (trigger_blk - (i+1)) << log_blk_size;
124  addresses.push_back(AddrPriority(prec_addr, 0));
125  }
126  }
127  for (int i = 0; i < succ.size(); i++) {
128  // Address from the succeding blocks to issue a prefetch
129  if (succ[i]) {
130  const Addr succ_addr = (trigger_blk + (i+1)) << log_blk_size;
131  addresses.push_back(AddrPriority(succ_addr, 0));
132  }
133  }
134 }
135 
136 void
138 {
139  // First access to the prefetcher
140  if (temporalCompactor.size() == 0) {
143  } else {
144  // If the PC of the instruction retired is in the same spatial region
145  // than the last trigger address, update the bit vectors based on the
146  // distance between them
148  // If the PC of the instruction retired is outside the latest spatial
149  // region, check if it matches in any of the regions in the temporal
150  // compactor and update it to the MRU position
151  } else {
152  bool is_in_temporal_compactor = false;
153 
154  // Check if the PC is in the temporal compactor
155  for (auto it = temporalCompactor.begin();
156  it != temporalCompactor.end(); it++)
157  {
158  if (it->inSameSpatialRegion(pc, lBlkSize, false)) {
159  spatialCompactor = (*it);
160  temporalCompactor.erase(it);
161  is_in_temporal_compactor = true;
162  break;
163  }
164  }
165 
166  if (temporalCompactor.size() == maxCompactorEntries) {
167  temporalCompactor.pop_front(); // Discard the LRU entry
168  }
169 
171 
172  // If the compactor entry is neither the spatial or can't be
173  // found in the temporal compactor, reset the spatial compactor
174  // updating the trigger address and resetting the vector bits
175  if (!is_in_temporal_compactor) {
176  // Insert the spatial entry into the history buffer and update
177  // the 'iterator' table to point to the new entry
179 
180  IndexEntry *idx_entry =
181  index.findEntry(spatialCompactor.trigger, false);
182  if (idx_entry != nullptr) {
183  index.accessEntry(idx_entry);
184  } else {
185  idx_entry = index.findVictim(spatialCompactor.trigger);
186  assert(idx_entry != nullptr);
187  index.insertEntry(spatialCompactor.trigger, false,
188  idx_entry);
189  }
190  idx_entry->historyIt =
192 
193  // Reset the spatial compactor fields with the new address
195  }
196  }
197  }
198 }
199 
200 void
202  std::vector<AddrPriority> &addresses)
203 {
204  if (!pfi.hasPC()) {
205  return;
206  }
207 
208  const Addr pc = pfi.getPC();
209 
210  // First check if the access has been prefetched, this is done by
211  // comparing the access against the active Stream Address Buffers
212  for (auto &sabEntry : streamAddressBuffer) {
213  if (sabEntry->hasAddress(pc, lBlkSize)) {
214  sabEntry++;
215  sabEntry->getPredictedAddresses(lBlkSize, addresses);
216  // We are done
217  return;
218  }
219  }
220 
221  // Check if a valid entry in the 'index' table is found and allocate a new
222  // active prediction stream
223  IndexEntry *idx_entry = index.findEntry(pc, /* unused */ false);
224 
225  if (idx_entry != nullptr) {
226  index.accessEntry(idx_entry);
227  // Trigger address from the 'index' table and index to the history
228  // buffer
229  auto entry = idx_entry->historyIt;
230 
231  // Track the block in the Stream Address Buffer
233 
234  entry->getPredictedAddresses(lBlkSize, addresses);
235  }
236 }
237 
238 void
240 {
241  parent.notifyRetiredInst(pc);
242 }
243 
244 void
246 {
247  ProbeManager *pm(obj->getProbeManager());
248  listenersPC.push_back(new PrefetchListenerPC(*this, pm, name));
249 }
250 
251 } // namespace prefetch
252 } // namespace gem5
iterator getIterator(size_t idx)
Return an iterator to an index in the queue.
void update() const
Align cycle and tick to the next clock edge if not already done.
virtual std::string name() const
Definition: named.hh:47
ProbeManager is a conduit class that lives on each SimObject, and is used to match up probe listeners...
Definition: probe.hh:164
Abstract superclass for simulation objects.
Definition: sim_object.hh:148
Class containing the information needed by the prefetch to train and generate new prefetch requests.
Definition: base.hh:98
Addr getPC() const
Returns the program counter that generated this request.
Definition: base.hh:143
bool hasPC() const
Returns true if the associated program counter is valid.
Definition: base.hh:153
unsigned lBlkSize
log_2(block size of the parent cache).
Definition: base.hh:273
Probe Listener to handle probe events from the CPU.
Definition: pif.hh:166
void notify(const Addr &pc) override
Definition: pif.cc:239
const unsigned int maxCompactorEntries
Number of entries used for the temporal compactor.
Definition: pif.hh:63
void calculatePrefetch(const PrefetchInfo &pfi, std::vector< AddrPriority > &addresses)
Definition: pif.cc:201
std::vector< PrefetchListenerPC * > listenersPC
Array of probe listeners.
Definition: pif.hh:178
const unsigned int precSize
Number of preceding and subsequent spatial addresses to compact.
Definition: pif.hh:60
void addEventProbeRetiredInsts(SimObject *obj, const char *name)
Add a SimObject and a probe name to monitor the retired instructions.
Definition: pif.cc:245
CircularQueue< HistoryBuffer::iterator > streamAddressBuffer
A Stream Address Buffer (SAB) tracks a window of consecutive spatial regions.
Definition: pif.hh:154
AssociativeSet< IndexEntry > index
The index table is a small cache-like structure that facilitates fast search of the history buffer.
Definition: pif.hh:146
void notifyRetiredInst(const Addr pc)
Updates the prefetcher structures upon an instruction retired.
Definition: pif.cc:137
const unsigned int succSize
Definition: pif.hh:61
CompactorEntry spatialCompactor
Definition: pif.hh:128
std::deque< CompactorEntry > temporalCompactor
Definition: pif.hh:129
PIF(const PIFPrefetcherParams &p)
Definition: pif.cc:44
HistoryBuffer historyBuffer
Definition: pif.hh:136
std::pair< Addr, int32_t > AddrPriority
Definition: queued.hh:191
STL vector class.
Definition: stl.hh:37
void push_back(typename std::vector< T >::value_type val)
Pushes an element at the end of the queue.
size_t tail() const
ProbeManager * getProbeManager()
Get the probe manager for this object.
Definition: sim_object.cc:120
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 4 > pc
Bitfield< 30, 0 > index
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 3 > addr
Definition: types.hh:84
Bitfield< 21 > trigger
Definition: intmessage.hh:52
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
The compactor tracks retired instructions addresses, leveraging the spatial and temporal locality amo...
Definition: pif.hh:80
std::vector< bool > prec
Definition: pif.hh:82
bool hasAddress(Addr target, unsigned int log_blk_size) const
Checks if the provided address is contained in this spatial region and if its corresponding bit vecto...
Definition: pif.cc:95
bool inSameSpatialRegion(Addr addr, unsigned int log_blk_size, bool update)
Checks if a given address is in the same defined spatial region as the compactor entry.
Definition: pif.cc:77
void getPredictedAddresses(unsigned int log_blk_size, std::vector< AddrPriority > &addresses) const
Fills the provided vector with the predicted addresses using the recorded bit vectors of the entry.
Definition: pif.cc:111
std::vector< bool > succ
Definition: pif.hh:83
Addr distanceFromTrigger(Addr addr, unsigned int log_blk_size) const
Computes the distance, in cache blocks, from an address to the trigger of the entry.
Definition: pif.cc:66
HistoryBuffer::iterator historyIt
Definition: pif.hh:140

Generated on Wed Dec 21 2022 10:22:36 for gem5 by doxygen 1.9.1