gem5 v24.0.0.0
Loading...
Searching...
No Matches
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
47namespace 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
60
61void
63{
64 // make sure both sides of the monitor are connected
66 fatal("Communication monitor is not connected on both sides.\n");
67}
68
69Port &
70MemCheckerMonitor::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
81void
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
99void
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
115Tick
117{
118 panic("Atomic not supported");
119}
120
121Tick
123{
124 panic("Atomic not supported");
125}
126
127bool
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;
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)) {
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
219bool
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
315void
320
321bool
326
327bool
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
341void
346
347void
352
353void
358
359} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Implements a MemChecker monitor, to be inserted between two ports.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
void recvFunctionalSnoop(PacketPtr pkt)
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
bool recvTimingSnoopResp(PacketPtr pkt)
Tick recvAtomicSnoop(PacketPtr pkt)
MemCheckerMonitorParams Params
Parameters of memchecker monitor.
bool recvTimingResp(PacketPtr pkt)
MemCheckerMonitor(const Params &params)
Constructor based on the Python params.
void recvTimingSnoopReq(PacketPtr pkt)
void recvFunctional(PacketPtr pkt)
MonitorResponsePort cpuSidePort
Instance of response port, i.e.
MonitorRequestPort memSidePort
Instance of request port, facing the memory side.
bool recvTimingReq(PacketPtr pkt)
AddrRangeList getAddrRanges() const
Tick recvAtomic(PacketPtr pkt)
void abortWrite(Serial serial, Addr addr, size_t size)
Aborts a previously started write transaction.
const std::string & getErrorMessage() const
In completeRead, if an error is encountered, this does not print nor cause an error,...
bool completeRead(Serial serial, Tick complete, Addr addr, size_t size, uint8_t *data)
Completes a previously started read transaction.
void reset()
Resets the entire checker.
Serial startWrite(Tick start, Addr addr, size_t size, const uint8_t *data)
Starts a write transaction.
uint64_t Serial
The Serial type is used to be able to uniquely identify a transaction as it passes through the system...
Serial startRead(Tick start, Addr addr, size_t size)
Starts a read transaction.
void completeWrite(Serial serial, Tick complete, Addr addr, size_t size)
Completes a previously started write transaction.
virtual std::string name() const
Definition named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
bool isRead() const
Definition packet.hh:593
Addr getAddr() const
Definition packet.hh:807
bool isResponse() const
Definition packet.hh:598
bool needsResponse() const
Definition packet.hh:608
SenderState * senderState
This packet's sender state.
Definition packet.hh:545
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:334
SenderState * popSenderState()
Pop the top of the state stack and return a pointer to it.
Definition packet.cc:342
bool isWrite() const
Definition packet.hh:594
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
bool isLLSC() const
Definition packet.hh:620
bool cacheResponding() const
Definition packet.hh:659
void writeData(uint8_t *p) const
Copy data from the packet to the memory at the provided pointer.
Definition packet.hh:1322
bool isRequest() const
Definition packet.hh:597
Ports are used to interface objects to each other.
Definition port.hh:62
bool isConnected() const
Is this port currently connected to a peer?
Definition port.hh:133
virtual void sendRetryResp()
Send a retry to the response port that previously attempted a sendTimingResp to this request port and...
Definition port.hh:637
AddrRangeList getAddrRanges() const
Get the address ranges of the connected responder port.
Definition port.cc:172
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition port.hh:603
bool sendTimingSnoopResp(PacketPtr pkt)
Attempt to send a timing snoop response packet to the response port by calling its corresponding rece...
Definition port.hh:627
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition port.hh:579
bool sendTimingResp(PacketPtr pkt)
Attempt to send a timing response to the request port by calling its corresponding receive function.
Definition port.hh:454
void sendFunctionalSnoop(PacketPtr pkt) const
Send a functional snoop request packet, where the data is instantly updated everywhere in the memory ...
Definition port.hh:430
void sendTimingSnoopReq(PacketPtr pkt)
Attempt to send a timing snoop request packet to the request port by calling its corresponding receiv...
Definition port.hh:475
bool isSnooping() const
Find out if the peer request port is snooping or not.
Definition port.hh:375
void sendRangeChange() const
Called by the owner to send a range change.
Definition port.hh:380
void sendRetryReq()
Send a retry to the request port that previously attempted a sendTimingReq to this response port and ...
Definition port.hh:489
Abstract superclass for simulation objects.
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
atomic_var_t state
Definition helpers.cc:211
#define warn(...)
Definition logging.hh:256
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition types.hh:245
uint64_t Tick
Tick count type.
Definition types.hh:58
SenderState * predecessor
Definition packet.hh:470
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:05 for gem5 by doxygen 1.11.0