gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
50 using namespace std;
51 
53  : MemObject(params),
54  masterPort(name() + "-master", *this),
55  slavePort(name() + "-slave", *this),
56  warnOnly(params->warn_only),
57  memchecker(params->memchecker)
58 {}
59 
61 {}
62 
64 MemCheckerMonitorParams::create()
65 {
66  return new MemCheckerMonitor(this);
67 }
68 
69 void
71 {
72  // make sure both sides of the monitor are connected
74  fatal("Communication monitor is not connected on both sides.\n");
75 }
76 
78 MemCheckerMonitor::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 
88 MemCheckerMonitor::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 
97 void
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 
109 
111  "Forwarded functional access: addr = %#llx, size = %d\n",
112  addr, size);
113 }
114 
115 void
117 {
118  Addr addr = pkt->getAddr();
119  unsigned size = pkt->getSize();
120 
121  // See above.
122  memchecker->reset(addr, size);
123 
125 
127  "Received functional snoop: addr = %#llx, size = %d\n",
128  addr, size);
129 }
130 
131 Tick
133 {
134  assert(false && "Atomic not supported");
135  return masterPort.sendAtomic(pkt);
136 }
137 
138 Tick
140 {
141  assert(false && "Atomic not supported");
142  return slavePort.sendAtomicSnoop(pkt);
143 }
144 
145 bool
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) {
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 
209  "Forwarded read request: serial = %d, addr = %#llx, "
210  "size = %d\n",
211  serial, addr, size);
212  } else if (is_write) {
214  addr,
215  size,
216  pkt_data.get());
217 
218  state->serial = serial;
219 
221  "Forwarded write request: serial = %d, addr = %#llx, "
222  "size = %d\n",
223  serial, addr, size);
224  } else {
226  "Forwarded non read/write request: addr = %#llx\n", addr);
227  }
228  } else if (successful) {
230  "Forwarded request marked for cache response: addr = %#llx\n",
231  addr);
232  }
233 
234  return successful;
235 }
236 
237 bool
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) {
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) {
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 {
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 
333 void
335 {
337 }
338 
339 bool
341 {
342  return masterPort.sendTimingSnoopResp(pkt);
343 }
344 
345 bool
347 {
348  // check if the connected master port is snooping
349  return slavePort.isSnooping();
350 }
351 
354 {
355  // get the address ranges of the connected slave port
356  return masterPort.getAddrRanges();
357 }
358 
359 void
361 {
363 }
364 
365 void
367 {
369 }
370 
371 void
373 {
375 }
~MemCheckerMonitor()
Destructor.
#define DPRINTF(x,...)
Definition: trace.hh:212
AddrRangeList getAddrRanges() const
bool isLLSC() const
Definition: packet.hh:527
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
const std::string & name()
Definition: trace.cc:49
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:187
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:237
uint64_t getExtraData() const
Accessor function for store conditional return value.
Definition: request.hh:672
ip6_addr_t addr
Definition: inet.hh:335
bool isWrite() const
Definition: packet.hh:503
panic_if(!root,"Invalid expression\n")
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:244
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:194
bool isPrefetch() const
Definition: request.hh:770
bool isRequest() const
Definition: packet.hh:505
A BaseSlavePort is a protocol-agnostic slave port, responsible only for the structural connection to ...
Definition: port.hh:139
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.
#define warn(...)
Definition: misc.hh:219
bool isSnooping() const
Find out if the peer master port is snooping or not.
Definition: port.hh:405
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the master port by calling its corresponding receive function...
Definition: port.cc:251
Tick curTick()
The current simulated tick.
Definition: core.hh:47
SenderState * predecessor
Definition: packet.hh:379
uint64_t Tick
Tick count type.
Definition: types.hh:63
void reset()
Resets the entire checker.
Definition: mem_checker.hh:452
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
#define fatal(...)
Definition: misc.hh:163
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
MemCheckerMonitorParams Params
Parameters of memchecker monitor.
bool needsResponse() const
Definition: packet.hh:516
void recvFunctionalSnoop(PacketPtr pkt)
bool isRead() const
Definition: packet.hh:502
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
bool cacheResponding() const
Definition: packet.hh:558
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
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.
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:410
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 isConnected() const
Definition: port.cc:84
int size()
Definition: pagetable.hh:146
virtual const std::string name() const
Definition: sim_object.hh:117
AddrRangeList getAddrRanges() const
Get the address ranges of the connected slave port.
Definition: port.cc:160
void sendRetryReq()
Send a retry to the master port that previously attempted a sendTimingReq to this slave port and fail...
Definition: port.cc:265
SenderState * senderState
This packet's sender state.
Definition: packet.hh:454
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
bool isConnected() const
Definition: port.cc:110
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:258
bool recvTimingSnoopResp(PacketPtr pkt)
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:329
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:337
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:181
const T * getConstPtr() const
Definition: packet.hh:967
bool recvTimingResp(PacketPtr pkt)
unsigned getSize() const
Definition: packet.hh:649
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
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
bool isResponse() const
Definition: packet.hh:506
Addr getAddr() const
Definition: packet.hh:639

Generated on Fri Jun 9 2017 13:03:49 for gem5 by doxygen 1.8.6