snoop_filter.cc (10403:b3231fc8ae9d) snoop_filter.cc (10821:581fb2484bd6)
1/*
2 * Copyright (c) 2013 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
57 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
58 SnoopMask req_port = portToMask(slave_port);
59 auto sf_it = cachedLocations.find(line_addr);
60 bool is_hit = (sf_it != cachedLocations.end());
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
1/*
2 * Copyright (c) 2013 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
57 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
58 SnoopMask req_port = portToMask(slave_port);
59 auto sf_it = cachedLocations.find(line_addr);
60 bool is_hit = (sf_it != cachedLocations.end());
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
77 if (cpkt->needsResponse()) {
77 if (!cpkt->req->isUncacheable() && 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
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
107 if (cpkt->req->isUncacheable())
108 return;
109
107 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
108 SnoopMask req_port = portToMask(slave_port);
109 SnoopItem& sf_item = cachedLocations[line_addr];
110
111 DPRINTF(SnoopFilter, "%s: old SF value %x.%x retry: %i\n",
112 __func__, sf_item.requested, sf_item.holder, will_retry);
113
114 if (will_retry) {
115 // Unmark a request that will come again.
116 sf_item.requested &= ~req_port;
117 return;
118 }
119
120 // will_retry == false
121 if (!cpkt->needsResponse()) {
122 // Packets that will not evoke a response but still need updates of the
123 // snoop filter; WRITEBACKs for now only
124 if (cpkt->cmd == MemCmd::Writeback) {
125 // make sure that the sender actually had the line
126 panic_if(sf_item.requested & req_port, "double request :( "\
127 "SF value %x.%x\n", sf_item.requested, sf_item.holder);
128 panic_if(!(sf_item.holder & req_port), "requester %x is not a "\
129 "holder :( SF value %x.%x\n", req_port,
130 sf_item.requested, sf_item.holder);
131 // Writebacks -> the sender does not have the line anymore
132 sf_item.holder &= ~req_port;
133 } else {
134 assert(0 == "Handle non-writeback, here");
135 }
136 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
137 __func__, sf_item.requested, sf_item.holder);
138 }
139}
140
141std::pair<SnoopFilter::SnoopList, Cycles>
142SnoopFilter::lookupSnoop(const Packet* cpkt)
143{
144 DPRINTF(SnoopFilter, "%s: packet addr 0x%x cmd %s\n",
145 __func__, cpkt->getAddr(), cpkt->cmdString());
146
147 assert(cpkt->isRequest());
148
149 // Broadcast / filter upward snoops
150 const bool filter_upward = true; // @todo: Make configurable
151
152 if (!filter_upward)
153 return snoopAll(lookupLatency);
154
155 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
156 auto sf_it = cachedLocations.find(line_addr);
157 bool is_hit = (sf_it != cachedLocations.end());
158 // Create a new element through operator[] and modify in-place
159 SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
160
161 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
162 __func__, sf_item.requested, sf_item.holder);
163
164 SnoopMask interested = (sf_item.holder | sf_item.requested);
165
166 totSnoops++;
167 if (is_hit) {
168 // Single bit set -> value is a power of two
169 if (isPow2(interested))
170 hitSingleSnoops++;
171 else
172 hitMultiSnoops++;
173 }
174
175 assert(cpkt->isInvalidate() == cpkt->needsExclusive());
176 if (cpkt->isInvalidate() && !sf_item.requested) {
177 // Early clear of the holder, if no other request is currently going on
178 // @todo: This should possibly be updated even though we do not filter
179 // upward snoops
180 sf_item.holder = 0;
181 }
182
183 DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n",
184 __func__, sf_item.requested, sf_item.holder, interested);
185
186 return snoopSelected(maskToPortList(interested), lookupLatency);
187}
188
189void
190SnoopFilter::updateSnoopResponse(const Packet* cpkt,
191 const SlavePort& rsp_port,
192 const SlavePort& req_port)
193{
194 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
195 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
196 cpkt->cmdString());
197
110 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
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 assert(0 == "Handle non-writeback, here");
138 }
139 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
140 __func__, sf_item.requested, sf_item.holder);
141 }
142}
143
144std::pair<SnoopFilter::SnoopList, Cycles>
145SnoopFilter::lookupSnoop(const Packet* cpkt)
146{
147 DPRINTF(SnoopFilter, "%s: packet addr 0x%x cmd %s\n",
148 __func__, cpkt->getAddr(), cpkt->cmdString());
149
150 assert(cpkt->isRequest());
151
152 // Broadcast / filter upward snoops
153 const bool filter_upward = true; // @todo: Make configurable
154
155 if (!filter_upward)
156 return snoopAll(lookupLatency);
157
158 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
159 auto sf_it = cachedLocations.find(line_addr);
160 bool is_hit = (sf_it != cachedLocations.end());
161 // Create a new element through operator[] and modify in-place
162 SnoopItem& sf_item = is_hit ? sf_it->second : cachedLocations[line_addr];
163
164 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
165 __func__, sf_item.requested, sf_item.holder);
166
167 SnoopMask interested = (sf_item.holder | sf_item.requested);
168
169 totSnoops++;
170 if (is_hit) {
171 // Single bit set -> value is a power of two
172 if (isPow2(interested))
173 hitSingleSnoops++;
174 else
175 hitMultiSnoops++;
176 }
177
178 assert(cpkt->isInvalidate() == cpkt->needsExclusive());
179 if (cpkt->isInvalidate() && !sf_item.requested) {
180 // Early clear of the holder, if no other request is currently going on
181 // @todo: This should possibly be updated even though we do not filter
182 // upward snoops
183 sf_item.holder = 0;
184 }
185
186 DPRINTF(SnoopFilter, "%s: new SF value %x.%x interest: %x \n",
187 __func__, sf_item.requested, sf_item.holder, interested);
188
189 return snoopSelected(maskToPortList(interested), lookupLatency);
190}
191
192void
193SnoopFilter::updateSnoopResponse(const Packet* cpkt,
194 const SlavePort& rsp_port,
195 const SlavePort& req_port)
196{
197 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
198 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
199 cpkt->cmdString());
200
201 assert(cpkt->isResponse());
202 assert(cpkt->memInhibitAsserted());
203
204 if (cpkt->req->isUncacheable())
205 return;
206
198 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
199 SnoopMask rsp_mask = portToMask(rsp_port);
200 SnoopMask req_mask = portToMask(req_port);
201 SnoopItem& sf_item = cachedLocations[line_addr];
202
207 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
208 SnoopMask rsp_mask = portToMask(rsp_port);
209 SnoopMask req_mask = portToMask(req_port);
210 SnoopItem& sf_item = cachedLocations[line_addr];
211
203 assert(cpkt->isResponse());
204 assert(cpkt->memInhibitAsserted());
205
206 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
207 __func__, sf_item.requested, sf_item.holder);
208
209 // The source should have the line
210 panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
211 "the line\n", sf_item.requested, sf_item.holder);
212
213 // The destination should have had a request in
214 panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
215 "the original request\n", sf_item.requested, sf_item.holder);
216
217 // Update the residency of the cache line.
218 if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) {
219 DPRINTF(SnoopFilter, "%s: dropping %x because needs: %i shared: %i "\
220 "SF val: %x.%x\n", __func__, rsp_mask,
221 cpkt->needsExclusive(), cpkt->sharedAsserted(),
222 sf_item.requested, sf_item.holder);
223
224 sf_item.holder &= ~rsp_mask;
225 // The snoop filter does not see any ACKs from non-responding sharers
226 // that have been invalidated :( So below assert would be nice, but..
227 //assert(sf_item.holder == 0);
228 sf_item.holder = 0;
229 }
230 assert(cpkt->cmd != MemCmd::Writeback);
231 sf_item.holder |= req_mask;
232 sf_item.requested &= ~req_mask;
233 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
234 __func__, sf_item.requested, sf_item.holder);
235}
236
237void
238SnoopFilter::updateSnoopForward(const Packet* cpkt,
239 const SlavePort& rsp_port, const MasterPort& req_port)
240{
241 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
242 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
243 cpkt->cmdString());
244
245 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
246 SnoopItem& sf_item = cachedLocations[line_addr];
247 SnoopMask rsp_mask M5_VAR_USED = portToMask(rsp_port);
248
249 assert(cpkt->isResponse());
250 assert(cpkt->memInhibitAsserted());
251
252 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
253 __func__, sf_item.requested, sf_item.holder);
254
255 // Remote (to this snoop filter) snoops update the filter already when they
256 // arrive from below, because we may not see any response.
257 if (cpkt->needsExclusive()) {
258 // If the request to this snoop response hit an in-flight transaction,
259 // the holder was not reset -> no assertion & do that here, now!
260 //assert(sf_item.holder == 0);
261 sf_item.holder = 0;
262 }
263 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
264 __func__, sf_item.requested, sf_item.holder);
265}
266
267void
268SnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
269{
270 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
271 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
272
212 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
213 __func__, sf_item.requested, sf_item.holder);
214
215 // The source should have the line
216 panic_if(!(sf_item.holder & rsp_mask), "SF value %x.%x does not have "\
217 "the line\n", sf_item.requested, sf_item.holder);
218
219 // The destination should have had a request in
220 panic_if(!(sf_item.requested & req_mask), "SF value %x.%x missing "\
221 "the original request\n", sf_item.requested, sf_item.holder);
222
223 // Update the residency of the cache line.
224 if (cpkt->needsExclusive() || !cpkt->sharedAsserted()) {
225 DPRINTF(SnoopFilter, "%s: dropping %x because needs: %i shared: %i "\
226 "SF val: %x.%x\n", __func__, rsp_mask,
227 cpkt->needsExclusive(), cpkt->sharedAsserted(),
228 sf_item.requested, sf_item.holder);
229
230 sf_item.holder &= ~rsp_mask;
231 // The snoop filter does not see any ACKs from non-responding sharers
232 // that have been invalidated :( So below assert would be nice, but..
233 //assert(sf_item.holder == 0);
234 sf_item.holder = 0;
235 }
236 assert(cpkt->cmd != MemCmd::Writeback);
237 sf_item.holder |= req_mask;
238 sf_item.requested &= ~req_mask;
239 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
240 __func__, sf_item.requested, sf_item.holder);
241}
242
243void
244SnoopFilter::updateSnoopForward(const Packet* cpkt,
245 const SlavePort& rsp_port, const MasterPort& req_port)
246{
247 DPRINTF(SnoopFilter, "%s: packet rsp %s req %s addr 0x%x cmd %s\n",
248 __func__, rsp_port.name(), req_port.name(), cpkt->getAddr(),
249 cpkt->cmdString());
250
251 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
252 SnoopItem& sf_item = cachedLocations[line_addr];
253 SnoopMask rsp_mask M5_VAR_USED = portToMask(rsp_port);
254
255 assert(cpkt->isResponse());
256 assert(cpkt->memInhibitAsserted());
257
258 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
259 __func__, sf_item.requested, sf_item.holder);
260
261 // Remote (to this snoop filter) snoops update the filter already when they
262 // arrive from below, because we may not see any response.
263 if (cpkt->needsExclusive()) {
264 // If the request to this snoop response hit an in-flight transaction,
265 // the holder was not reset -> no assertion & do that here, now!
266 //assert(sf_item.holder == 0);
267 sf_item.holder = 0;
268 }
269 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
270 __func__, sf_item.requested, sf_item.holder);
271}
272
273void
274SnoopFilter::updateResponse(const Packet* cpkt, const SlavePort& slave_port)
275{
276 DPRINTF(SnoopFilter, "%s: packet src %s addr 0x%x cmd %s\n",
277 __func__, slave_port.name(), cpkt->getAddr(), cpkt->cmdString());
278
279 assert(cpkt->isResponse());
280
281 if (cpkt->req->isUncacheable())
282 return;
283
273 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
274 SnoopMask slave_mask = portToMask(slave_port);
275 SnoopItem& sf_item = cachedLocations[line_addr];
276
284 Addr line_addr = cpkt->getAddr() & ~(linesize - 1);
285 SnoopMask slave_mask = portToMask(slave_port);
286 SnoopItem& sf_item = cachedLocations[line_addr];
287
277 assert(cpkt->isResponse());
278
279 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
280 __func__, sf_item.requested, sf_item.holder);
281
282 // Make sure we have seen the actual request, too
283 panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
284 "request bit\n", sf_item.requested, sf_item.holder);
285
286 // Update the residency of the cache line.
287 if (cpkt->needsExclusive() || !cpkt->sharedAsserted())
288 sf_item.holder = 0;
289 sf_item.holder |= slave_mask;
290 sf_item.requested &= ~slave_mask;
291 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
292 __func__, sf_item.requested, sf_item.holder);
293}
294
295void
296SnoopFilter::regStats()
297{
298 totRequests
299 .name(name() + ".tot_requests")
300 .desc("Total number of requests made to the snoop filter.");
301
302 hitSingleRequests
303 .name(name() + ".hit_single_requests")
304 .desc("Number of requests hitting in the snoop filter with a single "\
305 "holder of the requested data.");
306
307 hitMultiRequests
308 .name(name() + ".hit_multi_requests")
309 .desc("Number of requests hitting in the snoop filter with multiple "\
310 "(>1) holders of the requested data.");
311
312 totSnoops
313 .name(name() + ".tot_snoops")
314 .desc("Total number of snoops made to the snoop filter.");
315
316 hitSingleSnoops
317 .name(name() + ".hit_single_snoops")
318 .desc("Number of snoops hitting in the snoop filter with a single "\
319 "holder of the requested data.");
320
321 hitMultiSnoops
322 .name(name() + ".hit_multi_snoops")
323 .desc("Number of snoops hitting in the snoop filter with multiple "\
324 "(>1) holders of the requested data.");
325}
326
327SnoopFilter *
328SnoopFilterParams::create()
329{
330 return new SnoopFilter(this);
331}
288 DPRINTF(SnoopFilter, "%s: old SF value %x.%x\n",
289 __func__, sf_item.requested, sf_item.holder);
290
291 // Make sure we have seen the actual request, too
292 panic_if(!(sf_item.requested & slave_mask), "SF value %x.%x missing "\
293 "request bit\n", sf_item.requested, sf_item.holder);
294
295 // Update the residency of the cache line.
296 if (cpkt->needsExclusive() || !cpkt->sharedAsserted())
297 sf_item.holder = 0;
298 sf_item.holder |= slave_mask;
299 sf_item.requested &= ~slave_mask;
300 DPRINTF(SnoopFilter, "%s: new SF value %x.%x\n",
301 __func__, sf_item.requested, sf_item.holder);
302}
303
304void
305SnoopFilter::regStats()
306{
307 totRequests
308 .name(name() + ".tot_requests")
309 .desc("Total number of requests made to the snoop filter.");
310
311 hitSingleRequests
312 .name(name() + ".hit_single_requests")
313 .desc("Number of requests hitting in the snoop filter with a single "\
314 "holder of the requested data.");
315
316 hitMultiRequests
317 .name(name() + ".hit_multi_requests")
318 .desc("Number of requests hitting in the snoop filter with multiple "\
319 "(>1) holders of the requested data.");
320
321 totSnoops
322 .name(name() + ".tot_snoops")
323 .desc("Total number of snoops made to the snoop filter.");
324
325 hitSingleSnoops
326 .name(name() + ".hit_single_snoops")
327 .desc("Number of snoops hitting in the snoop filter with a single "\
328 "holder of the requested data.");
329
330 hitMultiSnoops
331 .name(name() + ".hit_multi_snoops")
332 .desc("Number of snoops hitting in the snoop filter with multiple "\
333 "(>1) holders of the requested data.");
334}
335
336SnoopFilter *
337SnoopFilterParams::create()
338{
339 return new SnoopFilter(this);
340}