snoop_filter.cc (12429:beefb9f5f551) snoop_filter.cc (14005:6cad91d6136c)
1/*
1/*
2 * Copyright (c) 2013-2017 ARM Limited
2 * Copyright (c) 2013-2017,2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 33 unchanged lines hidden (view full) ---

44
45#include "mem/snoop_filter.hh"
46
47#include "base/logging.hh"
48#include "base/trace.hh"
49#include "debug/SnoopFilter.hh"
50#include "sim/system.hh"
51
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 33 unchanged lines hidden (view full) ---

44
45#include "mem/snoop_filter.hh"
46
47#include "base/logging.hh"
48#include "base/trace.hh"
49#include "debug/SnoopFilter.hh"
50#include "sim/system.hh"
51
52const int SnoopFilter::SNOOP_MASK_SIZE;
53
52void
53SnoopFilter::eraseIfNullEntry(SnoopFilterCache::iterator& sf_it)
54{
55 SnoopItem& sf_item = sf_it->second;
54void
55SnoopFilter::eraseIfNullEntry(SnoopFilterCache::iterator& sf_it)
56{
57 SnoopItem& sf_item = sf_it->second;
56 if (!(sf_item.requested | sf_item.holder)) {
58 if ((sf_item.requested | sf_item.holder).none()) {
57 cachedLocations.erase(sf_it);
58 DPRINTF(SnoopFilter, "%s: Removed SF entry.\n",
59 __func__);
60 }
61}
62
63std::pair<SnoopFilter::SnoopList, Cycles>
64SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)

--- 26 unchanged lines hidden (view full) ---

91
92 // Store unmodified value of snoop filter item in temp storage in
93 // case we need to revert because of a send retry in
94 // updateRequest.
95 retryItem = sf_item;
96
97 totRequests++;
98 if (is_hit) {
59 cachedLocations.erase(sf_it);
60 DPRINTF(SnoopFilter, "%s: Removed SF entry.\n",
61 __func__);
62 }
63}
64
65std::pair<SnoopFilter::SnoopList, Cycles>
66SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)

--- 26 unchanged lines hidden (view full) ---

93
94 // Store unmodified value of snoop filter item in temp storage in
95 // case we need to revert because of a send retry in
96 // updateRequest.
97 retryItem = sf_item;
98
99 totRequests++;
100 if (is_hit) {
99 // Single bit set -> value is a power of two
100 if (isPow2(interested))
101 if (interested.count() == 1)
101 hitSingleRequests++;
102 else
103 hitMultiRequests++;
104 }
105
106 DPRINTF(SnoopFilter, "%s: SF value %x.%x\n",
107 __func__, sf_item.requested, sf_item.holder);
108
109 // If we are not allocating, we are done
110 if (!allocate)
111 return snoopSelected(maskToPortList(interested & ~req_port),
112 lookupLatency);
113
114 if (cpkt->needsResponse()) {
115 if (!cpkt->cacheResponding()) {
116 // Max one request per address per port
102 hitSingleRequests++;
103 else
104 hitMultiRequests++;
105 }
106
107 DPRINTF(SnoopFilter, "%s: SF value %x.%x\n",
108 __func__, sf_item.requested, sf_item.holder);
109
110 // If we are not allocating, we are done
111 if (!allocate)
112 return snoopSelected(maskToPortList(interested & ~req_port),
113 lookupLatency);
114
115 if (cpkt->needsResponse()) {
116 if (!cpkt->cacheResponding()) {
117 // Max one request per address per port
117 panic_if(sf_item.requested & req_port, "double request :( " \
118 "SF value %x.%x\n", sf_item.requested, sf_item.holder);
118 panic_if((sf_item.requested & req_port).any(),
119 "double request :( SF value %x.%x\n",
120 sf_item.requested, sf_item.holder);
119
120 // Mark in-flight requests to distinguish later on
121 sf_item.requested |= req_port;
122 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
123 __func__, sf_item.requested, sf_item.holder);
124 } else {
125 // NOTE: The memInhibit might have been asserted by a cache closer
126 // to the CPU, already -> the response will not be seen by this
127 // filter -> we do not need to keep the in-flight request, but make
128 // sure that we know that that cluster has a copy
121
122 // Mark in-flight requests to distinguish later on
123 sf_item.requested |= req_port;
124 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
125 __func__, sf_item.requested, sf_item.holder);
126 } else {
127 // NOTE: The memInhibit might have been asserted by a cache closer
128 // to the CPU, already -> the response will not be seen by this
129 // filter -> we do not need to keep the in-flight request, but make
130 // sure that we know that that cluster has a copy
129 panic_if(!(sf_item.holder & req_port), "Need to hold the value!");
131 panic_if((sf_item.holder & req_port).none(),
132 "Need to hold the value!");
130 DPRINTF(SnoopFilter,
131 "%s: not marking request. SF value %x.%x\n",
132 __func__, sf_item.requested, sf_item.holder);
133 }
134 } else { // if (!cpkt->needsResponse())
135 assert(cpkt->isEviction());
136 // make sure that the sender actually had the line
133 DPRINTF(SnoopFilter,
134 "%s: not marking request. SF value %x.%x\n",
135 __func__, sf_item.requested, sf_item.holder);
136 }
137 } else { // if (!cpkt->needsResponse())
138 assert(cpkt->isEviction());
139 // make sure that the sender actually had the line
137 panic_if(!(sf_item.holder & req_port), "requester %x is not a " \
140 panic_if((sf_item.holder & req_port).none(), "requester %x is not a " \
138 "holder :( SF value %x.%x\n", req_port,
139 sf_item.requested, sf_item.holder);
140 // CleanEvicts and Writebacks -> the sender and all caches above
141 // it may not have the line anymore.
142 if (!cpkt->isBlockCached()) {
143 sf_item.holder &= ~req_port;
144 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
145 __func__, sf_item.requested, sf_item.holder);

--- 55 unchanged lines hidden (view full) ---

201 SnoopItem& sf_item = sf_it->second;
202
203 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
204 __func__, sf_item.requested, sf_item.holder);
205
206 SnoopMask interested = (sf_item.holder | sf_item.requested);
207
208 totSnoops++;
141 "holder :( SF value %x.%x\n", req_port,
142 sf_item.requested, sf_item.holder);
143 // CleanEvicts and Writebacks -> the sender and all caches above
144 // it may not have the line anymore.
145 if (!cpkt->isBlockCached()) {
146 sf_item.holder &= ~req_port;
147 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
148 __func__, sf_item.requested, sf_item.holder);

--- 55 unchanged lines hidden (view full) ---

204 SnoopItem& sf_item = sf_it->second;
205
206 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
207 __func__, sf_item.requested, sf_item.holder);
208
209 SnoopMask interested = (sf_item.holder | sf_item.requested);
210
211 totSnoops++;
209 // Single bit set -> value is a power of two
210 if (isPow2(interested))
212
213 if (interested.count() == 1)
211 hitSingleSnoops++;
212 else
213 hitMultiSnoops++;
214
215 // ReadEx and Writes require both invalidation and exlusivity, while reads
216 // require neither. Writebacks on the other hand require exclusivity but
217 // not the invalidation. Previously Writebacks did not generate upward
218 // snoops so this was never an issue. Now that Writebacks generate snoops
219 // we need a special case for Writebacks. Additionally cache maintenance
220 // operations can generate snoops as they clean and/or invalidate all
221 // caches down to the specified point of reference.
222 assert(cpkt->isWriteback() || cpkt->req->isUncacheable() ||
223 (cpkt->isInvalidate() == cpkt->needsWritable()) ||
224 cpkt->req->isCacheMaintenance());
214 hitSingleSnoops++;
215 else
216 hitMultiSnoops++;
217
218 // ReadEx and Writes require both invalidation and exlusivity, while reads
219 // require neither. Writebacks on the other hand require exclusivity but
220 // not the invalidation. Previously Writebacks did not generate upward
221 // snoops so this was never an issue. Now that Writebacks generate snoops
222 // we need a special case for Writebacks. Additionally cache maintenance
223 // operations can generate snoops as they clean and/or invalidate all
224 // caches down to the specified point of reference.
225 assert(cpkt->isWriteback() || cpkt->req->isUncacheable() ||
226 (cpkt->isInvalidate() == cpkt->needsWritable()) ||
227 cpkt->req->isCacheMaintenance());
225 if (cpkt->isInvalidate() && !sf_item.requested) {
228 if (cpkt->isInvalidate() && sf_item.requested.none()) {
226 // Early clear of the holder, if no other request is currently going on
227 // @todo: This should possibly be updated even though we do not filter
228 // upward snoops
229 sf_item.holder = 0;
230 }
231
232 eraseIfNullEntry(sf_it);
233 DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n",

--- 27 unchanged lines hidden (view full) ---

261 SnoopMask rsp_mask = portToMask(rsp_port);
262 SnoopMask req_mask = portToMask(req_port);
263 SnoopItem& sf_item = cachedLocations[line_addr];
264
265 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
266 __func__, sf_item.requested, sf_item.holder);
267
268 // The source should have the line
229 // Early clear of the holder, if no other request is currently going on
230 // @todo: This should possibly be updated even though we do not filter
231 // upward snoops
232 sf_item.holder = 0;
233 }
234
235 eraseIfNullEntry(sf_it);
236 DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n",

--- 27 unchanged lines hidden (view full) ---

264 SnoopMask rsp_mask = portToMask(rsp_port);
265 SnoopMask req_mask = portToMask(req_port);
266 SnoopItem& sf_item = cachedLocations[line_addr];
267
268 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
269 __func__, sf_item.requested, sf_item.holder);
270
271 // The source should have the line
269 panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
270 "the line\n", sf_item.requested, sf_item.holder);
272 panic_if((sf_item.holder & rsp_mask).none(),
273 "SF value %x.%x does not have the line\n",
274 sf_item.requested, sf_item.holder);
271
272 // The destination should have had a request in
275
276 // The destination should have had a request in
273 panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
277 panic_if((sf_item.requested & req_mask).none(), "SF value %x.%x missing "\
274 "the original request\n", sf_item.requested, sf_item.holder);
275
276 // If the snoop response has no sharers the line is passed in
277 // Modified state, and we know that there are no other copies, or
278 // they will all be invalidated imminently
279 if (!cpkt->hasSharers()) {
280 DPRINTF(SnoopFilter,
281 "%s: dropping %x because non-shared snoop "
282 "response SF val: %x.%x\n", __func__, rsp_mask,
283 sf_item.requested, sf_item.holder);
284 sf_item.holder = 0;
285 }
286 assert(!cpkt->isWriteback());
287 // @todo Deal with invalidating responses
288 sf_item.holder |= req_mask;
289 sf_item.requested &= ~req_mask;
278 "the original request\n", sf_item.requested, sf_item.holder);
279
280 // If the snoop response has no sharers the line is passed in
281 // Modified state, and we know that there are no other copies, or
282 // they will all be invalidated imminently
283 if (!cpkt->hasSharers()) {
284 DPRINTF(SnoopFilter,
285 "%s: dropping %x because non-shared snoop "
286 "response SF val: %x.%x\n", __func__, rsp_mask,
287 sf_item.requested, sf_item.holder);
288 sf_item.holder = 0;
289 }
290 assert(!cpkt->isWriteback());
291 // @todo Deal with invalidating responses
292 sf_item.holder |= req_mask;
293 sf_item.requested &= ~req_mask;
290 assert(sf_item.requested | sf_item.holder);
294 assert((sf_item.requested | sf_item.holder).any());
291 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
292 __func__, sf_item.requested, sf_item.holder);
293}
294
295void
296SnoopFilter::updateSnoopForward(const Packet* cpkt,
297 const SlavePort& rsp_port, const MasterPort& req_port)
298{

--- 55 unchanged lines hidden (view full) ---

354
355 SnoopMask slave_mask = portToMask(slave_port);
356 SnoopItem& sf_item = sf_it->second;
357
358 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
359 __func__, sf_item.requested, sf_item.holder);
360
361 // Make sure we have seen the actual request, too
295 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
296 __func__, sf_item.requested, sf_item.holder);
297}
298
299void
300SnoopFilter::updateSnoopForward(const Packet* cpkt,
301 const SlavePort& rsp_port, const MasterPort& req_port)
302{

--- 55 unchanged lines hidden (view full) ---

358
359 SnoopMask slave_mask = portToMask(slave_port);
360 SnoopItem& sf_item = sf_it->second;
361
362 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
363 __func__, sf_item.requested, sf_item.holder);
364
365 // Make sure we have seen the actual request, too
362 panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
363 "request bit\n", sf_item.requested, sf_item.holder);
366 panic_if((sf_item.requested & slave_mask).none(),
367 "SF value %x.%x missing request bit\n",
368 sf_item.requested, sf_item.holder);
364
365 sf_item.requested &= ~slave_mask;
366 // Update the residency of the cache line.
367
368 if (cpkt->req->isCacheMaintenance()) {
369 // A cache clean response does not carry any data so it
370 // shouldn't change the holders, unless it is invalidating.
371 if (cpkt->isInvalidate()) {
372 sf_item.holder &= ~slave_mask;
373 }
374 eraseIfNullEntry(sf_it);
375 } else {
376 // Any other response implies that a cache above will have the
377 // block.
378 sf_item.holder |= slave_mask;
369
370 sf_item.requested &= ~slave_mask;
371 // Update the residency of the cache line.
372
373 if (cpkt->req->isCacheMaintenance()) {
374 // A cache clean response does not carry any data so it
375 // shouldn't change the holders, unless it is invalidating.
376 if (cpkt->isInvalidate()) {
377 sf_item.holder &= ~slave_mask;
378 }
379 eraseIfNullEntry(sf_it);
380 } else {
381 // Any other response implies that a cache above will have the
382 // block.
383 sf_item.holder |= slave_mask;
379 assert(sf_item.holder | sf_item.requested);
384 assert((sf_item.holder | sf_item.requested).any());
380 }
381 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
382 __func__, sf_item.requested, sf_item.holder);
383}
384
385void
386SnoopFilter::regStats()
387{

--- 36 unchanged lines hidden ---
385 }
386 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
387 __func__, sf_item.requested, sf_item.holder);
388}
389
390void
391SnoopFilter::regStats()
392{

--- 36 unchanged lines hidden ---