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

Generated on Tue Sep 21 2021 12:25:32 for gem5 by doxygen 1.8.17