snoop_filter.cc (10883:9294c4a60251) snoop_filter.cc (11128:b6532152a64a)
1/*
1/*
2 * Copyright (c) 2013 ARM Limited
2 * Copyright (c) 2013-2015 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
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Stephan Diestelhorst <stephan.diestelhorst@arm.com>
38 */
39
40/**
41 * @file
42 * Definition of a snoop filter.
43 */
44
45#include "base/misc.hh"
46#include "base/trace.hh"
47#include "debug/SnoopFilter.hh"
48#include "mem/snoop_filter.hh"
49#include "sim/system.hh"
50
51std::pair<SnoopFilter::SnoopList, Cycles>
52SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
53{
54 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
55 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
56
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
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Stephan Diestelhorst <stephan.diestelhorst@arm.com>
38 */
39
40/**
41 * @file
42 * Definition of a snoop filter.
43 */
44
45#include "base/misc.hh"
46#include "base/trace.hh"
47#include "debug/SnoopFilter.hh"
48#include "mem/snoop_filter.hh"
49#include "sim/system.hh"
50
51std::pair<SnoopFilter::SnoopList, Cycles>
52SnoopFilter::lookupRequest(const Packet* cpkt, const SlavePort& slave_port)
53{
54 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
55 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
56
57 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
57 // Ultimately we should check if the packet came from an
58 // allocating source, not just if the port is snooping
59 bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping();
60 Addr line_addr = cpkt->getBlockAddr(linesize);
58 SnoopMask req_port = portToMask(slave_port);
59 auto sf_it = cachedLocations.find(line_addr);
60 bool is_hit = (sf_it != cachedLocations.end());
61 SnoopMask req_port = portToMask(slave_port);
62 auto sf_it = cachedLocations.find(line_addr);
63 bool is_hit = (sf_it != cachedLocations.end());
64
65 // If the snoop filter has no entry, and we should not allocate,
66 // do not create a new snoop filter entry, simply return a NULL
67 // portlist.
68 if (!is_hit && !allocate)
69 return snoopDown(lookupLatency);
70
61 // Create a new element through operator[] and modify in-place
62 SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
63 SnoopMask interested = sf_item.holder | sf_item.requested;
64
65 totRequests++;
66 if (is_hit) {
67 // Single bit set -> value is a power of two
68 if (isPow2(interested))
69 hitSingleRequests++;
70 else
71 hitMultiRequests++;
72 }
73
74 DPRINTF(SnoopFilter, "%s: SF value %x.%x\n",
75 __func__, sf_item.requested, sf_item.holder);
76
71 // Create a new element through operator[] and modify in-place
72 SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
73 SnoopMask interested = sf_item.holder | sf_item.requested;
74
75 totRequests++;
76 if (is_hit) {
77 // Single bit set -> value is a power of two
78 if (isPow2(interested))
79 hitSingleRequests++;
80 else
81 hitMultiRequests++;
82 }
83
84 DPRINTF(SnoopFilter, "%s: SF value %x.%x\n",
85 __func__, sf_item.requested, sf_item.holder);
86
77 if (!cpkt->req->isUncacheable() && cpkt->needsResponse()) {
87 if (allocate && cpkt->needsResponse()) {
78 if (!cpkt->memInhibitAsserted()) {
79 // Max one request per address per port
80 panic_if(sf_item.requested & req_port, "double request :( "\
81 "SF value %x.%x\n", sf_item.requested, sf_item.holder);
82
83 // Mark in-flight requests to distinguish later on
84 sf_item.requested |= req_port;
85 } else {
86 // NOTE: The memInhibit might have been asserted by a cache closer
87 // to the CPU, already -> the response will not be seen by this
88 // filter -> we do not need to keep the in-flight request, but make
89 // sure that we know that that cluster has a copy
90 panic_if(!(sf_item.holder & req_port), "Need to hold the value!");
91 DPRINTF(SnoopFilter, "%s: not marking request. SF value %x.%x\n",
92 __func__, sf_item.requested, sf_item.holder);
93 }
94 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
95 __func__, sf_item.requested, sf_item.holder);
96 }
97 return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency);
98}
99
100void
101SnoopFilter::updateRequest(const Packet* cpkt, const SlavePort& slave_port,
102 bool will_retry)
103{
104 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
105 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
106
88 if (!cpkt->memInhibitAsserted()) {
89 // Max one request per address per port
90 panic_if(sf_item.requested & req_port, "double request :( "\
91 "SF value %x.%x\n", sf_item.requested, sf_item.holder);
92
93 // Mark in-flight requests to distinguish later on
94 sf_item.requested |= req_port;
95 } else {
96 // NOTE: The memInhibit might have been asserted by a cache closer
97 // to the CPU, already -> the response will not be seen by this
98 // filter -> we do not need to keep the in-flight request, but make
99 // sure that we know that that cluster has a copy
100 panic_if(!(sf_item.holder & req_port), "Need to hold the value!");
101 DPRINTF(SnoopFilter, "%s: not marking request. SF value %x.%x\n",
102 __func__, sf_item.requested, sf_item.holder);
103 }
104 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
105 __func__, sf_item.requested, sf_item.holder);
106 }
107 return snoopSelected(maskToPortList(interested & ~req_port), lookupLatency);
108}
109
110void
111SnoopFilter::updateRequest(const Packet* cpkt, const SlavePort& slave_port,
112 bool will_retry)
113{
114 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
115 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
116
107 if (cpkt->req->isUncacheable())
117 // Ultimately we should check if the packet came from an
118 // allocating source, not just if the port is snooping
119 bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping();
120 if (!allocate)
108 return;
109
121 return;
122
110 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
123 Addr line_addr = cpkt->getBlockAddr(linesize);
111 SnoopMask req_port = portToMask(slave_port);
112 SnoopItem& sf_item = cachedLocations[line_addr];
113
114 DPRINTF(SnoopFilter, "%s: old SF value %x.%x retry: %i\n",
115 __func__, sf_item.requested, sf_item.holder, will_retry);
116
117 if (will_retry) {
118 // Unmark a request that will come again.
119 sf_item.requested &= ~req_port;
120 return;
121 }
122
123 // will_retry == false
124 if (!cpkt->needsResponse()) {
125 // Packets that will not evoke a response but still need updates of the
126 // snoop filter; WRITEBACKs for now only
127 if (cpkt->cmd == MemCmd::Writeback) {
128 // make sure that the sender actually had the line
129 panic_if(sf_item.requested & req_port, "double request :( "\
130 "SF value %x.%x\n", sf_item.requested, sf_item.holder);
131 panic_if(!(sf_item.holder & req_port), "requester %x is not a "\
132 "holder :( SF value %x.%x\n", req_port,
133 sf_item.requested, sf_item.holder);
134 // Writebacks -> the sender does not have the line anymore
135 sf_item.holder &= ~req_port;
136 } else {
137 // @todo Add CleanEvicts
138 assert(cpkt->cmd == MemCmd::CleanEvict);
139 }
140 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
141 __func__, sf_item.requested, sf_item.holder);
142 }
143}
144
145std::pair<SnoopFilter::SnoopList, Cycles>
146SnoopFilter::lookupSnoop(const Packet* cpkt)
147{
148 DPRINTF(SnoopFilter, "%s: packet addr 0x%x cmd %s\n",
149 __func__, cpkt->getAddr(), cpkt->cmdString());
150
151 assert(cpkt->isRequest());
152
153 // Broadcast / filter upward snoops
154 const bool filter_upward = true; // @todo: Make configurable
155
156 if (!filter_upward)
157 return snoopAll(lookupLatency);
158
124 SnoopMask req_port = portToMask(slave_port);
125 SnoopItem& sf_item = cachedLocations[line_addr];
126
127 DPRINTF(SnoopFilter, "%s: old SF value %x.%x retry: %i\n",
128 __func__, sf_item.requested, sf_item.holder, will_retry);
129
130 if (will_retry) {
131 // Unmark a request that will come again.
132 sf_item.requested &= ~req_port;
133 return;
134 }
135
136 // will_retry == false
137 if (!cpkt->needsResponse()) {
138 // Packets that will not evoke a response but still need updates of the
139 // snoop filter; WRITEBACKs for now only
140 if (cpkt->cmd == MemCmd::Writeback) {
141 // make sure that the sender actually had the line
142 panic_if(sf_item.requested & req_port, "double request :( "\
143 "SF value %x.%x\n", sf_item.requested, sf_item.holder);
144 panic_if(!(sf_item.holder & req_port), "requester %x is not a "\
145 "holder :( SF value %x.%x\n", req_port,
146 sf_item.requested, sf_item.holder);
147 // Writebacks -> the sender does not have the line anymore
148 sf_item.holder &= ~req_port;
149 } else {
150 // @todo Add CleanEvicts
151 assert(cpkt->cmd == MemCmd::CleanEvict);
152 }
153 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
154 __func__, sf_item.requested, sf_item.holder);
155 }
156}
157
158std::pair<SnoopFilter::SnoopList, Cycles>
159SnoopFilter::lookupSnoop(const Packet* cpkt)
160{
161 DPRINTF(SnoopFilter, "%s: packet addr 0x%x cmd %s\n",
162 __func__, cpkt->getAddr(), cpkt->cmdString());
163
164 assert(cpkt->isRequest());
165
166 // Broadcast / filter upward snoops
167 const bool filter_upward = true; // @todo: Make configurable
168
169 if (!filter_upward)
170 return snoopAll(lookupLatency);
171
159 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
172 Addr line_addr = cpkt->getBlockAddr(linesize);
160 auto sf_it = cachedLocations.find(line_addr);
161 bool is_hit = (sf_it != cachedLocations.end());
162 // Create a new element through operator[] and modify in-place
163 SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
164
165 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
166 __func__, sf_item.requested, sf_item.holder);
167
168 SnoopMask interested = (sf_item.holder | sf_item.requested);
169
170 totSnoops++;
171 if (is_hit) {
172 // Single bit set -> value is a power of two
173 if (isPow2(interested))
174 hitSingleSnoops++;
175 else
176 hitMultiSnoops++;
177 }
178 // ReadEx and Writes require both invalidation and exlusivity, while reads
179 // require neither. Writebacks on the other hand require exclusivity but
180 // not the invalidation. Previously Writebacks did not generate upward
181 // snoops so this was never an aissue. Now that Writebacks generate snoops
182 // we need to special case for Writebacks.
183 assert(cpkt->cmd == MemCmd::Writeback ||
184 (cpkt->isInvalidate() == cpkt->needsExclusive()));
185 if (cpkt->isInvalidate() && !sf_item.requested) {
186 // Early clear of the holder, if no other request is currently going on
187 // @todo: This should possibly be updated even though we do not filter
188 // upward snoops
189 sf_item.holder = 0;
190 }
191
192 DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n",
193 __func__, sf_item.requested, sf_item.holder, interested);
194
195 return snoopSelected(maskToPortList(interested), lookupLatency);
196}
197
198void
199SnoopFilter::updateSnoopResponse(const Packet* cpkt,
200 const SlavePort& rsp_port,
201 const SlavePort& req_port)
202{
203 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
204 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
205 cpkt->cmdString());
206
207 assert(cpkt->isResponse());
208 assert(cpkt->memInhibitAsserted());
209
173 auto sf_it = cachedLocations.find(line_addr);
174 bool is_hit = (sf_it != cachedLocations.end());
175 // Create a new element through operator[] and modify in-place
176 SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
177
178 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
179 __func__, sf_item.requested, sf_item.holder);
180
181 SnoopMask interested = (sf_item.holder | sf_item.requested);
182
183 totSnoops++;
184 if (is_hit) {
185 // Single bit set -> value is a power of two
186 if (isPow2(interested))
187 hitSingleSnoops++;
188 else
189 hitMultiSnoops++;
190 }
191 // ReadEx and Writes require both invalidation and exlusivity, while reads
192 // require neither. Writebacks on the other hand require exclusivity but
193 // not the invalidation. Previously Writebacks did not generate upward
194 // snoops so this was never an aissue. Now that Writebacks generate snoops
195 // we need to special case for Writebacks.
196 assert(cpkt->cmd == MemCmd::Writeback ||
197 (cpkt->isInvalidate() == cpkt->needsExclusive()));
198 if (cpkt->isInvalidate() && !sf_item.requested) {
199 // Early clear of the holder, if no other request is currently going on
200 // @todo: This should possibly be updated even though we do not filter
201 // upward snoops
202 sf_item.holder = 0;
203 }
204
205 DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n",
206 __func__, sf_item.requested, sf_item.holder, interested);
207
208 return snoopSelected(maskToPortList(interested), lookupLatency);
209}
210
211void
212SnoopFilter::updateSnoopResponse(const Packet* cpkt,
213 const SlavePort& rsp_port,
214 const SlavePort& req_port)
215{
216 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
217 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
218 cpkt->cmdString());
219
220 assert(cpkt->isResponse());
221 assert(cpkt->memInhibitAsserted());
222
210 if (cpkt->req->isUncacheable())
223 // Ultimately we should check if the packet came from an
224 // allocating source, not just if the port is snooping
225 bool allocate = !cpkt->req->isUncacheable() && req_port.isSnooping();
226 if (!allocate)
211 return;
212
227 return;
228
213 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
229 Addr line_addr = cpkt->getBlockAddr(linesize);
214 SnoopMask rsp_mask = portToMask(rsp_port);
215 SnoopMask req_mask = portToMask(req_port);
216 SnoopItem& sf_item = cachedLocations[line_addr];
217
218 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
219 __func__, sf_item.requested, sf_item.holder);
220
221 // The source should have the line
222 panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
223 "the line\n", sf_item.requested, sf_item.holder);
224
225 // The destination should have had a request in
226 panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
227 "the original request\n", sf_item.requested, sf_item.holder);
228
229 // Update the residency of the cache line.
230 if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) {
231 DPRINTF(SnoopFilter, "%s: dropping %x because needs: %i shared: %i "\
232 "SF val: %x.%x\n", __func__, rsp_mask,
233 cpkt->needsExclusive(), cpkt->sharedAsserted(),
234 sf_item.requested, sf_item.holder);
235
236 sf_item.holder &= ~rsp_mask;
237 // The snoop filter does not see any ACKs from non-responding sharers
238 // that have been invalidated :( So below assert would be nice, but..
239 //assert(sf_item.holder == 0);
240 sf_item.holder = 0;
241 }
242 assert(cpkt->cmd != MemCmd::Writeback);
243 sf_item.holder |= req_mask;
244 sf_item.requested &= ~req_mask;
245 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
246 __func__, sf_item.requested, sf_item.holder);
247}
248
249void
250SnoopFilter::updateSnoopForward(const Packet* cpkt,
251 const SlavePort& rsp_port, const MasterPort& req_port)
252{
253 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
254 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
255 cpkt->cmdString());
256
230 SnoopMask rsp_mask = portToMask(rsp_port);
231 SnoopMask req_mask = portToMask(req_port);
232 SnoopItem& sf_item = cachedLocations[line_addr];
233
234 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
235 __func__, sf_item.requested, sf_item.holder);
236
237 // The source should have the line
238 panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
239 "the line\n", sf_item.requested, sf_item.holder);
240
241 // The destination should have had a request in
242 panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
243 "the original request\n", sf_item.requested, sf_item.holder);
244
245 // Update the residency of the cache line.
246 if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) {
247 DPRINTF(SnoopFilter, "%s: dropping %x because needs: %i shared: %i "\
248 "SF val: %x.%x\n", __func__, rsp_mask,
249 cpkt->needsExclusive(), cpkt->sharedAsserted(),
250 sf_item.requested, sf_item.holder);
251
252 sf_item.holder &= ~rsp_mask;
253 // The snoop filter does not see any ACKs from non-responding sharers
254 // that have been invalidated :( So below assert would be nice, but..
255 //assert(sf_item.holder == 0);
256 sf_item.holder = 0;
257 }
258 assert(cpkt->cmd != MemCmd::Writeback);
259 sf_item.holder |= req_mask;
260 sf_item.requested &= ~req_mask;
261 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
262 __func__, sf_item.requested, sf_item.holder);
263}
264
265void
266SnoopFilter::updateSnoopForward(const Packet* cpkt,
267 const SlavePort& rsp_port, const MasterPort& req_port)
268{
269 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
270 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
271 cpkt->cmdString());
272
257 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
273 Addr line_addr = cpkt->getBlockAddr(linesize);
258 SnoopItem& sf_item = cachedLocations[line_addr];
259 SnoopMask rsp_mask M5_VAR_USED = portToMask(rsp_port);
260
261 assert(cpkt->isResponse());
262 assert(cpkt->memInhibitAsserted());
263
264 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
265 __func__, sf_item.requested, sf_item.holder);
266
267 // Remote (to this snoop filter) snoops update the filter already when they
268 // arrive from below, because we may not see any response.
269 if (cpkt->needsExclusive()) {
270 // If the request to this snoop response hit an in-flight transaction,
271 // the holder was not reset -> no assertion & do that here, now!
272 //assert(sf_item.holder == 0);
273 sf_item.holder = 0;
274 }
275 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
276 __func__, sf_item.requested, sf_item.holder);
277}
278
279void
280SnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
281{
282 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
283 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
284
285 assert(cpkt->isResponse());
286
274 SnoopItem& sf_item = cachedLocations[line_addr];
275 SnoopMask rsp_mask M5_VAR_USED = portToMask(rsp_port);
276
277 assert(cpkt->isResponse());
278 assert(cpkt->memInhibitAsserted());
279
280 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
281 __func__, sf_item.requested, sf_item.holder);
282
283 // Remote (to this snoop filter) snoops update the filter already when they
284 // arrive from below, because we may not see any response.
285 if (cpkt->needsExclusive()) {
286 // If the request to this snoop response hit an in-flight transaction,
287 // the holder was not reset -> no assertion & do that here, now!
288 //assert(sf_item.holder == 0);
289 sf_item.holder = 0;
290 }
291 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
292 __func__, sf_item.requested, sf_item.holder);
293}
294
295void
296SnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
297{
298 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
299 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
300
301 assert(cpkt->isResponse());
302
287 if (cpkt->req->isUncacheable())
303 // Ultimately we should check if the packet came from an
304 // allocating source, not just if the port is snooping
305 bool allocate = !cpkt->req->isUncacheable() && slave_port.isSnooping();
306 if (!allocate)
288 return;
289
307 return;
308
290 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
309 Addr line_addr = cpkt->getBlockAddr(linesize);
291 SnoopMask slave_mask = portToMask(slave_port);
292 SnoopItem& sf_item = cachedLocations[line_addr];
293
294 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
295 __func__, sf_item.requested, sf_item.holder);
296
297 // Make sure we have seen the actual request, too
298 panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
299 "request bit\n", sf_item.requested, sf_item.holder);
300
301 // Update the residency of the cache line.
302 if (cpkt->needsExclusive() || !cpkt->sharedAsserted())
303 sf_item.holder = 0;
304 sf_item.holder |= slave_mask;
305 sf_item.requested &= ~slave_mask;
306 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
307 __func__, sf_item.requested, sf_item.holder);
308}
309
310void
311SnoopFilter::regStats()
312{
313 totRequests
314 .name(name() + ".tot_requests")
315 .desc("Total number of requests made to the snoop filter.");
316
317 hitSingleRequests
318 .name(name() + ".hit_single_requests")
319 .desc("Number of requests hitting in the snoop filter with a single "\
320 "holder of the requested data.");
321
322 hitMultiRequests
323 .name(name() + ".hit_multi_requests")
324 .desc("Number of requests hitting in the snoop filter with multiple "\
325 "(>1) holders of the requested data.");
326
327 totSnoops
328 .name(name() + ".tot_snoops")
329 .desc("Total number of snoops made to the snoop filter.");
330
331 hitSingleSnoops
332 .name(name() + ".hit_single_snoops")
333 .desc("Number of snoops hitting in the snoop filter with a single "\
334 "holder of the requested data.");
335
336 hitMultiSnoops
337 .name(name() + ".hit_multi_snoops")
338 .desc("Number of snoops hitting in the snoop filter with multiple "\
339 "(>1) holders of the requested data.");
340}
341
342SnoopFilter *
343SnoopFilterParams::create()
344{
345 return new SnoopFilter(this);
346}
310 SnoopMask slave_mask = portToMask(slave_port);
311 SnoopItem& sf_item = cachedLocations[line_addr];
312
313 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
314 __func__, sf_item.requested, sf_item.holder);
315
316 // Make sure we have seen the actual request, too
317 panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
318 "request bit\n", sf_item.requested, sf_item.holder);
319
320 // Update the residency of the cache line.
321 if (cpkt->needsExclusive() || !cpkt->sharedAsserted())
322 sf_item.holder = 0;
323 sf_item.holder |= slave_mask;
324 sf_item.requested &= ~slave_mask;
325 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
326 __func__, sf_item.requested, sf_item.holder);
327}
328
329void
330SnoopFilter::regStats()
331{
332 totRequests
333 .name(name() + ".tot_requests")
334 .desc("Total number of requests made to the snoop filter.");
335
336 hitSingleRequests
337 .name(name() + ".hit_single_requests")
338 .desc("Number of requests hitting in the snoop filter with a single "\
339 "holder of the requested data.");
340
341 hitMultiRequests
342 .name(name() + ".hit_multi_requests")
343 .desc("Number of requests hitting in the snoop filter with multiple "\
344 "(>1) holders of the requested data.");
345
346 totSnoops
347 .name(name() + ".tot_snoops")
348 .desc("Total number of snoops made to the snoop filter.");
349
350 hitSingleSnoops
351 .name(name() + ".hit_single_snoops")
352 .desc("Number of snoops hitting in the snoop filter with a single "\
353 "holder of the requested data.");
354
355 hitMultiSnoops
356 .name(name() + ".hit_multi_snoops")
357 .desc("Number of snoops hitting in the snoop filter with multiple "\
358 "(>1) holders of the requested data.");
359}
360
361SnoopFilter *
362SnoopFilterParams::create()
363{
364 return new SnoopFilter(this);
365}