gem5  v20.1.0.0
mem_checker_monitor.cc
Go to the documentation of this file.
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 
39 
40 #include <memory>
41 
42 #include "base/logging.hh"
43 #include "base/output.hh"
44 #include "base/trace.hh"
45 #include "debug/MemCheckerMonitor.hh"
46 
48  : SimObject(params),
49  memSidePort(name() + "-memSidePort", *this),
50  cpuSidePort(name() + "-cpuSidePort", *this),
51  warnOnly(params->warn_only),
52  memchecker(params->memchecker)
53 {}
54 
56 {}
57 
59 MemCheckerMonitorParams::create()
60 {
61  return new MemCheckerMonitor(this);
62 }
63 
64 void
66 {
67  // make sure both sides of the monitor are connected
69  fatal("Communication monitor is not connected on both sides.\n");
70 }
71 
72 Port &
73 MemCheckerMonitor::getPort(const std::string &if_name, PortID idx)
74 {
75  if (if_name == "request" || if_name == "mem_side_port") {
76  return memSidePort;
77  } else if (if_name == "response" || if_name == "cpu_side_port") {
78  return cpuSidePort;
79  } else {
80  return SimObject::getPort(if_name, idx);
81  }
82 }
83 
84 void
86 {
87  Addr addr = pkt->getAddr();
88  unsigned size = pkt->getSize();
89 
90  // Conservatively reset this address-range. Alternatively we could try to
91  // update the values seen by the memchecker, however, there may be other
92  // reads/writes to these location from other devices we do not see.
93  memchecker->reset(addr, size);
94 
96 
98  "Forwarded functional access: addr = %#llx, size = %d\n",
99  addr, size);
100 }
101 
102 void
104 {
105  Addr addr = pkt->getAddr();
106  unsigned size = pkt->getSize();
107 
108  // See above.
109  memchecker->reset(addr, size);
110 
112 
114  "Received functional snoop: addr = %#llx, size = %d\n",
115  addr, size);
116 }
117 
118 Tick
120 {
121  panic("Atomic not supported");
122 }
123 
124 Tick
126 {
127  panic("Atomic not supported");
128 }
129 
130 bool
132 {
133  // should always see a request
134  assert(pkt->isRequest());
135 
136  // Store relevant fields of packet, because packet may be modified
137  // or even deleted when sendTiming() is called.
138  //
139  // For reads we are only interested in real reads, and not prefetches, as
140  // it is not guaranteed that the prefetch returns any useful data.
141  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
142  bool is_write = pkt->isWrite();
143  unsigned size = pkt->getSize();
144  Addr addr = pkt->getAddr();
145  bool expects_response = pkt->needsResponse() && !pkt->cacheResponding();
146  std::unique_ptr<uint8_t[]> pkt_data;
147  MemCheckerMonitorSenderState* state = NULL;
148 
149  if (expects_response && is_write) {
150  // On receipt of a request, only need to allocate pkt_data if this is a
151  // write. For reads, we have no data yet, so it doesn't make sense to
152  // allocate.
153  pkt_data.reset(new uint8_t[size]);
154  pkt->writeData(pkt_data.get());
155  }
156 
157  // If a cache miss is served by a cache, a monitor near the memory
158  // would see a request which needs a response, but this response
159  // would not come back from the memory. Therefore
160  // we additionally have to check the inhibit flag.
161  if (expects_response && (is_read || is_write)) {
162  state = new MemCheckerMonitorSenderState(0);
163  pkt->pushSenderState(state);
164  }
165 
166  // Attempt to send the packet
167  bool successful = memSidePort.sendTimingReq(pkt);
168 
169  // If not successful, restore the sender state
170  if (!successful && expects_response && (is_read || is_write)) {
171  delete pkt->popSenderState();
172  }
173 
174  if (successful && expects_response) {
175  if (is_read) {
177  addr,
178  size);
179 
180  // At the time where we push the sender-state, we do not yet know
181  // the serial the MemChecker class will assign to this request. We
182  // cannot call startRead at the time we push the sender-state, as
183  // the memSidePort may not be successful in executing
184  // sendTimingReq, and in case of a failure, we must not
185  // modify the state of the MemChecker.
186  //
187  // Once we know that sendTimingReq was successful, we can set the
188  // serial of the newly constructed sender-state. This is legal, as
189  // we know that nobody else will touch nor is responsible for
190  // deletion of our sender-state.
191  state->serial = serial;
192 
194  "Forwarded read request: serial = %d, addr = %#llx, "
195  "size = %d\n",
196  serial, addr, size);
197  } else if (is_write) {
199  addr,
200  size,
201  pkt_data.get());
202 
203  state->serial = serial;
204 
206  "Forwarded write request: serial = %d, addr = %#llx, "
207  "size = %d\n",
208  serial, addr, size);
209  } else {
211  "Forwarded non read/write request: addr = %#llx\n", addr);
212  }
213  } else if (successful) {
215  "Forwarded request marked for cache response: addr = %#llx\n",
216  addr);
217  }
218 
219  return successful;
220 }
221 
222 bool
224 {
225  // should always see responses
226  assert(pkt->isResponse());
227 
228  // Store relevant fields of packet, because packet may be modified
229  // or even deleted when sendTiming() is called.
230  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
231  bool is_write = pkt->isWrite();
232  bool is_failed_LLSC = pkt->isLLSC() && pkt->req->getExtraData() == 0;
233  unsigned size = pkt->getSize();
234  Addr addr = pkt->getAddr();
235  std::unique_ptr<uint8_t[]> pkt_data;
236  MemCheckerMonitorSenderState* received_state = NULL;
237 
238  if (is_read) {
239  // On receipt of a response, only need to allocate pkt_data if this is
240  // a read. For writes, we have already given the MemChecker the data on
241  // the request, so it doesn't make sense to allocate on write.
242  pkt_data.reset(new uint8_t[size]);
243  pkt->writeData(pkt_data.get());
244  }
245 
246  if (is_read || is_write) {
247  received_state =
248  dynamic_cast<MemCheckerMonitorSenderState*>(pkt->senderState);
249 
250  // Restore initial sender state
251  panic_if(received_state == NULL,
252  "Monitor got a response without monitor sender state\n");
253 
254  // Restore the state
255  pkt->senderState = received_state->predecessor;
256  }
257 
258  // Attempt to send the packet
259  bool successful = cpuSidePort.sendTimingResp(pkt);
260 
261  // If packet successfully send, complete transaction in MemChecker
262  // instance, and delete sender state, otherwise restore state.
263  if (successful) {
264  if (is_read) {
266  "Received read response: serial = %d, addr = %#llx, "
267  "size = %d\n",
268  received_state->serial, addr, size);
269 
270  bool result = memchecker->completeRead(received_state->serial,
271  curTick(),
272  addr,
273  size,
274  pkt_data.get());
275 
276  if (!result) {
277  warn("%s: read of %#llx @ cycle %d failed:\n%s\n",
278  name(),
279  addr, curTick(),
280  memchecker->getErrorMessage().c_str());
281 
282  panic_if(!warnOnly, "MemChecker violation!");
283  }
284 
285  delete received_state;
286  } else if (is_write) {
288  "Received write response: serial = %d, addr = %#llx, "
289  "size = %d\n",
290  received_state->serial, addr, size);
291 
292  if (is_failed_LLSC) {
293  // The write was not successful, let MemChecker know.
294  memchecker->abortWrite(received_state->serial,
295  addr,
296  size);
297  } else {
298  memchecker->completeWrite(received_state->serial,
299  curTick(),
300  addr,
301  size);
302  }
303 
304  delete received_state;
305  } else {
307  "Received non read/write response: addr = %#llx\n", addr);
308  }
309  } else if (is_read || is_write) {
310  // Don't delete anything and let the packet look like we
311  // did not touch it
312  pkt->senderState = received_state;
313  }
314 
315  return successful;
316 }
317 
318 void
320 {
322 }
323 
324 bool
326 {
327  return memSidePort.sendTimingSnoopResp(pkt);
328 }
329 
330 bool
332 {
333  // check if the connected memSidePort is snooping
334  return cpuSidePort.isSnooping();
335 }
336 
339 {
340  // get the address ranges of the connected cpuSidePort
341  return memSidePort.getAddrRanges();
342 }
343 
344 void
346 {
348 }
349 
350 void
352 {
354 }
355 
356 void
358 {
360 }
fatal
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:183
MemCheckerMonitor::recvTimingResp
bool recvTimingResp(PacketPtr pkt)
Definition: mem_checker_monitor.cc:223
MemChecker::abortWrite
void abortWrite(Serial serial, Addr addr, size_t size)
Aborts a previously started write transaction.
Definition: mem_checker.hh:555
Packet::isResponse
bool isResponse() const
Definition: packet.hh:560
warn
#define warn(...)
Definition: logging.hh:239
MemCheckerMonitor::getAddrRanges
AddrRangeList getAddrRanges() const
Definition: mem_checker_monitor.cc:338
Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:619
MemCheckerMonitor::recvFunctional
void recvFunctional(PacketPtr pkt)
Definition: mem_checker_monitor.cc:85
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
ResponsePort::sendTimingResp
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition: port.hh:367
Packet::writeData
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
Definition: packet.hh:1254
MemCheckerMonitor::isSnooping
bool isSnooping() const
Definition: mem_checker_monitor.cc:331
Packet::isRead
bool isRead() const
Definition: packet.hh:556
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
RequestPort::getAddrRanges
AddrRangeList getAddrRanges() const
Get the address ranges of the connected responder port.
Definition: port.cc:148
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:340
Packet::isLLSC
bool isLLSC() const
Definition: packet.hh:582
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
MemChecker::getErrorMessage
const std::string & getErrorMessage() const
In completeRead, if an error is encountered, this does not print nor cause an error,...
Definition: mem_checker.hh:471
RequestPort::sendFunctional
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:482
MemCheckerMonitor::Params
MemCheckerMonitorParams Params
Parameters of memchecker monitor.
Definition: mem_checker_monitor.hh:55
Packet::isRequest
bool isRequest() const
Definition: packet.hh:559
MemCheckerMonitor::MemCheckerMonitorSenderState::serial
MemChecker::Serial serial
Definition: mem_checker_monitor.hh:82
output.hh
RequestPort::sendTimingSnoopResp
bool sendTimingSnoopResp(PacketPtr pkt)
Attempt to send a timing snoop response packet to the response port by calling its corresponding rece...
Definition: port.hh:512
MemCheckerMonitor::memSidePort
MonitorRequestPort memSidePort
Instance of request port, facing the memory side.
Definition: mem_checker_monitor.hh:144
ResponsePort::sendTimingSnoopReq
void sendTimingSnoopReq(PacketPtr pkt)
Attempt to send a timing snoop request packet to the request port by calling its corresponding receiv...
Definition: port.hh:384
mem_checker_monitor.hh
MemCheckerMonitor::init
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: mem_checker_monitor.cc:65
RequestPort::sendTimingReq
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:492
SimObject::getPort
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
Definition: sim_object.cc:123
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
MemChecker::reset
void reset()
Resets the entire checker.
Definition: mem_checker.hh:449
Port
Ports are used to interface objects to each other.
Definition: port.hh:56
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:570
MemCheckerMonitor
Implements a MemChecker monitor, to be inserted between two ports.
Definition: mem_checker_monitor.hh:50
RequestPort::sendRetryResp
virtual void sendRetryResp()
Send a retry to the response port that previously attempted a sendTimingResp to this request port and...
Definition: port.hh:522
MemCheckerMonitor::recvTimingSnoopResp
bool recvTimingSnoopResp(PacketPtr pkt)
Definition: mem_checker_monitor.cc:325
ResponsePort::isSnooping
bool isSnooping() const
Find out if the peer request port is snooping or not.
Definition: port.hh:288
MemChecker::startWrite
Serial startWrite(Tick start, Addr addr, size_t size, const uint8_t *data)
Starts a write transaction.
Definition: mem_checker.hh:528
MemCheckerMonitor::recvTimingSnoopReq
void recvTimingSnoopReq(PacketPtr pkt)
Definition: mem_checker_monitor.cc:319
MemCheckerMonitor::MemCheckerMonitor
MemCheckerMonitor(Params *params)
Constructor based on the Python params.
Definition: mem_checker_monitor.cc:47
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
name
const std::string & name()
Definition: trace.cc:50
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:133
MemChecker::completeWrite
void completeWrite(Serial serial, Tick complete, Addr addr, size_t size)
Completes a previously started write transaction.
Definition: mem_checker.hh:542
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:197
MemCheckerMonitor::cpuSidePort
MonitorResponsePort cpuSidePort
Instance of response port, i.e.
Definition: mem_checker_monitor.hh:200
Packet::pushSenderState
void pushSenderState(SenderState *sender_state)
Push a new sender state to the packet and make the current sender state the predecessor of the new on...
Definition: packet.cc:332
MemCheckerMonitor::recvReqRetry
void recvReqRetry()
Definition: mem_checker_monitor.cc:345
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
MemCheckerMonitor::recvRespRetry
void recvRespRetry()
Definition: mem_checker_monitor.cc:351
Packet::popSenderState
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:340
MemCheckerMonitor::recvTimingReq
bool recvTimingReq(PacketPtr pkt)
Definition: mem_checker_monitor.cc:131
addr
ip6_addr_t addr
Definition: inet.hh:423
ResponsePort::sendFunctionalSnoop
void sendFunctionalSnoop(PacketPtr pkt) const
Send a functional snoop request packet, where the data is instantly updated everywhere in the memory ...
Definition: port.hh:343
Port::isConnected
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:128
MemCheckerMonitor::MemCheckerMonitorSenderState
Definition: mem_checker_monitor.hh:76
MemChecker::startRead
Serial startRead(Tick start, Addr addr, size_t size)
Starts a read transaction.
Definition: mem_checker.hh:514
logging.hh
Packet::isWrite
bool isWrite() const
Definition: packet.hh:557
MemCheckerMonitor::recvFunctionalSnoop
void recvFunctionalSnoop(PacketPtr pkt)
Definition: mem_checker_monitor.cc:103
trace.hh
MemCheckerMonitor::~MemCheckerMonitor
~MemCheckerMonitor()
Destructor.
Definition: mem_checker_monitor.cc:55
ResponsePort::sendRetryReq
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition: port.hh:398
Packet::senderState
SenderState * senderState
This packet's sender state.
Definition: packet.hh:508
MemCheckerMonitor::recvAtomicSnoop
Tick recvAtomicSnoop(PacketPtr pkt)
Definition: mem_checker_monitor.cc:125
std::list< AddrRange >
MemCheckerMonitor::memchecker
MemChecker * memchecker
Definition: mem_checker_monitor.hh:230
MemCheckerMonitor::warnOnly
bool warnOnly
Definition: mem_checker_monitor.hh:228
MemCheckerMonitor::recvRangeChange
void recvRangeChange()
Definition: mem_checker_monitor.cc:357
Packet::SenderState::predecessor
SenderState * predecessor
Definition: packet.hh:433
ResponsePort::sendRangeChange
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:293
MemChecker::completeRead
bool completeRead(Serial serial, Tick complete, Addr addr, size_t size, uint8_t *data)
Completes a previously started read transaction.
Definition: mem_checker.cc:295
MemCheckerMonitor::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: mem_checker_monitor.cc:73
MemChecker::Serial
uint64_t Serial
The Serial type is used to be able to uniquely identify a transaction as it passes through the system...
Definition: mem_checker.hh:77
MemCheckerMonitor::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Definition: mem_checker_monitor.cc:119
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45
SimObject
Abstract superclass for simulation objects.
Definition: sim_object.hh:92

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17