gem5  v22.1.0.0
access_map_pattern_matching.cc
Go to the documentation of this file.
1 
30 
31 #include "debug/HWPrefetch.hh"
33 #include "params/AMPMPrefetcher.hh"
34 #include "params/AccessMapPatternMatching.hh"
35 
36 namespace gem5
37 {
38 
40 namespace prefetch
41 {
42 
44  const AccessMapPatternMatchingParams &p)
45  : ClockedObject(p), blkSize(p.block_size), limitStride(p.limit_stride),
46  startDegree(p.start_degree), hotZoneSize(p.hot_zone_size),
47  highCoverageThreshold(p.high_coverage_threshold),
48  lowCoverageThreshold(p.low_coverage_threshold),
49  highAccuracyThreshold(p.high_accuracy_threshold),
50  lowAccuracyThreshold(p.low_accuracy_threshold),
51  highCacheHitThreshold(p.high_cache_hit_threshold),
52  lowCacheHitThreshold(p.low_cache_hit_threshold),
53  epochCycles(p.epoch_cycles),
54  offChipMemoryLatency(p.offchip_memory_latency),
55  accessMapTable(p.access_map_table_assoc, p.access_map_table_entries,
56  p.access_map_table_indexing_policy,
57  p.access_map_table_replacement_policy,
58  AccessMapEntry(hotZoneSize / blkSize)),
59  numGoodPrefetches(0), numTotalPrefetches(0), numRawCacheMisses(0),
60  numRawCacheHits(0), degree(startDegree), usefulDegree(startDegree),
61  epochEvent([this]{ processEpochEvent(); }, name())
62 {
63  fatal_if(!isPowerOf2(hotZoneSize),
64  "the hot zone size must be a power of 2");
65 }
66 
67 void
69 {
71 }
72 
73 void
75 {
77  double prefetch_accuracy =
78  ((double) numGoodPrefetches) / ((double) numTotalPrefetches);
79  double prefetch_coverage =
80  ((double) numGoodPrefetches) / ((double) numRawCacheMisses);
81  double cache_hit_ratio = ((double) numRawCacheHits) /
82  ((double) (numRawCacheHits + numRawCacheMisses));
83  double num_requests = (double) (numRawCacheMisses - numGoodPrefetches +
85  double memory_bandwidth = num_requests * offChipMemoryLatency /
87 
88  if (prefetch_coverage > highCoverageThreshold &&
89  (prefetch_accuracy > highAccuracyThreshold ||
90  cache_hit_ratio < lowCacheHitThreshold)) {
91  usefulDegree += 1;
92  } else if ((prefetch_coverage < lowCoverageThreshold &&
93  (prefetch_accuracy < lowAccuracyThreshold ||
94  cache_hit_ratio > highCacheHitThreshold)) ||
95  (prefetch_accuracy < lowAccuracyThreshold &&
96  cache_hit_ratio > highCacheHitThreshold)) {
97  usefulDegree -= 1;
98  }
99  degree = std::min((unsigned) memory_bandwidth, usefulDegree);
100  // reset epoch stats
101  numGoodPrefetches = 0.0;
102  numTotalPrefetches = 0.0;
103  numRawCacheMisses = 0.0;
104  numRawCacheHits = 0.0;
105 }
106 
109  bool is_secure)
110 {
111  AccessMapEntry *am_entry = accessMapTable.findEntry(am_addr, is_secure);
112  if (am_entry != nullptr) {
113  accessMapTable.accessEntry(am_entry);
114  } else {
115  am_entry = accessMapTable.findVictim(am_addr);
116  assert(am_entry != nullptr);
117 
118  accessMapTable.insertEntry(am_addr, is_secure, am_entry);
119  }
120  return am_entry;
121 }
122 
123 void
125  Addr block, enum AccessMapState state)
126 {
127  enum AccessMapState old = entry.states[block];
128  entry.states[block] = state;
129 
130  //do not update stats when initializing
131  if (state == AM_INIT) return;
132 
133  switch (old) {
134  case AM_INIT:
135  if (state == AM_PREFETCH) {
136  numTotalPrefetches += 1;
137  } else if (state == AM_ACCESS) {
138  numRawCacheMisses += 1;
139  }
140  break;
141  case AM_PREFETCH:
142  if (state == AM_ACCESS) {
143  numGoodPrefetches += 1;
144  numRawCacheMisses += 1;
145  }
146  break;
147  case AM_ACCESS:
148  if (state == AM_ACCESS) {
149  numRawCacheHits += 1;
150  }
151  break;
152  default:
153  panic("Impossible path\n");
154  break;
155  }
156 }
157 
158 void
161 {
162  assert(addresses.empty());
163 
164  bool is_secure = pfi.isSecure();
165  Addr am_addr = pfi.getAddr() / hotZoneSize;
166  Addr current_block = (pfi.getAddr() % hotZoneSize) / blkSize;
167  uint64_t lines_per_zone = hotZoneSize / blkSize;
168 
169  // Get the entries of the curent block (am_addr), the previous, and the
170  // following ones
171  AccessMapEntry *am_entry_curr = getAccessMapEntry(am_addr, is_secure);
172  AccessMapEntry *am_entry_prev = (am_addr > 0) ?
173  getAccessMapEntry(am_addr-1, is_secure) : nullptr;
174  AccessMapEntry *am_entry_next = (am_addr < (MaxAddr/hotZoneSize)) ?
175  getAccessMapEntry(am_addr+1, is_secure) : nullptr;
176  assert(am_entry_curr != am_entry_prev);
177  assert(am_entry_curr != am_entry_next);
178  assert(am_entry_prev != am_entry_next);
179  assert(am_entry_curr != nullptr);
180 
181  //Mark the current access as Accessed
182  setEntryState(*am_entry_curr, current_block, AM_ACCESS);
183 
189  std::vector<AccessMapState> states(3 * lines_per_zone);
190  for (unsigned idx = 0; idx < lines_per_zone; idx += 1) {
191  states[idx] =
192  am_entry_prev != nullptr ? am_entry_prev->states[idx] : AM_INVALID;
193  states[idx + lines_per_zone] = am_entry_curr->states[idx];
194  states[idx + 2 * lines_per_zone] =
195  am_entry_next != nullptr ? am_entry_next->states[idx] : AM_INVALID;
196  }
197 
204  // index of the current_block in the new vector
205  Addr states_current_block = current_block + lines_per_zone;
206  // consider strides 1..lines_per_zone/2
207  int max_stride = limitStride == 0 ? lines_per_zone / 2 : limitStride + 1;
208  for (int stride = 1; stride < max_stride; stride += 1) {
209  // Test accessed positive strides
210  if (checkCandidate(states, states_current_block, stride)) {
211  // candidate found, current_block - stride
212  Addr pf_addr;
213  if (stride > current_block) {
214  // The index (current_block - stride) falls in the range of
215  // the previous zone (am_entry_prev), adjust the address
216  // accordingly
217  Addr blk = states_current_block - stride;
218  pf_addr = (am_addr - 1) * hotZoneSize + blk * blkSize;
219  setEntryState(*am_entry_prev, blk, AM_PREFETCH);
220  } else {
221  // The index (current_block - stride) falls within
222  // am_entry_curr
223  Addr blk = current_block - stride;
224  pf_addr = am_addr * hotZoneSize + blk * blkSize;
225  setEntryState(*am_entry_curr, blk, AM_PREFETCH);
226  }
227  addresses.push_back(Queued::AddrPriority(pf_addr, 0));
228  if (addresses.size() == degree) {
229  break;
230  }
231  }
232 
233  // Test accessed negative strides
234  if (checkCandidate(states, states_current_block, -stride)) {
235  // candidate found, current_block + stride
236  Addr pf_addr;
237  if (current_block + stride >= lines_per_zone) {
238  // The index (current_block + stride) falls in the range of
239  // the next zone (am_entry_next), adjust the address
240  // accordingly
241  Addr blk = (states_current_block + stride) % lines_per_zone;
242  pf_addr = (am_addr + 1) * hotZoneSize + blk * blkSize;
243  setEntryState(*am_entry_next, blk, AM_PREFETCH);
244  } else {
245  // The index (current_block + stride) falls within
246  // am_entry_curr
247  Addr blk = current_block + stride;
248  pf_addr = am_addr * hotZoneSize + blk * blkSize;
249  setEntryState(*am_entry_curr, blk, AM_PREFETCH);
250  }
251  addresses.push_back(Queued::AddrPriority(pf_addr, 0));
252  if (addresses.size() == degree) {
253  break;
254  }
255  }
256  }
257 }
258 
259 AMPM::AMPM(const AMPMPrefetcherParams &p)
260  : Queued(p), ampm(*p.ampm)
261 {
262 }
263 
264 void
266  std::vector<AddrPriority> &addresses)
267 {
268  ampm.calculatePrefetch(pfi, addresses);
269 }
270 
271 } // namespace prefetch
272 } // namespace gem5
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Tick cyclesToTicks(Cycles c) const
AMPM(const AMPMPrefetcherParams &p)
void calculatePrefetch(const PrefetchInfo &pfi, std::vector< AddrPriority > &addresses) override
AccessMapPatternMatching & ampm
AccessMapState
Data type representing the state of a cacheline in the access map.
uint64_t numGoodPrefetches
Number of good prefetches.
AccessMapPatternMatching(const AccessMapPatternMatchingParams &p)
uint64_t numTotalPrefetches
Number of prefetches issued.
const double highCoverageThreshold
A prefetch coverage factor bigger than this is considered high.
uint64_t numRawCacheMisses
Number of raw cache misses.
const Tick offChipMemoryLatency
Off chip memory latency to use for the epoch bandwidth calculation.
AssociativeSet< AccessMapEntry > accessMapTable
Access map table.
const unsigned limitStride
Limit the stride checking to -limitStride/+limitStride.
void startup() override
startup() is the final initialization call before simulation.
const double highCacheHitThreshold
A cache hit ratio bigger than this is considered high.
void processEpochEvent()
This event constitues the epoch of the statistics that keep track of the prefetcher accuracy,...
uint64_t numRawCacheHits
Number of raw cache hits.
const double lowAccuracyThreshold
A prefetch accuracy factor smaller than this is considered low.
const double lowCacheHitThreshold
A cache hit ratio smaller than this is considered low.
const double highAccuracyThreshold
A prefetch accuracy factor bigger than this is considered high.
void setEntryState(AccessMapEntry &entry, Addr block, enum AccessMapState state)
Updates the state of a block within an AccessMapEntry, also updates the prefetcher metrics.
bool checkCandidate(std::vector< AccessMapState > const &states, Addr current, int stride) const
Given a target cacheline, this function checks if the cachelines that follow the provided stride have...
const unsigned blkSize
Cacheline size used by the prefetcher using this object.
const double lowCoverageThreshold
A prefetch coverage factor smaller than this is considered low.
void calculatePrefetch(const Base::PrefetchInfo &pfi, std::vector< Queued::AddrPriority > &addresses)
const Cycles epochCycles
Cycles in an epoch period.
AccessMapEntry * getAccessMapEntry(Addr am_addr, bool is_secure)
Obtain an AccessMapEntry from the AccessMapTable, if the entry is not found a new one is initialized ...
const uint64_t hotZoneSize
Amount of memory covered by a hot zone.
Class containing the information needed by the prefetch to train and generate new prefetch requests.
Definition: base.hh:98
bool isSecure() const
Returns true if the address targets the secure memory space.
Definition: base.hh:134
Addr getAddr() const
Obtains the address value of this Prefetcher address.
Definition: base.hh:125
STL pair class.
Definition: stl.hh:58
STL vector class.
Definition: stl.hh:37
static constexpr bool isPowerOf2(const T &n)
Definition: intmath.hh:98
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
atomic_var_t state
Definition: helpers.cc:188
Bitfield< 21, 20 > stride
Definition: misc_types.hh:453
Bitfield< 54 > p
Definition: pagetable.hh:70
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
const Addr MaxAddr
Definition: types.hh:171
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
std::vector< AccessMapState > states
vector containing the state of the cachelines in this zone
const std::string & name()
Definition: trace.cc:49

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