gem5 [DEVELOP-FOR-25.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
52 memSidePort(name() + "-memSidePort", *this),
53 cpuSidePort(name() + "-cpuSidePort", *this),
54 warnOnly(params.warn_only),
56{}
57
60
61void
63{
64 // make sure both sides of the monitor are connected
65 if (!cpuSidePort.isConnected() || !memSidePort.isConnected())
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
92 memSidePort.sendFunctional(pkt);
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
108 cpuSidePort.sendFunctionalSnoop(pkt);
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;
144 MemCheckerMonitorSenderState* state = NULL;
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)) {
159 state = new MemCheckerMonitorSenderState(0);
160 pkt->pushSenderState(state);
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) {
173 MemChecker::Serial serial = memchecker->startRead(curTick(),
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) {
195 MemChecker::Serial serial = memchecker->startWrite(curTick(),
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
317{
318 cpuSidePort.sendTimingSnoopReq(pkt);
319}
320
321bool
323{
324 return memSidePort.sendTimingSnoopResp(pkt);
325}
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
343{
344 cpuSidePort.sendRetryReq();
345}
346
347void
349{
350 memSidePort.sendRetryResp();
351}
352
353void
355{
356 cpuSidePort.sendRangeChange();
357}
358
359} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
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)
uint64_t Serial
The Serial type is used to be able to uniquely identify a transaction as it passes through the system...
virtual std::string name() const
Definition named.hh:60
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
std::list< AddrRange > AddrRangeList
Convenience typedef for a collection of address ranges.
Definition addr_range.hh:64
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
const Params & params() const
SimObject(const Params &p)
Definition sim_object.cc:58
virtual Port & getPort(const std::string &if_name, PortID idx=InvalidPortID)
Get a port with a given name and index.
#define warn(...)
Definition logging.hh:288
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 Arm Limited 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
Packet * PacketPtr
SenderState * predecessor
Definition packet.hh:470

Generated on Mon May 26 2025 09:19:12 for gem5 by doxygen 1.13.2