gem5  v20.0.0.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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 
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  masterPort(name() + "-master", *this),
50  slavePort(name() + "-slave", *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 == "master" || if_name == "mem_side") {
76  return masterPort;
77  } else if (if_name == "slave" || if_name == "cpu_side") {
78  return slavePort;
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 = masterPort.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 masterPort may not be successful in executing sendTimingReq,
184  // and in case of a failure, we must not modify the state of the
185  // 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 = slavePort.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 masterPort.sendTimingSnoopResp(pkt);
328 }
329 
330 bool
332 {
333  // check if the connected master port is snooping
334  return slavePort.isSnooping();
335 }
336 
339 {
340  // get the address ranges of the connected slave port
341  return masterPort.getAddrRanges();
342 }
343 
344 void
346 {
348 }
349 
350 void
352 {
354 }
355 
356 void
358 {
360 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
~MemCheckerMonitor()
Destructor.
#define DPRINTF(x,...)
Definition: trace.hh:222
Ports are used to interface objects to each other.
Definition: port.hh:56
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:542
void sendRangeChange() const
Called by the owner to send a range change.
Definition: port.hh:282
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:171
const std::string & name()
Definition: trace.cc:50
void abortWrite(Serial serial, Addr addr, size_t size)
Aborts a previously started write transaction.
Definition: mem_checker.hh:555
bool sendTimingSnoopResp(PacketPtr pkt)
Attempt to send a timing snoop response packet to the slave port by calling its corresponding receive...
Definition: port.hh:453
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
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
ip6_addr_t addr
Definition: inet.hh:330
bool cacheResponding() const
Definition: packet.hh:585
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
AddrRangeList getAddrRanges() const
Tick recvAtomic(PacketPtr pkt)
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the slave port by calling its corresponding receive function...
Definition: port.hh:441
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:124
virtual void sendRetryResp()
Send a retry to the slave port that previously attempted a sendTimingResp to this master port and fai...
Definition: port.hh:459
bool isWrite() const
Definition: packet.hh:523
bool isRead() const
Definition: packet.hh:522
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
void sendFunctionalSnoop(PacketPtr pkt) const
Send a functional snoop request packet, where the data is instantly updated everywhere in the memory ...
Definition: port.hh:333
MemCheckerMonitor(Params *params)
Constructor based on the Python params.
RequestPtr req
A pointer to the original request.
Definition: packet.hh:321
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:471
unsigned getSize() const
Definition: packet.hh:730
bool isRequest() const
Definition: packet.hh:525
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the master port by calling its corresponding receive function...
Definition: port.hh:353
Tick curTick()
The current simulated tick.
Definition: core.hh:44
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
bool needsResponse() const
Definition: packet.hh:536
SenderState * predecessor
Definition: packet.hh:399
uint64_t Tick
Tick count type.
Definition: types.hh:61
bool isResponse() const
Definition: packet.hh:526
void reset()
Resets the entire checker.
Definition: mem_checker.hh:449
MemCheckerMonitorParams Params
Parameters of memchecker monitor.
Addr getAddr() const
Definition: packet.hh:720
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
Definition: packet.hh:1181
void recvFunctionalSnoop(PacketPtr pkt)
bool isSnooping() const
Find out if the peer master port is snooping or not.
Definition: port.hh:276
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
Implements a MemChecker monitor, to be inserted between two ports.
MonitorSlavePort slavePort
Instance of slave port, i.e.
bool isLLSC() const
Definition: packet.hh:548
virtual const std::string name() const
Definition: sim_object.hh:128
AddrRangeList getAddrRanges() const
Get the address ranges of the connected slave port.
Definition: port.cc:89
void sendRetryReq()
Send a retry to the master port that previously attempted a sendTimingReq to this slave port and fail...
Definition: port.hh:376
SenderState * senderState
This packet&#39;s sender state.
Definition: packet.hh:474
void recvTimingSnoopReq(PacketPtr pkt)
Serial startWrite(Tick start, Addr addr, size_t size, const uint8_t *data)
Starts a write transaction.
Definition: mem_checker.hh:528
void sendTimingSnoopReq(PacketPtr pkt)
Attempt to send a timing snoop request packet to the master port by calling its corresponding receive...
Definition: port.hh:366
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:316
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:324
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:435
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:235
#define warn(...)
Definition: logging.hh:208
bool recvTimingResp(PacketPtr pkt)
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:181
Serial startRead(Tick start, Addr addr, size_t size)
Starts a read transaction.
Definition: mem_checker.hh:514
Abstract superclass for simulation objects.
Definition: sim_object.hh:92

Generated on Mon Jun 8 2020 15:45:12 for gem5 by doxygen 1.8.13