gem5  v22.0.0.2
memtest.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, 2019, 2021 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  * Copyright (c) 2002-2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
42 
43 #include "base/compiler.hh"
44 #include "base/random.hh"
45 #include "base/statistics.hh"
46 #include "base/trace.hh"
47 #include "debug/MemTest.hh"
48 #include "sim/sim_exit.hh"
49 #include "sim/stats.hh"
50 #include "sim/system.hh"
51 
52 namespace gem5
53 {
54 
55 static unsigned int TESTER_ALLOCATOR = 0;
56 
57 bool
59 {
61  return true;
62 }
63 
64 void
66 {
67  memtest.recvRetry();
68 }
69 
70 bool
72  if (atomic) {
73  port.sendAtomic(pkt);
74  completeRequest(pkt);
75  } else {
76  if (!port.sendTimingReq(pkt)) {
77  retryPkt = pkt;
78  return false;
79  }
80  }
81  return true;
82 }
83 
85  : ClockedObject(p),
86  tickEvent([this]{ tick(); }, name()),
87  noRequestEvent([this]{ noRequest(); }, name()),
88  noResponseEvent([this]{ noResponse(); }, name()),
89  port("port", *this),
90  retryPkt(nullptr),
91  waitResponse(false),
92  size(p.size),
93  interval(p.interval),
94  percentReads(p.percent_reads),
95  percentFunctional(p.percent_functional),
96  percentUncacheable(p.percent_uncacheable),
97  requestorId(p.system->getRequestorId(this)),
98  blockSize(p.system->cacheLineSize()),
99  blockAddrMask(blockSize - 1),
100  sizeBlocks(size / blockSize),
101  baseAddr1(p.base_addr_1),
102  baseAddr2(p.base_addr_2),
103  uncacheAddr(p.uncacheable_base_addr),
104  progressInterval(p.progress_interval),
105  progressCheck(p.progress_check),
106  nextProgressMessage(p.progress_interval),
107  maxLoads(p.max_loads),
108  atomic(p.system->isAtomicMode()),
109  suppressFuncErrors(p.suppress_func_errors), stats(this)
110 {
111  id = TESTER_ALLOCATOR++;
112  fatal_if(id >= blockSize, "Too many testers, only %d allowed\n",
113  blockSize - 1);
114 
115  // set up counters
116  numReads = 0;
117  numWrites = 0;
118 
119  // kick things into action
120  schedule(tickEvent, curTick());
121  schedule(noRequestEvent, clockEdge(progressCheck));
122 }
123 
124 Port &
125 MemTest::getPort(const std::string &if_name, PortID idx)
126 {
127  if (if_name == "port")
128  return port;
129  else
130  return ClockedObject::getPort(if_name, idx);
131 }
132 
133 void
134 MemTest::completeRequest(PacketPtr pkt, bool functional)
135 {
136  const RequestPtr &req = pkt->req;
137  assert(req->getSize() == 1);
138 
139  // this address is no longer outstanding
140  auto remove_addr = outstandingAddrs.find(req->getPaddr());
141  assert(remove_addr != outstandingAddrs.end());
142  outstandingAddrs.erase(remove_addr);
143 
144  DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
145  pkt->isWrite() ? "write" : "read",
146  req->getPaddr(), blockAlign(req->getPaddr()),
147  pkt->isError() ? "error" : "success");
148 
149  const uint8_t *pkt_data = pkt->getConstPtr<uint8_t>();
150 
151  if (pkt->isError()) {
152  if (!functional || !suppressFuncErrors)
153  panic( "%s access failed at %#x\n",
154  pkt->isWrite() ? "Write" : "Read", req->getPaddr());
155  } else {
156  if (pkt->isRead()) {
157  uint8_t ref_data = referenceData[req->getPaddr()];
158  if (pkt_data[0] != ref_data) {
159  panic("%s: read of %x (blk %x) @ cycle %d "
160  "returns %x, expected %x\n", name(),
161  req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
162  pkt_data[0], ref_data);
163  }
164 
165  numReads++;
166  stats.numReads++;
167 
168  if (numReads == (uint64_t)nextProgressMessage) {
169  ccprintf(std::cerr,
170  "%s: completed %d read, %d write accesses @%d\n",
171  name(), numReads, numWrites, curTick());
173  }
174 
175  if (maxLoads != 0 && numReads >= maxLoads)
176  exitSimLoop("maximum number of loads reached");
177  } else {
178  assert(pkt->isWrite());
179 
180  // update the reference data
181  referenceData[req->getPaddr()] = pkt_data[0];
182  numWrites++;
183  stats.numWrites++;
184  }
185  }
186 
187  // the packet will delete the data
188  delete pkt;
189 
190  // finally shift the response timeout forward if we are still
191  // expecting responses; deschedule it otherwise
192  if (outstandingAddrs.size() != 0)
194  else if (noResponseEvent.scheduled())
196 
197  // schedule the next tick
198  if (waitResponse) {
199  waitResponse = false;
201  }
202 }
204  : statistics::Group(parent),
205  ADD_STAT(numReads, statistics::units::Count::get(),
206  "number of read accesses completed"),
207  ADD_STAT(numWrites, statistics::units::Count::get(),
208  "number of write accesses completed")
209 {
210 
211 }
212 
213 void
215 {
216  // we should never tick if we are waiting for a retry or response
217  assert(!retryPkt);
218  assert(!waitResponse);
219 
220  // create a new request
221  unsigned cmd = random_mt.random(0, 100);
222  uint8_t data = random_mt.random<uint8_t>();
223  bool uncacheable = random_mt.random(0, 100) < percentUncacheable;
224  unsigned base = random_mt.random(0, 1);
226  Addr paddr;
227 
228  // halt until we clear outstanding requests, otherwise it won't be able to
229  // find a new unique address
230  if (outstandingAddrs.size() >= sizeBlocks) {
231  waitResponse = true;
232  return;
233  }
234 
235  // generate a unique address
236  do {
237  unsigned offset = random_mt.random<unsigned>(0, size - 1);
238 
239  // use the tester id as offset within the block for false sharing
241  offset += id;
242 
243  if (uncacheable) {
245  paddr = uncacheAddr + offset;
246  } else {
247  paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
248  }
249  } while (outstandingAddrs.find(paddr) != outstandingAddrs.end());
250 
251  bool do_functional = (random_mt.random(0, 100) < percentFunctional) &&
252  !uncacheable;
253  RequestPtr req = std::make_shared<Request>(paddr, 1, flags, requestorId);
254  req->setContext(id);
255 
256  outstandingAddrs.insert(paddr);
257 
258  // sanity check
259  panic_if(outstandingAddrs.size() > 100,
260  "Tester %s has more than 100 outstanding requests\n", name());
261 
262  PacketPtr pkt = nullptr;
263  uint8_t *pkt_data = new uint8_t[1];
264 
265  if (cmd < percentReads) {
266  // start by ensuring there is a reference value if we have not
267  // seen this address before
268  [[maybe_unused]] uint8_t ref_data = 0;
269  auto ref = referenceData.find(req->getPaddr());
270  if (ref == referenceData.end()) {
271  referenceData[req->getPaddr()] = 0;
272  } else {
273  ref_data = ref->second;
274  }
275 
277  "Initiating %sread at addr %x (blk %x) expecting %x\n",
278  do_functional ? "functional " : "", req->getPaddr(),
279  blockAlign(req->getPaddr()), ref_data);
280 
281  pkt = new Packet(req, MemCmd::ReadReq);
282  pkt->dataDynamic(pkt_data);
283  } else {
284  DPRINTF(MemTest, "Initiating %swrite at addr %x (blk %x) value %x\n",
285  do_functional ? "functional " : "", req->getPaddr(),
286  blockAlign(req->getPaddr()), data);
287 
288  pkt = new Packet(req, MemCmd::WriteReq);
289  pkt->dataDynamic(pkt_data);
290  pkt_data[0] = data;
291  }
292 
293  // there is no point in ticking if we are waiting for a retry
294  bool keep_ticking = true;
295  if (do_functional) {
296  pkt->setSuppressFuncError();
297  port.sendFunctional(pkt);
298  completeRequest(pkt, true);
299  } else {
300  keep_ticking = sendPkt(pkt);
301  }
302 
303  if (keep_ticking) {
304  // schedule the next tick
306 
307  // finally shift the timeout for sending of requests forwards
308  // as we have successfully sent a packet
310  } else {
311  DPRINTF(MemTest, "Waiting for retry\n");
312  }
313 
314  // Schedule noResponseEvent now if we are expecting a response
315  if (!noResponseEvent.scheduled() && (outstandingAddrs.size() != 0))
317 }
318 
319 void
321 {
322  panic("%s did not send a request for %d cycles", name(), progressCheck);
323 }
324 
325 void
327 {
328  panic("%s did not see a response for %d cycles", name(), progressCheck);
329 }
330 
331 void
333 {
334  assert(retryPkt);
335  if (port.sendTimingReq(retryPkt)) {
336  DPRINTF(MemTest, "Proceeding after successful retry\n");
337 
338  retryPkt = nullptr;
339  // kick things into action again
342  }
343 }
344 
345 } // namespace gem5
gem5::MemTest::numReads
uint64_t numReads
Definition: memtest.hh:170
gem5::MemTest::MemTest
MemTest(const Params &p)
Definition: memtest.cc:84
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:245
gem5::SimObject::getPort
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
gem5::MemTest::requestorId
RequestorID requestorId
Request id for all generated traffic.
Definition: memtest.hh:136
gem5::RequestPort::sendTimingReq
bool sendTimingReq(PacketPtr pkt)
Attempt to send a timing request to the responder port by calling its corresponding receive function.
Definition: port.hh:495
system.hh
gem5::MemTest::noResponse
void noResponse()
Definition: memtest.cc:326
gem5::MemTest
The MemTest class tests a cache coherent memory system by generating false sharing and verifying the ...
Definition: memtest.hh:70
data
const char data[]
Definition: circlebuf.test.cc:48
memtest.hh
gem5::MemTest::percentFunctional
const unsigned percentFunctional
Definition: memtest.hh:132
gem5::MemTest::nextProgressMessage
Tick nextProgressMessage
Definition: memtest.hh:168
gem5::Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:374
gem5::MemTest::sendPkt
bool sendPkt(PacketPtr pkt)
Definition: memtest.cc:71
gem5::MemTest::referenceData
std::unordered_map< Addr, uint8_t > referenceData
Definition: memtest.hh:143
gem5::RequestPort::sendAtomic
Tick sendAtomic(PacketPtr pkt)
Send an atomic request packet, where the data is moved and the state is updated in zero time,...
Definition: port.hh:464
gem5::MemTest::sizeBlocks
const unsigned sizeBlocks
Definition: memtest.hh:149
gem5::MemTest::percentUncacheable
const unsigned percentUncacheable
Definition: memtest.hh:133
random.hh
gem5::Packet::isWrite
bool isWrite() const
Definition: packet.hh:591
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::MemTest::retryPkt
PacketPtr retryPkt
Definition: memtest.hh:121
gem5::MemTest::tick
void tick()
Definition: memtest.cc:214
gem5::X86ISA::base
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
sim_exit.hh
gem5::MemTest::numWrites
uint64_t numWrites
Definition: memtest.hh:171
gem5::MemTest::interval
const Cycles interval
Definition: memtest.hh:129
gem5::MemTest::noResponseEvent
EventFunctionWrapper noResponseEvent
Definition: memtest.hh:94
gem5::ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:130
gem5::exitSimLoop
void exitSimLoop(const std::string &message, int exit_code, Tick when, Tick repeat, bool serialize)
Schedule an event to exit the simulation loop (returning to Python) at the end of the current cycle (...
Definition: sim_events.cc:88
gem5::MemTest::uncacheAddr
const Addr uncacheAddr
Definition: memtest.hh:164
gem5::Random::random
std::enable_if_t< std::is_integral_v< T >, T > random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:90
gem5::MemTest::recvRetry
void recvRetry()
Definition: memtest.cc:332
gem5::ArmISA::atomic
Bitfield< 23, 20 > atomic
Definition: misc_types.hh:100
stats.hh
gem5::Flags< FlagsType >
gem5::RequestPort::sendFunctional
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:485
gem5::Packet::isRead
bool isRead() const
Definition: packet.hh:590
gem5::Request::UNCACHEABLE
@ UNCACHEABLE
The request is to an uncacheable address.
Definition: request.hh:125
gem5::Named::name
virtual std::string name() const
Definition: named.hh:47
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::MemTest::stats
gem5::MemTest::MemTestStats stats
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:75
gem5::Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:291
gem5::MemTest::waitResponse
bool waitResponse
Definition: memtest.hh:125
gem5::probing::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
statistics.hh
gem5::MemTest::noRequestEvent
EventFunctionWrapper noRequestEvent
Definition: memtest.hh:90
gem5::MemTest::port
CpuPort port
Definition: memtest.hh:119
gem5::MemTest::tickEvent
EventFunctionWrapper tickEvent
Definition: memtest.hh:86
gem5::MemTest::suppressFuncErrors
const bool suppressFuncErrors
Definition: memtest.hh:176
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
gem5::Packet::getConstPtr
const T * getConstPtr() const
Definition: packet.hh:1206
gem5::MemCmd::ReadReq
@ ReadReq
Definition: packet.hh:86
gem5::MemTest::CpuPort::recvTimingResp
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: memtest.cc:58
gem5::MemTest::MemTestStats::numWrites
statistics::Scalar numWrites
Definition: memtest.hh:182
gem5::MemTest::getPort
Port & getPort(const std::string &if_name, PortID idx=InvalidPortID) override
Get a port with a given name and index.
Definition: memtest.cc:125
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1037
compiler.hh
flags
uint8_t flags
Definition: helpers.cc:66
gem5::Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
gem5::Packet::isError
bool isError() const
Definition: packet.hh:619
name
const std::string & name()
Definition: trace.cc:49
gem5::ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:234
gem5::Clocked::clockEdge
Tick clockEdge(Cycles cycles=Cycles(0)) const
Determine the tick when a cycle begins, by default the current one, but the argument also enables the...
Definition: clocked_object.hh:177
gem5::EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1028
gem5::MemTest::progressInterval
const unsigned progressInterval
Definition: memtest.hh:166
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
gem5::MemTest::maxLoads
const uint64_t maxLoads
Definition: memtest.hh:172
gem5::MemTest::atomic
const bool atomic
Definition: memtest.hh:174
gem5::MemTest::Params
MemTestParams Params
Definition: memtest.hh:75
gem5::MemTest::MemTestStats::numReads
statistics::Scalar numReads
Definition: memtest.hh:181
gem5::Packet::dataDynamic
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1185
gem5::MemTest::baseAddr2
const Addr baseAddr2
Definition: memtest.hh:163
gem5::MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:89
gem5::MemTest::size
const unsigned size
Definition: memtest.hh:127
gem5::MemTest::blockAlign
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition: memtest.hh:157
gem5::statistics::Group
Statistics container.
Definition: group.hh:93
gem5::MemTest::progressCheck
const Cycles progressCheck
Definition: memtest.hh:167
gem5::TESTER_ALLOCATOR
static unsigned int TESTER_ALLOCATOR
Definition: memtest.cc:55
trace.hh
gem5::MemTest::CpuPort::memtest
MemTest & memtest
Definition: memtest.hh:98
gem5::MemTest::percentReads
const unsigned percentReads
Definition: memtest.hh:131
gem5::MemTest::outstandingAddrs
std::unordered_set< Addr > outstandingAddrs
Definition: memtest.hh:140
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::MemTest::baseAddr1
const Addr baseAddr1
Definition: memtest.hh:162
gem5::random_mt
Random random_mt
Definition: random.cc:99
gem5::Packet::setSuppressFuncError
void setSuppressFuncError()
Definition: packet.hh:753
gem5::MemTest::completeRequest
void completeRequest(PacketPtr pkt, bool functional=false)
Complete a request by checking the response.
Definition: memtest.cc:134
gem5::MemTest::MemTestStats::MemTestStats
MemTestStats(statistics::Group *parent)
Definition: memtest.cc:203
gem5::MemTest::CpuPort::recvReqRetry
void recvReqRetry()
Called by the peer if sendTimingReq was called on this peer (causing recvTimingReq to be called on th...
Definition: memtest.cc:65
gem5::Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:465
gem5::MemTest::id
unsigned int id
Definition: memtest.hh:138
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
gem5::MemTest::noRequest
void noRequest()
Definition: memtest.cc:320

Generated on Thu Jul 28 2022 13:32:29 for gem5 by doxygen 1.8.17