gem5  v21.1.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  size(p.size),
92  interval(p.interval),
93  percentReads(p.percent_reads),
94  percentFunctional(p.percent_functional),
95  percentUncacheable(p.percent_uncacheable),
96  requestorId(p.system->getRequestorId(this)),
97  blockSize(p.system->cacheLineSize()),
98  blockAddrMask(blockSize - 1),
99  baseAddr1(p.base_addr_1),
100  baseAddr2(p.base_addr_2),
101  uncacheAddr(p.uncacheable_base_addr),
102  progressInterval(p.progress_interval),
103  progressCheck(p.progress_check),
104  nextProgressMessage(p.progress_interval),
105  maxLoads(p.max_loads),
106  atomic(p.system->isAtomicMode()),
107  suppressFuncErrors(p.suppress_func_errors), stats(this)
108 {
109  id = TESTER_ALLOCATOR++;
110  fatal_if(id >= blockSize, "Too many testers, only %d allowed\n",
111  blockSize - 1);
112 
113  // set up counters
114  numReads = 0;
115  numWrites = 0;
116 
117  // kick things into action
118  schedule(tickEvent, curTick());
119  schedule(noRequestEvent, clockEdge(progressCheck));
120 }
121 
122 Port &
123 MemTest::getPort(const std::string &if_name, PortID idx)
124 {
125  if (if_name == "port")
126  return port;
127  else
128  return ClockedObject::getPort(if_name, idx);
129 }
130 
131 void
132 MemTest::completeRequest(PacketPtr pkt, bool functional)
133 {
134  const RequestPtr &req = pkt->req;
135  assert(req->getSize() == 1);
136 
137  // this address is no longer outstanding
138  auto remove_addr = outstandingAddrs.find(req->getPaddr());
139  assert(remove_addr != outstandingAddrs.end());
140  outstandingAddrs.erase(remove_addr);
141 
142  DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
143  pkt->isWrite() ? "write" : "read",
144  req->getPaddr(), blockAlign(req->getPaddr()),
145  pkt->isError() ? "error" : "success");
146 
147  const uint8_t *pkt_data = pkt->getConstPtr<uint8_t>();
148 
149  if (pkt->isError()) {
150  if (!functional || !suppressFuncErrors)
151  panic( "%s access failed at %#x\n",
152  pkt->isWrite() ? "Write" : "Read", req->getPaddr());
153  } else {
154  if (pkt->isRead()) {
155  uint8_t ref_data = referenceData[req->getPaddr()];
156  if (pkt_data[0] != ref_data) {
157  panic("%s: read of %x (blk %x) @ cycle %d "
158  "returns %x, expected %x\n", name(),
159  req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
160  pkt_data[0], ref_data);
161  }
162 
163  numReads++;
164  stats.numReads++;
165 
166  if (numReads == (uint64_t)nextProgressMessage) {
167  ccprintf(std::cerr,
168  "%s: completed %d read, %d write accesses @%d\n",
169  name(), numReads, numWrites, curTick());
171  }
172 
173  if (maxLoads != 0 && numReads >= maxLoads)
174  exitSimLoop("maximum number of loads reached");
175  } else {
176  assert(pkt->isWrite());
177 
178  // update the reference data
179  referenceData[req->getPaddr()] = pkt_data[0];
180  numWrites++;
181  stats.numWrites++;
182  }
183  }
184 
185  // the packet will delete the data
186  delete pkt;
187 
188  // finally shift the response timeout forward if we are still
189  // expecting responses; deschedule it otherwise
190  if (outstandingAddrs.size() != 0)
192  else if (noResponseEvent.scheduled())
194 }
196  : statistics::Group(parent),
197  ADD_STAT(numReads, statistics::units::Count::get(),
198  "number of read accesses completed"),
199  ADD_STAT(numWrites, statistics::units::Count::get(),
200  "number of write accesses completed")
201 {
202 
203 }
204 
205 void
207 {
208  // we should never tick if we are waiting for a retry
209  assert(!retryPkt);
210 
211  // create a new request
212  unsigned cmd = random_mt.random(0, 100);
213  uint8_t data = random_mt.random<uint8_t>();
214  bool uncacheable = random_mt.random(0, 100) < percentUncacheable;
215  unsigned base = random_mt.random(0, 1);
216  Request::Flags flags;
217  Addr paddr;
218 
219  // generate a unique address
220  do {
221  unsigned offset = random_mt.random<unsigned>(0, size - 1);
222 
223  // use the tester id as offset within the block for false sharing
225  offset += id;
226 
227  if (uncacheable) {
228  flags.set(Request::UNCACHEABLE);
229  paddr = uncacheAddr + offset;
230  } else {
231  paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
232  }
233  } while (outstandingAddrs.find(paddr) != outstandingAddrs.end());
234 
235  bool do_functional = (random_mt.random(0, 100) < percentFunctional) &&
236  !uncacheable;
237  RequestPtr req = std::make_shared<Request>(paddr, 1, flags, requestorId);
238  req->setContext(id);
239 
240  outstandingAddrs.insert(paddr);
241 
242  // sanity check
243  panic_if(outstandingAddrs.size() > 100,
244  "Tester %s has more than 100 outstanding requests\n", name());
245 
246  PacketPtr pkt = nullptr;
247  uint8_t *pkt_data = new uint8_t[1];
248 
249  if (cmd < percentReads) {
250  // start by ensuring there is a reference value if we have not
251  // seen this address before
252  GEM5_VAR_USED uint8_t ref_data = 0;
253  auto ref = referenceData.find(req->getPaddr());
254  if (ref == referenceData.end()) {
255  referenceData[req->getPaddr()] = 0;
256  } else {
257  ref_data = ref->second;
258  }
259 
261  "Initiating %sread at addr %x (blk %x) expecting %x\n",
262  do_functional ? "functional " : "", req->getPaddr(),
263  blockAlign(req->getPaddr()), ref_data);
264 
265  pkt = new Packet(req, MemCmd::ReadReq);
266  pkt->dataDynamic(pkt_data);
267  } else {
268  DPRINTF(MemTest, "Initiating %swrite at addr %x (blk %x) value %x\n",
269  do_functional ? "functional " : "", req->getPaddr(),
270  blockAlign(req->getPaddr()), data);
271 
272  pkt = new Packet(req, MemCmd::WriteReq);
273  pkt->dataDynamic(pkt_data);
274  pkt_data[0] = data;
275  }
276 
277  // there is no point in ticking if we are waiting for a retry
278  bool keep_ticking = true;
279  if (do_functional) {
280  pkt->setSuppressFuncError();
281  port.sendFunctional(pkt);
282  completeRequest(pkt, true);
283  } else {
284  keep_ticking = sendPkt(pkt);
285  }
286 
287  if (keep_ticking) {
288  // schedule the next tick
290 
291  // finally shift the timeout for sending of requests forwards
292  // as we have successfully sent a packet
294  } else {
295  DPRINTF(MemTest, "Waiting for retry\n");
296  }
297 
298  // Schedule noResponseEvent now if we are expecting a response
299  if (!noResponseEvent.scheduled() && (outstandingAddrs.size() != 0))
301 }
302 
303 void
305 {
306  panic("%s did not send a request for %d cycles", name(), progressCheck);
307 }
308 
309 void
311 {
312  panic("%s did not see a response for %d cycles", name(), progressCheck);
313 }
314 
315 void
317 {
318  assert(retryPkt);
319  if (port.sendTimingReq(retryPkt)) {
320  DPRINTF(MemTest, "Proceeding after successful retry\n");
321 
322  retryPkt = nullptr;
323  // kick things into action again
326  }
327 }
328 
329 } // namespace gem5
gem5::MemTest::numReads
uint64_t numReads
Definition: memtest.hh:164
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:252
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:132
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:310
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:128
gem5::MemTest::nextProgressMessage
Tick nextProgressMessage
Definition: memtest.hh:162
gem5::Flags::set
void set(Type mask)
Set all flag's bits matching the given mask.
Definition: flags.hh:116
gem5::Request::UNCACHEABLE
@ UNCACHEABLE
The request is to an uncacheable address.
Definition: request.hh:125
gem5::Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:366
gem5::MemTest::sendPkt
bool sendPkt(PacketPtr pkt)
Definition: memtest.cc:71
gem5::MemTest::referenceData
std::unordered_map< Addr, uint8_t > referenceData
Definition: memtest.hh:139
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::percentUncacheable
const unsigned percentUncacheable
Definition: memtest.hh:129
random.hh
gem5::Packet::isWrite
bool isWrite() const
Definition: packet.hh:583
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:206
gem5::X86ISA::base
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
sim_exit.hh
gem5::MemTest::numWrites
uint64_t numWrites
Definition: memtest.hh:165
gem5::MemTest::interval
const Cycles interval
Definition: memtest.hh:125
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:158
gem5::MemTest::recvRetry
void recvRetry()
Definition: memtest.cc:316
gem5::ArmISA::atomic
Bitfield< 23, 20 > atomic
Definition: misc_types.hh:99
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:582
gem5::Random::random
std::enable_if_t< std::is_integral< T >::value, 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::Named::name
virtual std::string name() const
Definition: named.hh:47
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:283
gem5::probing::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:109
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
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:170
gem5::RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:92
gem5::Packet::getConstPtr
const T * getConstPtr() const
Definition: packet.hh:1193
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:176
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:123
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
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:610
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:160
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:203
gem5::MemTest::maxLoads
const uint64_t maxLoads
Definition: memtest.hh:166
gem5::MemTest::atomic
const bool atomic
Definition: memtest.hh:168
gem5::MemTest::Params
MemTestParams Params
Definition: memtest.hh:75
gem5::MemTest::MemTestStats::numReads
statistics::Scalar numReads
Definition: memtest.hh:175
gem5::Packet::dataDynamic
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1172
gem5::MemTest::baseAddr2
const Addr baseAddr2
Definition: memtest.hh:157
gem5::MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:89
gem5::MemTest::size
const unsigned size
Definition: memtest.hh:123
gem5::MemTest::blockAlign
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition: memtest.hh:151
gem5::statistics::Group
Statistics container.
Definition: group.hh:93
gem5::MemTest::progressCheck
const Cycles progressCheck
Definition: memtest.hh:161
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:127
gem5::MemTest::outstandingAddrs
std::unordered_set< Addr > outstandingAddrs
Definition: memtest.hh:136
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:225
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::MemTest::baseAddr1
const Addr baseAddr1
Definition: memtest.hh:156
gem5::random_mt
Random random_mt
Definition: random.cc:99
gem5::Packet::setSuppressFuncError
void setSuppressFuncError()
Definition: packet.hh:744
gem5::MemTest::completeRequest
void completeRequest(PacketPtr pkt, bool functional=false)
Complete a request by checking the response.
Definition: memtest.cc:132
gem5::MemTest::MemTestStats::MemTestStats
MemTestStats(statistics::Group *parent)
Definition: memtest.cc:195
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:134
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
gem5::MemTest::noRequest
void noRequest()
Definition: memtest.cc:304

Generated on Tue Sep 21 2021 12:25:09 for gem5 by doxygen 1.8.17