gem5  v21.0.1.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 
58 void
60 {
61  // make sure both sides of the monitor are connected
63  fatal("Communication monitor is not connected on both sides.\n");
64 }
65 
66 Port &
67 MemCheckerMonitor::getPort(const std::string &if_name, PortID idx)
68 {
69  if (if_name == "request" || if_name == "mem_side_port") {
70  return memSidePort;
71  } else if (if_name == "response" || if_name == "cpu_side_port") {
72  return cpuSidePort;
73  } else {
74  return SimObject::getPort(if_name, idx);
75  }
76 }
77 
78 void
80 {
81  Addr addr = pkt->getAddr();
82  unsigned size = pkt->getSize();
83 
84  // Conservatively reset this address-range. Alternatively we could try to
85  // update the values seen by the memchecker, however, there may be other
86  // reads/writes to these location from other devices we do not see.
87  memchecker->reset(addr, size);
88 
90 
92  "Forwarded functional access: addr = %#llx, size = %d\n",
93  addr, size);
94 }
95 
96 void
98 {
99  Addr addr = pkt->getAddr();
100  unsigned size = pkt->getSize();
101 
102  // See above.
103  memchecker->reset(addr, size);
104 
106 
108  "Received functional snoop: addr = %#llx, size = %d\n",
109  addr, size);
110 }
111 
112 Tick
114 {
115  panic("Atomic not supported");
116 }
117 
118 Tick
120 {
121  panic("Atomic not supported");
122 }
123 
124 bool
126 {
127  // should always see a request
128  assert(pkt->isRequest());
129 
130  // Store relevant fields of packet, because packet may be modified
131  // or even deleted when sendTiming() is called.
132  //
133  // For reads we are only interested in real reads, and not prefetches, as
134  // it is not guaranteed that the prefetch returns any useful data.
135  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
136  bool is_write = pkt->isWrite();
137  unsigned size = pkt->getSize();
138  Addr addr = pkt->getAddr();
139  bool expects_response = pkt->needsResponse() && !pkt->cacheResponding();
140  std::unique_ptr<uint8_t[]> pkt_data;
141  MemCheckerMonitorSenderState* state = NULL;
142 
143  if (expects_response && is_write) {
144  // On receipt of a request, only need to allocate pkt_data if this is a
145  // write. For reads, we have no data yet, so it doesn't make sense to
146  // allocate.
147  pkt_data.reset(new uint8_t[size]);
148  pkt->writeData(pkt_data.get());
149  }
150 
151  // If a cache miss is served by a cache, a monitor near the memory
152  // would see a request which needs a response, but this response
153  // would not come back from the memory. Therefore
154  // we additionally have to check the inhibit flag.
155  if (expects_response && (is_read || is_write)) {
156  state = new MemCheckerMonitorSenderState(0);
157  pkt->pushSenderState(state);
158  }
159 
160  // Attempt to send the packet
161  bool successful = memSidePort.sendTimingReq(pkt);
162 
163  // If not successful, restore the sender state
164  if (!successful && expects_response && (is_read || is_write)) {
165  delete pkt->popSenderState();
166  }
167 
168  if (successful && expects_response) {
169  if (is_read) {
171  addr,
172  size);
173 
174  // At the time where we push the sender-state, we do not yet know
175  // the serial the MemChecker class will assign to this request. We
176  // cannot call startRead at the time we push the sender-state, as
177  // the memSidePort may not be successful in executing
178  // sendTimingReq, and in case of a failure, we must not
179  // modify the state of the MemChecker.
180  //
181  // Once we know that sendTimingReq was successful, we can set the
182  // serial of the newly constructed sender-state. This is legal, as
183  // we know that nobody else will touch nor is responsible for
184  // deletion of our sender-state.
185  state->serial = serial;
186 
188  "Forwarded read request: serial = %d, addr = %#llx, "
189  "size = %d\n",
190  serial, addr, size);
191  } else if (is_write) {
193  addr,
194  size,
195  pkt_data.get());
196 
197  state->serial = serial;
198 
200  "Forwarded write request: serial = %d, addr = %#llx, "
201  "size = %d\n",
202  serial, addr, size);
203  } else {
205  "Forwarded non read/write request: addr = %#llx\n", addr);
206  }
207  } else if (successful) {
209  "Forwarded request marked for cache response: addr = %#llx\n",
210  addr);
211  }
212 
213  return successful;
214 }
215 
216 bool
218 {
219  // should always see responses
220  assert(pkt->isResponse());
221 
222  // Store relevant fields of packet, because packet may be modified
223  // or even deleted when sendTiming() is called.
224  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
225  bool is_write = pkt->isWrite();
226  bool is_failed_LLSC = pkt->isLLSC() && pkt->req->getExtraData() == 0;
227  unsigned size = pkt->getSize();
228  Addr addr = pkt->getAddr();
229  std::unique_ptr<uint8_t[]> pkt_data;
230  MemCheckerMonitorSenderState* received_state = NULL;
231 
232  if (is_read) {
233  // On receipt of a response, only need to allocate pkt_data if this is
234  // a read. For writes, we have already given the MemChecker the data on
235  // the request, so it doesn't make sense to allocate on write.
236  pkt_data.reset(new uint8_t[size]);
237  pkt->writeData(pkt_data.get());
238  }
239 
240  if (is_read || is_write) {
241  received_state =
242  dynamic_cast<MemCheckerMonitorSenderState*>(pkt->senderState);
243 
244  // Restore initial sender state
245  panic_if(received_state == NULL,
246  "Monitor got a response without monitor sender state\n");
247 
248  // Restore the state
249  pkt->senderState = received_state->predecessor;
250  }
251 
252  // Attempt to send the packet
253  bool successful = cpuSidePort.sendTimingResp(pkt);
254 
255  // If packet successfully send, complete transaction in MemChecker
256  // instance, and delete sender state, otherwise restore state.
257  if (successful) {
258  if (is_read) {
260  "Received read response: serial = %d, addr = %#llx, "
261  "size = %d\n",
262  received_state->serial, addr, size);
263 
264  bool result = memchecker->completeRead(received_state->serial,
265  curTick(),
266  addr,
267  size,
268  pkt_data.get());
269 
270  if (!result) {
271  warn("%s: read of %#llx @ cycle %d failed:\n%s\n",
272  name(),
273  addr, curTick(),
274  memchecker->getErrorMessage().c_str());
275 
276  panic_if(!warnOnly, "MemChecker violation!");
277  }
278 
279  delete received_state;
280  } else if (is_write) {
282  "Received write response: serial = %d, addr = %#llx, "
283  "size = %d\n",
284  received_state->serial, addr, size);
285 
286  if (is_failed_LLSC) {
287  // The write was not successful, let MemChecker know.
288  memchecker->abortWrite(received_state->serial,
289  addr,
290  size);
291  } else {
292  memchecker->completeWrite(received_state->serial,
293  curTick(),
294  addr,
295  size);
296  }
297 
298  delete received_state;
299  } else {
301  "Received non read/write response: addr = %#llx\n", addr);
302  }
303  } else if (is_read || is_write) {
304  // Don't delete anything and let the packet look like we
305  // did not touch it
306  pkt->senderState = received_state;
307  }
308 
309  return successful;
310 }
311 
312 void
314 {
316 }
317 
318 bool
320 {
321  return memSidePort.sendTimingSnoopResp(pkt);
322 }
323 
324 bool
326 {
327  // check if the connected memSidePort is snooping
328  return cpuSidePort.isSnooping();
329 }
330 
333 {
334  // get the address ranges of the connected cpuSidePort
335  return memSidePort.getAddrRanges();
336 }
337 
338 void
340 {
342 }
343 
344 void
346 {
348 }
349 
350 void
352 {
354 }
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:217
MemChecker::abortWrite
void abortWrite(Serial serial, Addr addr, size_t size)
Aborts a previously started write transaction.
Definition: mem_checker.hh:557
Packet::isResponse
bool isResponse() const
Definition: packet.hh:561
warn
#define warn(...)
Definition: logging.hh:239
MemCheckerMonitor::getAddrRanges
AddrRangeList getAddrRanges() const
Definition: mem_checker_monitor.cc:332
Packet::cacheResponding
bool cacheResponding() const
Definition: packet.hh:620
MemCheckerMonitor::recvFunctional
void recvFunctional(PacketPtr pkt)
Definition: mem_checker_monitor.cc:79
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:755
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:1255
MemCheckerMonitor::isSnooping
bool isSnooping() const
Definition: mem_checker_monitor.cc:325
Packet::isRead
bool isRead() const
Definition: packet.hh:557
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:59
PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:243
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:341
Packet::isLLSC
bool isLLSC() const
Definition: packet.hh:583
Packet::getSize
unsigned getSize() const
Definition: packet.hh:765
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:473
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
Packet::isRequest
bool isRequest() const
Definition: packet.hh:560
MemCheckerMonitor::MemCheckerMonitorSenderState::serial
MemChecker::Serial serial
Definition: mem_checker_monitor.hh:80
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:142
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:59
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:120
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:237
MemChecker::reset
void reset()
Resets the entire checker.
Definition: mem_checker.hh:451
Port
Ports are used to interface objects to each other.
Definition: port.hh:56
Packet::needsResponse
bool needsResponse() const
Definition: packet.hh:571
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:319
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:530
MemCheckerMonitor::Params
MemCheckerMonitorParams Params
Parameters of memchecker monitor.
Definition: mem_checker_monitor.hh:55
MemCheckerMonitor::recvTimingSnoopReq
void recvTimingSnoopReq(PacketPtr pkt)
Definition: mem_checker_monitor.cc:313
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:148
name
const std::string & name()
Definition: trace.cc:48
MemCheckerMonitor::MemCheckerMonitor
MemCheckerMonitor(const Params &params)
Constructor based on the Python params.
Definition: mem_checker_monitor.cc:47
X86ISA::addr
Bitfield< 3 > addr
Definition: types.hh:80
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:182
MemChecker::completeWrite
void completeWrite(Serial serial, Tick complete, Addr addr, size_t size)
Completes a previously started write transaction.
Definition: mem_checker.hh:544
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:198
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:339
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:258
MemCheckerMonitor::recvRespRetry
void recvRespRetry()
Definition: mem_checker_monitor.cc:345
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:125
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:74
MemChecker::startRead
Serial startRead(Tick start, Addr addr, size_t size)
Starts a read transaction.
Definition: mem_checker.hh:516
logging.hh
Packet::isWrite
bool isWrite() const
Definition: packet.hh:558
MemCheckerMonitor::recvFunctionalSnoop
void recvFunctionalSnoop(PacketPtr pkt)
Definition: mem_checker_monitor.cc:97
curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:43
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:509
MemCheckerMonitor::recvAtomicSnoop
Tick recvAtomicSnoop(PacketPtr pkt)
Definition: mem_checker_monitor.cc:119
std::list< AddrRange >
MemCheckerMonitor::memchecker
MemChecker * memchecker
Definition: mem_checker_monitor.hh:228
MemCheckerMonitor::warnOnly
bool warnOnly
Definition: mem_checker_monitor.hh:226
MemCheckerMonitor::recvRangeChange
void recvRangeChange()
Definition: mem_checker_monitor.cc:351
Packet::SenderState::predecessor
SenderState * predecessor
Definition: packet.hh:434
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:298
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:67
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:79
MemCheckerMonitor::recvAtomic
Tick recvAtomic(PacketPtr pkt)
Definition: mem_checker_monitor.cc:113
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
SimObject
Abstract superclass for simulation objects.
Definition: sim_object.hh:141

Generated on Tue Jun 22 2021 15:28:29 for gem5 by doxygen 1.8.17