mem_checker_monitor.cc (11489:47aca087ebb4) mem_checker_monitor.cc (11793:ef606668d247)
1/*
2 * Copyright (c) 2012-2014 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: Thomas Grass
38 * Andreas Hansson
39 * Marco Elver
40 */
41
1/*
2 * Copyright (c) 2012-2014 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: Thomas Grass
38 * Andreas Hansson
39 * Marco Elver
40 */
41
42#include "mem/mem_checker_monitor.hh"
43
42#include <memory>
43
44#include "base/output.hh"
45#include "base/trace.hh"
46#include "debug/MemCheckerMonitor.hh"
44#include <memory>
45
46#include "base/output.hh"
47#include "base/trace.hh"
48#include "debug/MemCheckerMonitor.hh"
47#include "mem/mem_checker_monitor.hh"
48
49using namespace std;
50
51MemCheckerMonitor::MemCheckerMonitor(Params* params)
52 : MemObject(params),
53 masterPort(name() + "-master", *this),
54 slavePort(name() + "-slave", *this),
55 warnOnly(params->warn_only),
56 memchecker(params->memchecker)
57{}
58
59MemCheckerMonitor::~MemCheckerMonitor()
60{}
61
62MemCheckerMonitor*
63MemCheckerMonitorParams::create()
64{
65 return new MemCheckerMonitor(this);
66}
67
68void
69MemCheckerMonitor::init()
70{
71 // make sure both sides of the monitor are connected
72 if (!slavePort.isConnected() || !masterPort.isConnected())
73 fatal("Communication monitor is not connected on both sides.\n");
74}
75
76BaseMasterPort&
77MemCheckerMonitor::getMasterPort(const std::string& if_name, PortID idx)
78{
79 if (if_name == "master" || if_name == "mem_side") {
80 return masterPort;
81 } else {
82 return MemObject::getMasterPort(if_name, idx);
83 }
84}
85
86BaseSlavePort&
87MemCheckerMonitor::getSlavePort(const std::string& if_name, PortID idx)
88{
89 if (if_name == "slave" || if_name == "cpu_side") {
90 return slavePort;
91 } else {
92 return MemObject::getSlavePort(if_name, idx);
93 }
94}
95
96void
97MemCheckerMonitor::recvFunctional(PacketPtr pkt)
98{
99 Addr addr = pkt->getAddr();
100 unsigned size = pkt->getSize();
101
102 // Conservatively reset this address-range. Alternatively we could try to
103 // update the values seen by the memchecker, however, there may be other
104 // reads/writes to these location from other devices we do not see.
105 memchecker->reset(addr, size);
106
107 masterPort.sendFunctional(pkt);
108
109 DPRINTF(MemCheckerMonitor,
110 "Forwarded functional access: addr = %#llx, size = %d\n",
111 addr, size);
112}
113
114void
115MemCheckerMonitor::recvFunctionalSnoop(PacketPtr pkt)
116{
117 Addr addr = pkt->getAddr();
118 unsigned size = pkt->getSize();
119
120 // See above.
121 memchecker->reset(addr, size);
122
123 slavePort.sendFunctionalSnoop(pkt);
124
125 DPRINTF(MemCheckerMonitor,
126 "Received functional snoop: addr = %#llx, size = %d\n",
127 addr, size);
128}
129
130Tick
131MemCheckerMonitor::recvAtomic(PacketPtr pkt)
132{
133 assert(false && "Atomic not supported");
134 return masterPort.sendAtomic(pkt);
135}
136
137Tick
138MemCheckerMonitor::recvAtomicSnoop(PacketPtr pkt)
139{
140 assert(false && "Atomic not supported");
141 return slavePort.sendAtomicSnoop(pkt);
142}
143
144bool
145MemCheckerMonitor::recvTimingReq(PacketPtr pkt)
146{
147 // should always see a request
148 assert(pkt->isRequest());
149
150 // Store relevant fields of packet, because packet may be modified
151 // or even deleted when sendTiming() is called.
152 //
153 // For reads we are only interested in real reads, and not prefetches, as
154 // it is not guaranteed that the prefetch returns any useful data.
155 bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
156 bool is_write = pkt->isWrite();
157 unsigned size = pkt->getSize();
158 Addr addr = pkt->getAddr();
159 bool expects_response = pkt->needsResponse() && !pkt->cacheResponding();
160 std::unique_ptr<uint8_t[]> pkt_data;
161 MemCheckerMonitorSenderState* state = NULL;
162
163 if (expects_response && is_write) {
164 // On receipt of a request, only need to allocate pkt_data if this is a
165 // write. For reads, we have no data yet, so it doesn't make sense to
166 // allocate.
167 pkt_data.reset(new uint8_t[size]);
168 memcpy(pkt_data.get(), pkt->getConstPtr<uint8_t*>(), size);
169 }
170
171 // If a cache miss is served by a cache, a monitor near the memory
172 // would see a request which needs a response, but this response
173 // would not come back from the memory. Therefore
174 // we additionally have to check the inhibit flag.
175 if (expects_response && (is_read || is_write)) {
176 state = new MemCheckerMonitorSenderState(0);
177 pkt->pushSenderState(state);
178 }
179
180 // Attempt to send the packet
181 bool successful = masterPort.sendTimingReq(pkt);
182
183 // If not successful, restore the sender state
184 if (!successful && expects_response && (is_read || is_write)) {
185 delete pkt->popSenderState();
186 }
187
188 if (successful && expects_response) {
189 if (is_read) {
190 MemChecker::Serial serial = memchecker->startRead(curTick(),
191 addr,
192 size);
193
194 // At the time where we push the sender-state, we do not yet know
195 // the serial the MemChecker class will assign to this request. We
196 // cannot call startRead at the time we push the sender-state, as
197 // the masterPort may not be successful in executing sendTimingReq,
198 // and in case of a failure, we must not modify the state of the
199 // MemChecker.
200 //
201 // Once we know that sendTimingReq was successful, we can set the
202 // serial of the newly constructed sender-state. This is legal, as
203 // we know that nobody else will touch nor is responsible for
204 // deletion of our sender-state.
205 state->serial = serial;
206
207 DPRINTF(MemCheckerMonitor,
208 "Forwarded read request: serial = %d, addr = %#llx, "
209 "size = %d\n",
210 serial, addr, size);
211 } else if (is_write) {
212 MemChecker::Serial serial = memchecker->startWrite(curTick(),
213 addr,
214 size,
215 pkt_data.get());
216
217 state->serial = serial;
218
219 DPRINTF(MemCheckerMonitor,
220 "Forwarded write request: serial = %d, addr = %#llx, "
221 "size = %d\n",
222 serial, addr, size);
223 } else {
224 DPRINTF(MemCheckerMonitor,
225 "Forwarded non read/write request: addr = %#llx\n", addr);
226 }
227 } else if (successful) {
228 DPRINTF(MemCheckerMonitor,
229 "Forwarded request marked for cache response: addr = %#llx\n",
230 addr);
231 }
232
233 return successful;
234}
235
236bool
237MemCheckerMonitor::recvTimingResp(PacketPtr pkt)
238{
239 // should always see responses
240 assert(pkt->isResponse());
241
242 // Store relevant fields of packet, because packet may be modified
243 // or even deleted when sendTiming() is called.
244 bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
245 bool is_write = pkt->isWrite();
246 bool is_failed_LLSC = pkt->isLLSC() && pkt->req->getExtraData() == 0;
247 unsigned size = pkt->getSize();
248 Addr addr = pkt->getAddr();
249 std::unique_ptr<uint8_t[]> pkt_data;
250 MemCheckerMonitorSenderState* received_state = NULL;
251
252 if (is_read) {
253 // On receipt of a response, only need to allocate pkt_data if this is
254 // a read. For writes, we have already given the MemChecker the data on
255 // the request, so it doesn't make sense to allocate on write.
256 pkt_data.reset(new uint8_t[size]);
257 memcpy(pkt_data.get(), pkt->getConstPtr<uint8_t*>(), size);
258 }
259
260 if (is_read || is_write) {
261 received_state =
262 dynamic_cast<MemCheckerMonitorSenderState*>(pkt->senderState);
263
264 // Restore initial sender state
265 panic_if(received_state == NULL,
266 "Monitor got a response without monitor sender state\n");
267
268 // Restore the state
269 pkt->senderState = received_state->predecessor;
270 }
271
272 // Attempt to send the packet
273 bool successful = slavePort.sendTimingResp(pkt);
274
275 // If packet successfully send, complete transaction in MemChecker
276 // instance, and delete sender state, otherwise restore state.
277 if (successful) {
278 if (is_read) {
279 DPRINTF(MemCheckerMonitor,
280 "Received read response: serial = %d, addr = %#llx, "
281 "size = %d\n",
282 received_state->serial, addr, size);
283
284 bool result = memchecker->completeRead(received_state->serial,
285 curTick(),
286 addr,
287 size,
288 pkt_data.get());
289
290 if (!result) {
291 warn("%s: read of %#llx @ cycle %d failed:\n%s\n",
292 name(),
293 addr, curTick(),
294 memchecker->getErrorMessage().c_str());
295
296 panic_if(!warnOnly, "MemChecker violation!");
297 }
298
299 delete received_state;
300 } else if (is_write) {
301 DPRINTF(MemCheckerMonitor,
302 "Received write response: serial = %d, addr = %#llx, "
303 "size = %d\n",
304 received_state->serial, addr, size);
305
306 if (is_failed_LLSC) {
307 // The write was not successful, let MemChecker know.
308 memchecker->abortWrite(received_state->serial,
309 addr,
310 size);
311 } else {
312 memchecker->completeWrite(received_state->serial,
313 curTick(),
314 addr,
315 size);
316 }
317
318 delete received_state;
319 } else {
320 DPRINTF(MemCheckerMonitor,
321 "Received non read/write response: addr = %#llx\n", addr);
322 }
323 } else if (is_read || is_write) {
324 // Don't delete anything and let the packet look like we
325 // did not touch it
326 pkt->senderState = received_state;
327 }
328
329 return successful;
330}
331
332void
333MemCheckerMonitor::recvTimingSnoopReq(PacketPtr pkt)
334{
335 slavePort.sendTimingSnoopReq(pkt);
336}
337
338bool
339MemCheckerMonitor::recvTimingSnoopResp(PacketPtr pkt)
340{
341 return masterPort.sendTimingSnoopResp(pkt);
342}
343
344bool
345MemCheckerMonitor::isSnooping() const
346{
347 // check if the connected master port is snooping
348 return slavePort.isSnooping();
349}
350
351AddrRangeList
352MemCheckerMonitor::getAddrRanges() const
353{
354 // get the address ranges of the connected slave port
355 return masterPort.getAddrRanges();
356}
357
358void
359MemCheckerMonitor::recvReqRetry()
360{
361 slavePort.sendRetryReq();
362}
363
364void
365MemCheckerMonitor::recvRespRetry()
366{
367 masterPort.sendRetryResp();
368}
369
370void
371MemCheckerMonitor::recvRangeChange()
372{
373 slavePort.sendRangeChange();
374}
49
50using namespace std;
51
52MemCheckerMonitor::MemCheckerMonitor(Params* params)
53 : MemObject(params),
54 masterPort(name() + "-master", *this),
55 slavePort(name() + "-slave", *this),
56 warnOnly(params->warn_only),
57 memchecker(params->memchecker)
58{}
59
60MemCheckerMonitor::~MemCheckerMonitor()
61{}
62
63MemCheckerMonitor*
64MemCheckerMonitorParams::create()
65{
66 return new MemCheckerMonitor(this);
67}
68
69void
70MemCheckerMonitor::init()
71{
72 // make sure both sides of the monitor are connected
73 if (!slavePort.isConnected() || !masterPort.isConnected())
74 fatal("Communication monitor is not connected on both sides.\n");
75}
76
77BaseMasterPort&
78MemCheckerMonitor::getMasterPort(const std::string& if_name, PortID idx)
79{
80 if (if_name == "master" || if_name == "mem_side") {
81 return masterPort;
82 } else {
83 return MemObject::getMasterPort(if_name, idx);
84 }
85}
86
87BaseSlavePort&
88MemCheckerMonitor::getSlavePort(const std::string& if_name, PortID idx)
89{
90 if (if_name == "slave" || if_name == "cpu_side") {
91 return slavePort;
92 } else {
93 return MemObject::getSlavePort(if_name, idx);
94 }
95}
96
97void
98MemCheckerMonitor::recvFunctional(PacketPtr pkt)
99{
100 Addr addr = pkt->getAddr();
101 unsigned size = pkt->getSize();
102
103 // Conservatively reset this address-range. Alternatively we could try to
104 // update the values seen by the memchecker, however, there may be other
105 // reads/writes to these location from other devices we do not see.
106 memchecker->reset(addr, size);
107
108 masterPort.sendFunctional(pkt);
109
110 DPRINTF(MemCheckerMonitor,
111 "Forwarded functional access: addr = %#llx, size = %d\n",
112 addr, size);
113}
114
115void
116MemCheckerMonitor::recvFunctionalSnoop(PacketPtr pkt)
117{
118 Addr addr = pkt->getAddr();
119 unsigned size = pkt->getSize();
120
121 // See above.
122 memchecker->reset(addr, size);
123
124 slavePort.sendFunctionalSnoop(pkt);
125
126 DPRINTF(MemCheckerMonitor,
127 "Received functional snoop: addr = %#llx, size = %d\n",
128 addr, size);
129}
130
131Tick
132MemCheckerMonitor::recvAtomic(PacketPtr pkt)
133{
134 assert(false && "Atomic not supported");
135 return masterPort.sendAtomic(pkt);
136}
137
138Tick
139MemCheckerMonitor::recvAtomicSnoop(PacketPtr pkt)
140{
141 assert(false && "Atomic not supported");
142 return slavePort.sendAtomicSnoop(pkt);
143}
144
145bool
146MemCheckerMonitor::recvTimingReq(PacketPtr pkt)
147{
148 // should always see a request
149 assert(pkt->isRequest());
150
151 // Store relevant fields of packet, because packet may be modified
152 // or even deleted when sendTiming() is called.
153 //
154 // For reads we are only interested in real reads, and not prefetches, as
155 // it is not guaranteed that the prefetch returns any useful data.
156 bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
157 bool is_write = pkt->isWrite();
158 unsigned size = pkt->getSize();
159 Addr addr = pkt->getAddr();
160 bool expects_response = pkt->needsResponse() && !pkt->cacheResponding();
161 std::unique_ptr<uint8_t[]> pkt_data;
162 MemCheckerMonitorSenderState* state = NULL;
163
164 if (expects_response && is_write) {
165 // On receipt of a request, only need to allocate pkt_data if this is a
166 // write. For reads, we have no data yet, so it doesn't make sense to
167 // allocate.
168 pkt_data.reset(new uint8_t[size]);
169 memcpy(pkt_data.get(), pkt->getConstPtr<uint8_t*>(), size);
170 }
171
172 // If a cache miss is served by a cache, a monitor near the memory
173 // would see a request which needs a response, but this response
174 // would not come back from the memory. Therefore
175 // we additionally have to check the inhibit flag.
176 if (expects_response && (is_read || is_write)) {
177 state = new MemCheckerMonitorSenderState(0);
178 pkt->pushSenderState(state);
179 }
180
181 // Attempt to send the packet
182 bool successful = masterPort.sendTimingReq(pkt);
183
184 // If not successful, restore the sender state
185 if (!successful && expects_response && (is_read || is_write)) {
186 delete pkt->popSenderState();
187 }
188
189 if (successful && expects_response) {
190 if (is_read) {
191 MemChecker::Serial serial = memchecker->startRead(curTick(),
192 addr,
193 size);
194
195 // At the time where we push the sender-state, we do not yet know
196 // the serial the MemChecker class will assign to this request. We
197 // cannot call startRead at the time we push the sender-state, as
198 // the masterPort may not be successful in executing sendTimingReq,
199 // and in case of a failure, we must not modify the state of the
200 // MemChecker.
201 //
202 // Once we know that sendTimingReq was successful, we can set the
203 // serial of the newly constructed sender-state. This is legal, as
204 // we know that nobody else will touch nor is responsible for
205 // deletion of our sender-state.
206 state->serial = serial;
207
208 DPRINTF(MemCheckerMonitor,
209 "Forwarded read request: serial = %d, addr = %#llx, "
210 "size = %d\n",
211 serial, addr, size);
212 } else if (is_write) {
213 MemChecker::Serial serial = memchecker->startWrite(curTick(),
214 addr,
215 size,
216 pkt_data.get());
217
218 state->serial = serial;
219
220 DPRINTF(MemCheckerMonitor,
221 "Forwarded write request: serial = %d, addr = %#llx, "
222 "size = %d\n",
223 serial, addr, size);
224 } else {
225 DPRINTF(MemCheckerMonitor,
226 "Forwarded non read/write request: addr = %#llx\n", addr);
227 }
228 } else if (successful) {
229 DPRINTF(MemCheckerMonitor,
230 "Forwarded request marked for cache response: addr = %#llx\n",
231 addr);
232 }
233
234 return successful;
235}
236
237bool
238MemCheckerMonitor::recvTimingResp(PacketPtr pkt)
239{
240 // should always see responses
241 assert(pkt->isResponse());
242
243 // Store relevant fields of packet, because packet may be modified
244 // or even deleted when sendTiming() is called.
245 bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
246 bool is_write = pkt->isWrite();
247 bool is_failed_LLSC = pkt->isLLSC() && pkt->req->getExtraData() == 0;
248 unsigned size = pkt->getSize();
249 Addr addr = pkt->getAddr();
250 std::unique_ptr<uint8_t[]> pkt_data;
251 MemCheckerMonitorSenderState* received_state = NULL;
252
253 if (is_read) {
254 // On receipt of a response, only need to allocate pkt_data if this is
255 // a read. For writes, we have already given the MemChecker the data on
256 // the request, so it doesn't make sense to allocate on write.
257 pkt_data.reset(new uint8_t[size]);
258 memcpy(pkt_data.get(), pkt->getConstPtr<uint8_t*>(), size);
259 }
260
261 if (is_read || is_write) {
262 received_state =
263 dynamic_cast<MemCheckerMonitorSenderState*>(pkt->senderState);
264
265 // Restore initial sender state
266 panic_if(received_state == NULL,
267 "Monitor got a response without monitor sender state\n");
268
269 // Restore the state
270 pkt->senderState = received_state->predecessor;
271 }
272
273 // Attempt to send the packet
274 bool successful = slavePort.sendTimingResp(pkt);
275
276 // If packet successfully send, complete transaction in MemChecker
277 // instance, and delete sender state, otherwise restore state.
278 if (successful) {
279 if (is_read) {
280 DPRINTF(MemCheckerMonitor,
281 "Received read response: serial = %d, addr = %#llx, "
282 "size = %d\n",
283 received_state->serial, addr, size);
284
285 bool result = memchecker->completeRead(received_state->serial,
286 curTick(),
287 addr,
288 size,
289 pkt_data.get());
290
291 if (!result) {
292 warn("%s: read of %#llx @ cycle %d failed:\n%s\n",
293 name(),
294 addr, curTick(),
295 memchecker->getErrorMessage().c_str());
296
297 panic_if(!warnOnly, "MemChecker violation!");
298 }
299
300 delete received_state;
301 } else if (is_write) {
302 DPRINTF(MemCheckerMonitor,
303 "Received write response: serial = %d, addr = %#llx, "
304 "size = %d\n",
305 received_state->serial, addr, size);
306
307 if (is_failed_LLSC) {
308 // The write was not successful, let MemChecker know.
309 memchecker->abortWrite(received_state->serial,
310 addr,
311 size);
312 } else {
313 memchecker->completeWrite(received_state->serial,
314 curTick(),
315 addr,
316 size);
317 }
318
319 delete received_state;
320 } else {
321 DPRINTF(MemCheckerMonitor,
322 "Received non read/write response: addr = %#llx\n", addr);
323 }
324 } else if (is_read || is_write) {
325 // Don't delete anything and let the packet look like we
326 // did not touch it
327 pkt->senderState = received_state;
328 }
329
330 return successful;
331}
332
333void
334MemCheckerMonitor::recvTimingSnoopReq(PacketPtr pkt)
335{
336 slavePort.sendTimingSnoopReq(pkt);
337}
338
339bool
340MemCheckerMonitor::recvTimingSnoopResp(PacketPtr pkt)
341{
342 return masterPort.sendTimingSnoopResp(pkt);
343}
344
345bool
346MemCheckerMonitor::isSnooping() const
347{
348 // check if the connected master port is snooping
349 return slavePort.isSnooping();
350}
351
352AddrRangeList
353MemCheckerMonitor::getAddrRanges() const
354{
355 // get the address ranges of the connected slave port
356 return masterPort.getAddrRanges();
357}
358
359void
360MemCheckerMonitor::recvReqRetry()
361{
362 slavePort.sendRetryReq();
363}
364
365void
366MemCheckerMonitor::recvRespRetry()
367{
368 masterPort.sendRetryResp();
369}
370
371void
372MemCheckerMonitor::recvRangeChange()
373{
374 slavePort.sendRangeChange();
375}