gem5
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  * Authors: Thomas Grass
38  * Andreas Hansson
39  * Marco Elver
40  */
41 
43 
44 #include <memory>
45 
46 #include "base/output.hh"
47 #include "base/trace.hh"
48 #include "debug/MemCheckerMonitor.hh"
49 
51  : MemObject(params),
52  masterPort(name() + "-master", *this),
53  slavePort(name() + "-slave", *this),
54  warnOnly(params->warn_only),
55  memchecker(params->memchecker)
56 {}
57 
59 {}
60 
62 MemCheckerMonitorParams::create()
63 {
64  return new MemCheckerMonitor(this);
65 }
66 
67 void
69 {
70  // make sure both sides of the monitor are connected
72  fatal("Communication monitor is not connected on both sides.\n");
73 }
74 
76 MemCheckerMonitor::getMasterPort(const std::string& if_name, PortID idx)
77 {
78  if (if_name == "master" || if_name == "mem_side") {
79  return masterPort;
80  } else {
81  return MemObject::getMasterPort(if_name, idx);
82  }
83 }
84 
86 MemCheckerMonitor::getSlavePort(const std::string& if_name, PortID idx)
87 {
88  if (if_name == "slave" || if_name == "cpu_side") {
89  return slavePort;
90  } else {
91  return MemObject::getSlavePort(if_name, idx);
92  }
93 }
94 
95 void
97 {
98  Addr addr = pkt->getAddr();
99  unsigned size = pkt->getSize();
100 
101  // Conservatively reset this address-range. Alternatively we could try to
102  // update the values seen by the memchecker, however, there may be other
103  // reads/writes to these location from other devices we do not see.
104  memchecker->reset(addr, size);
105 
107 
109  "Forwarded functional access: addr = %#llx, size = %d\n",
110  addr, size);
111 }
112 
113 void
115 {
116  Addr addr = pkt->getAddr();
117  unsigned size = pkt->getSize();
118 
119  // See above.
120  memchecker->reset(addr, size);
121 
123 
125  "Received functional snoop: addr = %#llx, size = %d\n",
126  addr, size);
127 }
128 
129 Tick
131 {
132  assert(false && "Atomic not supported");
133  return masterPort.sendAtomic(pkt);
134 }
135 
136 Tick
138 {
139  assert(false && "Atomic not supported");
140  return slavePort.sendAtomicSnoop(pkt);
141 }
142 
143 bool
145 {
146  // should always see a request
147  assert(pkt->isRequest());
148 
149  // Store relevant fields of packet, because packet may be modified
150  // or even deleted when sendTiming() is called.
151  //
152  // For reads we are only interested in real reads, and not prefetches, as
153  // it is not guaranteed that the prefetch returns any useful data.
154  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
155  bool is_write = pkt->isWrite();
156  unsigned size = pkt->getSize();
157  Addr addr = pkt->getAddr();
158  bool expects_response = pkt->needsResponse() && !pkt->cacheResponding();
159  std::unique_ptr<uint8_t[]> pkt_data;
160  MemCheckerMonitorSenderState* state = NULL;
161 
162  if (expects_response && is_write) {
163  // On receipt of a request, only need to allocate pkt_data if this is a
164  // write. For reads, we have no data yet, so it doesn't make sense to
165  // allocate.
166  pkt_data.reset(new uint8_t[size]);
167  memcpy(pkt_data.get(), pkt->getConstPtr<uint8_t*>(), size);
168  }
169 
170  // If a cache miss is served by a cache, a monitor near the memory
171  // would see a request which needs a response, but this response
172  // would not come back from the memory. Therefore
173  // we additionally have to check the inhibit flag.
174  if (expects_response && (is_read || is_write)) {
175  state = new MemCheckerMonitorSenderState(0);
176  pkt->pushSenderState(state);
177  }
178 
179  // Attempt to send the packet
180  bool successful = masterPort.sendTimingReq(pkt);
181 
182  // If not successful, restore the sender state
183  if (!successful && expects_response && (is_read || is_write)) {
184  delete pkt->popSenderState();
185  }
186 
187  if (successful && expects_response) {
188  if (is_read) {
190  addr,
191  size);
192 
193  // At the time where we push the sender-state, we do not yet know
194  // the serial the MemChecker class will assign to this request. We
195  // cannot call startRead at the time we push the sender-state, as
196  // the masterPort may not be successful in executing sendTimingReq,
197  // and in case of a failure, we must not modify the state of the
198  // MemChecker.
199  //
200  // Once we know that sendTimingReq was successful, we can set the
201  // serial of the newly constructed sender-state. This is legal, as
202  // we know that nobody else will touch nor is responsible for
203  // deletion of our sender-state.
204  state->serial = serial;
205 
207  "Forwarded read request: serial = %d, addr = %#llx, "
208  "size = %d\n",
209  serial, addr, size);
210  } else if (is_write) {
212  addr,
213  size,
214  pkt_data.get());
215 
216  state->serial = serial;
217 
219  "Forwarded write request: serial = %d, addr = %#llx, "
220  "size = %d\n",
221  serial, addr, size);
222  } else {
224  "Forwarded non read/write request: addr = %#llx\n", addr);
225  }
226  } else if (successful) {
228  "Forwarded request marked for cache response: addr = %#llx\n",
229  addr);
230  }
231 
232  return successful;
233 }
234 
235 bool
237 {
238  // should always see responses
239  assert(pkt->isResponse());
240 
241  // Store relevant fields of packet, because packet may be modified
242  // or even deleted when sendTiming() is called.
243  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
244  bool is_write = pkt->isWrite();
245  bool is_failed_LLSC = pkt->isLLSC() && pkt->req->getExtraData() == 0;
246  unsigned size = pkt->getSize();
247  Addr addr = pkt->getAddr();
248  std::unique_ptr<uint8_t[]> pkt_data;
249  MemCheckerMonitorSenderState* received_state = NULL;
250 
251  if (is_read) {
252  // On receipt of a response, only need to allocate pkt_data if this is
253  // a read. For writes, we have already given the MemChecker the data on
254  // the request, so it doesn't make sense to allocate on write.
255  pkt_data.reset(new uint8_t[size]);
256  memcpy(pkt_data.get(), pkt->getConstPtr<uint8_t*>(), size);
257  }
258 
259  if (is_read || is_write) {
260  received_state =
261  dynamic_cast<MemCheckerMonitorSenderState*>(pkt->senderState);
262 
263  // Restore initial sender state
264  panic_if(received_state == NULL,
265  "Monitor got a response without monitor sender state\n");
266 
267  // Restore the state
268  pkt->senderState = received_state->predecessor;
269  }
270 
271  // Attempt to send the packet
272  bool successful = slavePort.sendTimingResp(pkt);
273 
274  // If packet successfully send, complete transaction in MemChecker
275  // instance, and delete sender state, otherwise restore state.
276  if (successful) {
277  if (is_read) {
279  "Received read response: serial = %d, addr = %#llx, "
280  "size = %d\n",
281  received_state->serial, addr, size);
282 
283  bool result = memchecker->completeRead(received_state->serial,
284  curTick(),
285  addr,
286  size,
287  pkt_data.get());
288 
289  if (!result) {
290  warn("%s: read of %#llx @ cycle %d failed:\n%s\n",
291  name(),
292  addr, curTick(),
293  memchecker->getErrorMessage().c_str());
294 
295  panic_if(!warnOnly, "MemChecker violation!");
296  }
297 
298  delete received_state;
299  } else if (is_write) {
301  "Received write response: serial = %d, addr = %#llx, "
302  "size = %d\n",
303  received_state->serial, addr, size);
304 
305  if (is_failed_LLSC) {
306  // The write was not successful, let MemChecker know.
307  memchecker->abortWrite(received_state->serial,
308  addr,
309  size);
310  } else {
311  memchecker->completeWrite(received_state->serial,
312  curTick(),
313  addr,
314  size);
315  }
316 
317  delete received_state;
318  } else {
320  "Received non read/write response: addr = %#llx\n", addr);
321  }
322  } else if (is_read || is_write) {
323  // Don't delete anything and let the packet look like we
324  // did not touch it
325  pkt->senderState = received_state;
326  }
327 
328  return successful;
329 }
330 
331 void
333 {
335 }
336 
337 bool
339 {
340  return masterPort.sendTimingSnoopResp(pkt);
341 }
342 
343 bool
345 {
346  // check if the connected master port is snooping
347  return slavePort.isSnooping();
348 }
349 
352 {
353  // get the address ranges of the connected slave port
354  return masterPort.getAddrRanges();
355 }
356 
357 void
359 {
361 }
362 
363 void
365 {
367 }
368 
369 void
371 {
373 }
~MemCheckerMonitor()
Destructor.
#define DPRINTF(x,...)
Definition: trace.hh:212
Tick recvAtomicSnoop(PacketPtr pkt)
bool recvTimingReq(PacketPtr pkt)
void completeWrite(Serial serial, Tick complete, Addr addr, size_t size)
Completes a previously started write transaction.
Definition: mem_checker.hh:545
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:423
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:175
bool isConnected() const
Definition: port.cc:84
const std::string & name()
Definition: trace.cc:49
uint64_t getExtraData() const
Accessor function for store conditional return value.
Definition: request.hh:688
void abortWrite(Serial serial, Addr addr, size_t size)
Aborts a previously started write transaction.
Definition: mem_checker.hh:558
bool sendTimingSnoopResp(PacketPtr pkt)
Attempt to send a timing snoop response packet to the slave port by calling its corresponding receive...
Definition: port.cc:194
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
Tick sendAtomicSnoop(PacketPtr pkt)
Send an atomic snoop request packet, where the data is moved and the state is updated in zero time...
Definition: port.cc:244
ip6_addr_t addr
Definition: inet.hh:335
bool cacheResponding() const
Definition: packet.hh:578
AddrRangeList getAddrRanges() const
Tick recvAtomic(PacketPtr pkt)
void sendFunctionalSnoop(PacketPtr pkt)
Send a functional snoop request packet, where the data is instantly updated everywhere in the memory ...
Definition: port.cc:251
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.cc:180
virtual BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID)
Get a slave port with a given name and index.
Definition: mem_object.cc:58
virtual void sendRetryResp()
Send a retry to the slave port that previously attempted a sendTimingResp to this master port and fai...
Definition: port.cc:201
bool isWrite() const
Definition: packet.hh:522
A BaseSlavePort is a protocol-agnostic slave port, responsible only for the structural connection to ...
Definition: port.hh:139
bool isRead() const
Definition: packet.hh:521
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:80
MemCheckerMonitor(Params *params)
Constructor based on the Python params.
MonitorMasterPort masterPort
Instance of master port, facing the memory side.
const std::string & getErrorMessage() const
In completeRead, if an error is encountered, this does not print nor cause an error, but instead should be handled by the caller.
Definition: mem_checker.hh:474
unsigned getSize() const
Definition: packet.hh:695
bool isRequest() const
Definition: packet.hh:524
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the master port by calling its corresponding receive function...
Definition: port.cc:258
Tick curTick()
The current simulated tick.
Definition: core.hh:47
bool needsResponse() const
Definition: packet.hh:535
SenderState * predecessor
Definition: packet.hh:398
uint64_t Tick
Tick count type.
Definition: types.hh:63
bool isResponse() const
Definition: packet.hh:525
void reset()
Resets the entire checker.
Definition: mem_checker.hh:452
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:323
MemCheckerMonitorParams Params
Parameters of memchecker monitor.
Addr getAddr() const
Definition: packet.hh:685
void recvFunctionalSnoop(PacketPtr pkt)
bool isSnooping() const
Find out if the peer master port is snooping or not.
Definition: port.hh:418
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
virtual const std::string name() const
Definition: sim_object.hh:117
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:254
Implements a MemChecker monitor, to be inserted between two ports.
MonitorSlavePort slavePort
Instance of slave port, i.e.
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
virtual void init()
init() is called after all C++ SimObjects have been created and all ports are connected.
virtual BaseSlavePort & getSlavePort(const std::string &if_name, PortID idx=InvalidPortID)
Get a slave port with a given name and index.
bool isLLSC() const
Definition: packet.hh:547
AddrRangeList getAddrRanges() const
Get the address ranges of the connected slave port.
Definition: port.cc:160
bool isPrefetch() const
Definition: request.hh:786
void sendRetryReq()
Send a retry to the master port that previously attempted a sendTimingReq to this slave port and fail...
Definition: port.cc:272
SenderState * senderState
This packet&#39;s sender state.
Definition: packet.hh:473
void recvTimingSnoopReq(PacketPtr pkt)
The MemObject class extends the ClockedObject with accessor functions to get its master and slave por...
Definition: mem_object.hh:60
A BaseMasterPort is a protocol-agnostic master port, responsible only for the structural connection t...
Definition: port.hh:115
Serial startWrite(Tick start, Addr addr, size_t size, const uint8_t *data)
Starts a write transaction.
Definition: mem_checker.hh:531
void sendTimingSnoopReq(PacketPtr pkt)
Attempt to send a timing snoop request packet to the master port by calling its corresponding receive...
Definition: port.cc:265
bool recvTimingSnoopResp(PacketPtr pkt)
const T * getConstPtr() const
Definition: packet.hh:1018
void recvFunctional(PacketPtr pkt)
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:351
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:359
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
bool isConnected() const
Definition: port.cc:110
#define warn(...)
Definition: logging.hh:212
bool recvTimingResp(PacketPtr pkt)
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time...
Definition: port.cc:166
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
Serial startRead(Tick start, Addr addr, size_t size)
Starts a read transaction.
Definition: mem_checker.hh:517
virtual BaseMasterPort & getMasterPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a master port with a given name and index.
Definition: mem_object.cc:52
void sendFunctional(PacketPtr pkt)
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.cc:173

Generated on Fri Apr 20 2018 09:05:03 for gem5 by doxygen 1.8.13