gem5  v19.0.0.0
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  * Authors: Thomas Grass
38  * Andreas Hansson
39  * Marco Elver
40  */
41 
43 
44 #include <memory>
45 
46 #include "base/logging.hh"
47 #include "base/output.hh"
48 #include "base/trace.hh"
49 #include "debug/MemCheckerMonitor.hh"
50 
52  : SimObject(params),
53  masterPort(name() + "-master", *this),
54  slavePort(name() + "-slave", *this),
55  warnOnly(params->warn_only),
56  memchecker(params->memchecker)
57 {}
58 
60 {}
61 
63 MemCheckerMonitorParams::create()
64 {
65  return new MemCheckerMonitor(this);
66 }
67 
68 void
70 {
71  // make sure both sides of the monitor are connected
73  fatal("Communication monitor is not connected on both sides.\n");
74 }
75 
76 Port &
77 MemCheckerMonitor::getPort(const std::string &if_name, PortID idx)
78 {
79  if (if_name == "master" || if_name == "mem_side") {
80  return masterPort;
81  } else if (if_name == "slave" || if_name == "cpu_side") {
82  return slavePort;
83  } else {
84  return SimObject::getPort(if_name, idx);
85  }
86 }
87 
88 void
90 {
91  Addr addr = pkt->getAddr();
92  unsigned size = pkt->getSize();
93 
94  // Conservatively reset this address-range. Alternatively we could try to
95  // update the values seen by the memchecker, however, there may be other
96  // reads/writes to these location from other devices we do not see.
97  memchecker->reset(addr, size);
98 
100 
102  "Forwarded functional access: addr = %#llx, size = %d\n",
103  addr, size);
104 }
105 
106 void
108 {
109  Addr addr = pkt->getAddr();
110  unsigned size = pkt->getSize();
111 
112  // See above.
113  memchecker->reset(addr, size);
114 
116 
118  "Received functional snoop: addr = %#llx, size = %d\n",
119  addr, size);
120 }
121 
122 Tick
124 {
125  panic("Atomic not supported");
126 }
127 
128 Tick
130 {
131  panic("Atomic not supported");
132 }
133 
134 bool
136 {
137  // should always see a request
138  assert(pkt->isRequest());
139 
140  // Store relevant fields of packet, because packet may be modified
141  // or even deleted when sendTiming() is called.
142  //
143  // For reads we are only interested in real reads, and not prefetches, as
144  // it is not guaranteed that the prefetch returns any useful data.
145  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
146  bool is_write = pkt->isWrite();
147  unsigned size = pkt->getSize();
148  Addr addr = pkt->getAddr();
149  bool expects_response = pkt->needsResponse() && !pkt->cacheResponding();
150  std::unique_ptr<uint8_t[]> pkt_data;
151  MemCheckerMonitorSenderState* state = NULL;
152 
153  if (expects_response && is_write) {
154  // On receipt of a request, only need to allocate pkt_data if this is a
155  // write. For reads, we have no data yet, so it doesn't make sense to
156  // allocate.
157  pkt_data.reset(new uint8_t[size]);
158  pkt->writeData(pkt_data.get());
159  }
160 
161  // If a cache miss is served by a cache, a monitor near the memory
162  // would see a request which needs a response, but this response
163  // would not come back from the memory. Therefore
164  // we additionally have to check the inhibit flag.
165  if (expects_response && (is_read || is_write)) {
166  state = new MemCheckerMonitorSenderState(0);
167  pkt->pushSenderState(state);
168  }
169 
170  // Attempt to send the packet
171  bool successful = masterPort.sendTimingReq(pkt);
172 
173  // If not successful, restore the sender state
174  if (!successful && expects_response && (is_read || is_write)) {
175  delete pkt->popSenderState();
176  }
177 
178  if (successful && expects_response) {
179  if (is_read) {
181  addr,
182  size);
183 
184  // At the time where we push the sender-state, we do not yet know
185  // the serial the MemChecker class will assign to this request. We
186  // cannot call startRead at the time we push the sender-state, as
187  // the masterPort may not be successful in executing sendTimingReq,
188  // and in case of a failure, we must not modify the state of the
189  // MemChecker.
190  //
191  // Once we know that sendTimingReq was successful, we can set the
192  // serial of the newly constructed sender-state. This is legal, as
193  // we know that nobody else will touch nor is responsible for
194  // deletion of our sender-state.
195  state->serial = serial;
196 
198  "Forwarded read request: serial = %d, addr = %#llx, "
199  "size = %d\n",
200  serial, addr, size);
201  } else if (is_write) {
203  addr,
204  size,
205  pkt_data.get());
206 
207  state->serial = serial;
208 
210  "Forwarded write request: serial = %d, addr = %#llx, "
211  "size = %d\n",
212  serial, addr, size);
213  } else {
215  "Forwarded non read/write request: addr = %#llx\n", addr);
216  }
217  } else if (successful) {
219  "Forwarded request marked for cache response: addr = %#llx\n",
220  addr);
221  }
222 
223  return successful;
224 }
225 
226 bool
228 {
229  // should always see responses
230  assert(pkt->isResponse());
231 
232  // Store relevant fields of packet, because packet may be modified
233  // or even deleted when sendTiming() is called.
234  bool is_read = pkt->isRead() && !pkt->req->isPrefetch();
235  bool is_write = pkt->isWrite();
236  bool is_failed_LLSC = pkt->isLLSC() && pkt->req->getExtraData() == 0;
237  unsigned size = pkt->getSize();
238  Addr addr = pkt->getAddr();
239  std::unique_ptr<uint8_t[]> pkt_data;
240  MemCheckerMonitorSenderState* received_state = NULL;
241 
242  if (is_read) {
243  // On receipt of a response, only need to allocate pkt_data if this is
244  // a read. For writes, we have already given the MemChecker the data on
245  // the request, so it doesn't make sense to allocate on write.
246  pkt_data.reset(new uint8_t[size]);
247  pkt->writeData(pkt_data.get());
248  }
249 
250  if (is_read || is_write) {
251  received_state =
252  dynamic_cast<MemCheckerMonitorSenderState*>(pkt->senderState);
253 
254  // Restore initial sender state
255  panic_if(received_state == NULL,
256  "Monitor got a response without monitor sender state\n");
257 
258  // Restore the state
259  pkt->senderState = received_state->predecessor;
260  }
261 
262  // Attempt to send the packet
263  bool successful = slavePort.sendTimingResp(pkt);
264 
265  // If packet successfully send, complete transaction in MemChecker
266  // instance, and delete sender state, otherwise restore state.
267  if (successful) {
268  if (is_read) {
270  "Received read response: serial = %d, addr = %#llx, "
271  "size = %d\n",
272  received_state->serial, addr, size);
273 
274  bool result = memchecker->completeRead(received_state->serial,
275  curTick(),
276  addr,
277  size,
278  pkt_data.get());
279 
280  if (!result) {
281  warn("%s: read of %#llx @ cycle %d failed:\n%s\n",
282  name(),
283  addr, curTick(),
284  memchecker->getErrorMessage().c_str());
285 
286  panic_if(!warnOnly, "MemChecker violation!");
287  }
288 
289  delete received_state;
290  } else if (is_write) {
292  "Received write response: serial = %d, addr = %#llx, "
293  "size = %d\n",
294  received_state->serial, addr, size);
295 
296  if (is_failed_LLSC) {
297  // The write was not successful, let MemChecker know.
298  memchecker->abortWrite(received_state->serial,
299  addr,
300  size);
301  } else {
302  memchecker->completeWrite(received_state->serial,
303  curTick(),
304  addr,
305  size);
306  }
307 
308  delete received_state;
309  } else {
311  "Received non read/write response: addr = %#llx\n", addr);
312  }
313  } else if (is_read || is_write) {
314  // Don't delete anything and let the packet look like we
315  // did not touch it
316  pkt->senderState = received_state;
317  }
318 
319  return successful;
320 }
321 
322 void
324 {
326 }
327 
328 bool
330 {
331  return masterPort.sendTimingSnoopResp(pkt);
332 }
333 
334 bool
336 {
337  // check if the connected master port is snooping
338  return slavePort.isSnooping();
339 }
340 
343 {
344  // get the address ranges of the connected slave port
345  return masterPort.getAddrRanges();
346 }
347 
348 void
350 {
352 }
353 
354 void
356 {
358 }
359 
360 void
362 {
364 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
~MemCheckerMonitor()
Destructor.
#define DPRINTF(x,...)
Definition: trace.hh:229
Ports are used to interface objects to each other.
Definition: port.hh:60
Tick recvAtomicSnoop(PacketPtr pkt)
bool recvTimingReq(PacketPtr pkt)
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
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:286
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:175
const std::string & name()
Definition: trace.cc:54
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.hh:457
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:298
ip6_addr_t addr
Definition: inet.hh:335
bool cacheResponding() const
Definition: packet.hh:591
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:445
bool isConnected() const
Is this port currently connected to a peer?
Definition: port.hh:128
virtual void sendRetryResp()
Send a retry to the slave port that previously attempted a sendTimingResp to this master port and fai...
Definition: port.hh:463
bool isWrite() const
Definition: packet.hh:529
bool isRead() const
Definition: packet.hh:528
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
void sendFunctionalSnoop(PacketPtr pkt) const
Send a functional snoop request packet, where the data is instantly updated everywhere in the memory ...
Definition: port.hh:337
MemCheckerMonitor(Params *params)
Constructor based on the Python params.
RequestPtr req
A pointer to the original request.
Definition: packet.hh:327
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:736
bool isRequest() const
Definition: packet.hh:531
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the master port by calling its corresponding receive function...
Definition: port.hh:357
Tick curTick()
The current simulated tick.
Definition: core.hh:47
bool needsResponse() const
Definition: packet.hh:542
SenderState * predecessor
Definition: packet.hh:405
uint64_t Tick
Tick count type.
Definition: types.hh:63
bool isResponse() const
Definition: packet.hh:532
void reset()
Resets the entire checker.
Definition: mem_checker.hh:452
MemCheckerMonitorParams Params
Parameters of memchecker monitor.
Addr getAddr() const
Definition: packet.hh:726
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
Definition: packet.hh:1187
void recvFunctionalSnoop(PacketPtr pkt)
bool isSnooping() const
Find out if the peer master port is snooping or not.
Definition: port.hh:280
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:120
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
Implements a MemChecker monitor, to be inserted between two ports.
MonitorSlavePort slavePort
Instance of slave port, i.e.
bool isLLSC() const
Definition: packet.hh:554
AddrRangeList getAddrRanges() const
Get the address ranges of the connected slave port.
Definition: port.cc:93
void sendRetryReq()
Send a retry to the master port that previously attempted a sendTimingReq to this slave port and fail...
Definition: port.hh:380
SenderState * senderState
This packet&#39;s sender state.
Definition: packet.hh:480
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:531
void sendTimingSnoopReq(PacketPtr pkt)
Attempt to send a timing snoop request packet to the master port by calling its corresponding receive...
Definition: port.hh:370
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:319
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition: packet.cc:327
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:439
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
#define warn(...)
Definition: logging.hh:212
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:185
Serial startRead(Tick start, Addr addr, size_t size)
Starts a read transaction.
Definition: mem_checker.hh:517
Abstract superclass for simulation objects.
Definition: sim_object.hh:96

Generated on Fri Feb 28 2020 16:27:02 for gem5 by doxygen 1.8.13