gem5  v20.1.0.0
memtest.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, 2019 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/random.hh"
44 #include "base/statistics.hh"
45 #include "base/trace.hh"
46 #include "debug/MemTest.hh"
47 #include "sim/sim_exit.hh"
48 #include "sim/stats.hh"
49 #include "sim/system.hh"
50 
51 using namespace std;
52 
53 unsigned int TESTER_ALLOCATOR = 0;
54 
55 bool
57 {
58  memtest.completeRequest(pkt);
59  return true;
60 }
61 
62 void
64 {
65  memtest.recvRetry();
66 }
67 
68 bool
70  if (atomic) {
71  port.sendAtomic(pkt);
72  completeRequest(pkt);
73  } else {
74  if (!port.sendTimingReq(pkt)) {
75  retryPkt = pkt;
76  return false;
77  }
78  }
79  return true;
80 }
81 
83  : ClockedObject(p),
84  tickEvent([this]{ tick(); }, name()),
85  noRequestEvent([this]{ noRequest(); }, name()),
86  noResponseEvent([this]{ noResponse(); }, name()),
87  port("port", *this),
88  retryPkt(nullptr),
89  size(p->size),
90  interval(p->interval),
91  percentReads(p->percent_reads),
92  percentFunctional(p->percent_functional),
93  percentUncacheable(p->percent_uncacheable),
94  requestorId(p->system->getRequestorId(this)),
95  blockSize(p->system->cacheLineSize()),
96  blockAddrMask(blockSize - 1),
97  progressInterval(p->progress_interval),
98  progressCheck(p->progress_check),
99  nextProgressMessage(p->progress_interval),
100  maxLoads(p->max_loads),
101  atomic(p->system->isAtomicMode()),
102  suppressFuncErrors(p->suppress_func_errors), stats(this)
103 {
104  id = TESTER_ALLOCATOR++;
105  fatal_if(id >= blockSize, "Too many testers, only %d allowed\n",
106  blockSize - 1);
107 
108  baseAddr1 = 0x100000;
109  baseAddr2 = 0x400000;
110  uncacheAddr = 0x800000;
111 
112  // set up counters
113  numReads = 0;
114  numWrites = 0;
115 
116  // kick things into action
117  schedule(tickEvent, curTick());
118  schedule(noRequestEvent, clockEdge(progressCheck));
119 }
120 
121 Port &
122 MemTest::getPort(const std::string &if_name, PortID idx)
123 {
124  if (if_name == "port")
125  return port;
126  else
127  return ClockedObject::getPort(if_name, idx);
128 }
129 
130 void
131 MemTest::completeRequest(PacketPtr pkt, bool functional)
132 {
133  const RequestPtr &req = pkt->req;
134  assert(req->getSize() == 1);
135 
136  // this address is no longer outstanding
137  auto remove_addr = outstandingAddrs.find(req->getPaddr());
138  assert(remove_addr != outstandingAddrs.end());
139  outstandingAddrs.erase(remove_addr);
140 
141  DPRINTF(MemTest, "Completing %s at address %x (blk %x) %s\n",
142  pkt->isWrite() ? "write" : "read",
143  req->getPaddr(), blockAlign(req->getPaddr()),
144  pkt->isError() ? "error" : "success");
145 
146  const uint8_t *pkt_data = pkt->getConstPtr<uint8_t>();
147 
148  if (pkt->isError()) {
149  if (!functional || !suppressFuncErrors)
150  panic( "%s access failed at %#x\n",
151  pkt->isWrite() ? "Write" : "Read", req->getPaddr());
152  } else {
153  if (pkt->isRead()) {
154  uint8_t ref_data = referenceData[req->getPaddr()];
155  if (pkt_data[0] != ref_data) {
156  panic("%s: read of %x (blk %x) @ cycle %d "
157  "returns %x, expected %x\n", name(),
158  req->getPaddr(), blockAlign(req->getPaddr()), curTick(),
159  pkt_data[0], ref_data);
160  }
161 
162  numReads++;
163  stats.numReads++;
164 
165  if (numReads == (uint64_t)nextProgressMessage) {
166  ccprintf(cerr, "%s: completed %d read, %d write accesses @%d\n",
167  name(), numReads, numWrites, curTick());
169  }
170 
171  if (maxLoads != 0 && numReads >= maxLoads)
172  exitSimLoop("maximum number of loads reached");
173  } else {
174  assert(pkt->isWrite());
175 
176  // update the reference data
177  referenceData[req->getPaddr()] = pkt_data[0];
178  numWrites++;
179  stats.numWrites++;
180  }
181  }
182 
183  // the packet will delete the data
184  delete pkt;
185 
186  // finally shift the response timeout forward if we are still
187  // expecting responses; deschedule it otherwise
188  if (outstandingAddrs.size() != 0)
190  else if (noResponseEvent.scheduled())
192 }
194  : Stats::Group(parent),
195  ADD_STAT(numReads, "number of read accesses completed"),
196  ADD_STAT(numWrites, "number of write accesses completed")
197 {
198 
199 }
200 
201 void
203 {
204  // we should never tick if we are waiting for a retry
205  assert(!retryPkt);
206 
207  // create a new request
208  unsigned cmd = random_mt.random(0, 100);
209  uint8_t data = random_mt.random<uint8_t>();
210  bool uncacheable = random_mt.random(0, 100) < percentUncacheable;
211  unsigned base = random_mt.random(0, 1);
212  Request::Flags flags;
213  Addr paddr;
214 
215  // generate a unique address
216  do {
217  unsigned offset = random_mt.random<unsigned>(0, size - 1);
218 
219  // use the tester id as offset within the block for false sharing
221  offset += id;
222 
223  if (uncacheable) {
224  flags.set(Request::UNCACHEABLE);
225  paddr = uncacheAddr + offset;
226  } else {
227  paddr = ((base) ? baseAddr1 : baseAddr2) + offset;
228  }
229  } while (outstandingAddrs.find(paddr) != outstandingAddrs.end());
230 
231  bool do_functional = (random_mt.random(0, 100) < percentFunctional) &&
232  !uncacheable;
233  RequestPtr req = std::make_shared<Request>(paddr, 1, flags, requestorId);
234  req->setContext(id);
235 
236  outstandingAddrs.insert(paddr);
237 
238  // sanity check
239  panic_if(outstandingAddrs.size() > 100,
240  "Tester %s has more than 100 outstanding requests\n", name());
241 
242  PacketPtr pkt = nullptr;
243  uint8_t *pkt_data = new uint8_t[1];
244 
245  if (cmd < percentReads) {
246  // start by ensuring there is a reference value if we have not
247  // seen this address before
248  uint8_t M5_VAR_USED ref_data = 0;
249  auto ref = referenceData.find(req->getPaddr());
250  if (ref == referenceData.end()) {
251  referenceData[req->getPaddr()] = 0;
252  } else {
253  ref_data = ref->second;
254  }
255 
257  "Initiating %sread at addr %x (blk %x) expecting %x\n",
258  do_functional ? "functional " : "", req->getPaddr(),
259  blockAlign(req->getPaddr()), ref_data);
260 
261  pkt = new Packet(req, MemCmd::ReadReq);
262  pkt->dataDynamic(pkt_data);
263  } else {
264  DPRINTF(MemTest, "Initiating %swrite at addr %x (blk %x) value %x\n",
265  do_functional ? "functional " : "", req->getPaddr(),
266  blockAlign(req->getPaddr()), data);
267 
268  pkt = new Packet(req, MemCmd::WriteReq);
269  pkt->dataDynamic(pkt_data);
270  pkt_data[0] = data;
271  }
272 
273  // there is no point in ticking if we are waiting for a retry
274  bool keep_ticking = true;
275  if (do_functional) {
276  pkt->setSuppressFuncError();
277  port.sendFunctional(pkt);
278  completeRequest(pkt, true);
279  } else {
280  keep_ticking = sendPkt(pkt);
281  }
282 
283  if (keep_ticking) {
284  // schedule the next tick
286 
287  // finally shift the timeout for sending of requests forwards
288  // as we have successfully sent a packet
290  } else {
291  DPRINTF(MemTest, "Waiting for retry\n");
292  }
293 
294  // Schedule noResponseEvent now if we are expecting a response
295  if (!noResponseEvent.scheduled() && (outstandingAddrs.size() != 0))
297 }
298 
299 void
301 {
302  panic("%s did not send a request for %d cycles", name(), progressCheck);
303 }
304 
305 void
307 {
308  panic("%s did not see a response for %d cycles", name(), progressCheck);
309 }
310 
311 void
313 {
314  assert(retryPkt);
315  if (port.sendTimingReq(retryPkt)) {
316  DPRINTF(MemTest, "Proceeding after successful retry\n");
317 
318  retryPkt = nullptr;
319  // kick things into action again
322  }
323 }
324 
325 MemTest *
326 MemTestParams::create()
327 {
328  return new MemTest(this);
329 }
Packet::isError
bool isError() const
Definition: packet.hh:583
Packet::setSuppressFuncError
void setSuppressFuncError()
Definition: packet.hh:717
Event::scheduled
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:460
system.hh
data
const char data[]
Definition: circlebuf.test.cc:42
memtest.hh
MemTest::noResponseEvent
EventFunctionWrapper noResponseEvent
Definition: memtest.hh:91
ArmISA::atomic
Bitfield< 23, 20 > atomic
Definition: miscregs_types.hh:96
EventManager::reschedule
void reschedule(Event &event, Tick when, bool always=false)
Definition: eventq.hh:1023
Flags< FlagsType >
MemTest::tick
void tick()
Definition: memtest.cc:202
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:122
MemTest::nextProgressMessage
Tick nextProgressMessage
Definition: memtest.hh:159
random.hh
Packet::isRead
bool isRead() const
Definition: packet.hh:556
MemTest::suppressFuncErrors
const bool suppressFuncErrors
Definition: memtest.hh:167
MemCmd::ReadReq
@ ReadReq
Definition: packet.hh:82
PortID
int16_t PortID
Port index/ID type, and a symbolic name for an invalid port id.
Definition: types.hh:237
MemTest::progressCheck
const Cycles progressCheck
Definition: memtest.hh:158
RequestPtr
std::shared_ptr< Request > RequestPtr
Definition: request.hh:82
X86ISA::base
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
Packet::req
RequestPtr req
A pointer to the original request.
Definition: packet.hh:340
MemTest::MemTestStats::MemTestStats
MemTestStats(Stats::Group *parent)
Definition: memtest.cc:193
EventManager::deschedule
void deschedule(Event &event)
Definition: eventq.hh:1014
Packet::dataDynamic
void dataDynamic(T *p)
Set the data pointer to a value that should have delete [] called on it.
Definition: packet.hh:1145
MemTest::percentUncacheable
const unsigned percentUncacheable
Definition: memtest.hh:126
MemTest::port
CpuPort port
Definition: memtest.hh:116
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:482
MemTest::progressInterval
const unsigned progressInterval
Definition: memtest.hh:157
sim_exit.hh
MemTest::MemTestStats::numWrites
Stats::Scalar numWrites
Definition: memtest.hh:173
ClockedObject
The ClockedObject class extends the SimObject with a clock and accessor functions to relate ticks to ...
Definition: clocked_object.hh:231
MemTest::tickEvent
EventFunctionWrapper tickEvent
Definition: memtest.hh:83
MemTest::percentReads
const unsigned percentReads
Definition: memtest.hh:124
MemTest::referenceData
std::unordered_map< Addr, uint8_t > referenceData
Definition: memtest.hh:136
MemCmd::WriteReq
@ WriteReq
Definition: packet.hh:85
random_mt
Random random_mt
Definition: random.cc:96
stats.hh
EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1005
MemTest::blockAlign
Addr blockAlign(Addr addr) const
Get the block aligned address.
Definition: memtest.hh:148
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:492
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:123
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
ADD_STAT
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition: group.hh:67
MemTest::sendPkt
bool sendPkt(PacketPtr pkt)
Definition: memtest.cc:69
statistics.hh
Port
Ports are used to interface objects to each other.
Definition: port.hh:56
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:174
MemTest::outstandingAddrs
std::set< Addr > outstandingAddrs
Definition: memtest.hh:133
MemTest::size
const unsigned size
Definition: memtest.hh:120
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
MemTest::CpuPort::recvTimingResp
bool recvTimingResp(PacketPtr pkt)
Receive a timing response from the peer.
Definition: memtest.cc:56
Flags::set
void set(Type flags)
Definition: flags.hh:87
MemTest::id
unsigned int id
Definition: memtest.hh:131
Request::UNCACHEABLE
@ UNCACHEABLE
The request is to an uncacheable address.
Definition: request.hh:114
MemTest
The MemTest class tests a cache coherent memory system by generating false sharing and verifying the ...
Definition: memtest.hh:67
MemTest::percentFunctional
const unsigned percentFunctional
Definition: memtest.hh:125
MemTest::stats
MemTest::MemTestStats stats
ProbePoints::Packet
ProbePointArg< PacketInfo > Packet
Packet probe point.
Definition: mem.hh:103
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
MemTest::baseAddr1
Addr baseAddr1
Definition: memtest.hh:153
MemTest::MemTest
MemTest(const Params *p)
Definition: memtest.cc:82
name
const std::string & name()
Definition: trace.cc:50
SimObject::name
virtual const std::string name() const
Definition: sim_object.hh:133
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:197
MemTest::noRequest
void noRequest()
Definition: memtest.cc:300
MemTest::retryPkt
PacketPtr retryPkt
Definition: memtest.hh:118
MemTest::numReads
uint64_t numReads
Definition: memtest.hh:161
MemTest::interval
const Cycles interval
Definition: memtest.hh:122
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
MemTest::baseAddr2
Addr baseAddr2
Definition: memtest.hh:154
MemTest::maxLoads
const uint64_t maxLoads
Definition: memtest.hh:163
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
Stats::Group
Statistics container.
Definition: group.hh:83
MemTest::requestorId
RequestorID requestorId
Request id for all generated traffic.
Definition: memtest.hh:129
ccprintf
void ccprintf(cp::Print &print)
Definition: cprintf.hh:127
Packet::isWrite
bool isWrite() const
Definition: packet.hh:557
Random::random
std::enable_if< std::is_integral< T >::value, T >::type random()
Use the SFINAE idiom to choose an implementation based on whether the type is integral or floating po...
Definition: random.hh:86
Stats
Definition: statistics.cc:61
MemTest::noRequestEvent
EventFunctionWrapper noRequestEvent
Definition: memtest.hh:87
trace.hh
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
MemTest::MemTestStats::numReads
Stats::Scalar numReads
Definition: memtest.hh:172
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:219
MemTest::recvRetry
void recvRetry()
Definition: memtest.cc:312
Packet::getConstPtr
const T * getConstPtr() const
Definition: packet.hh:1166
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:63
MemTest::numWrites
uint64_t numWrites
Definition: memtest.hh:162
MemTest::completeRequest
void completeRequest(PacketPtr pkt, bool functional=false)
Complete a request by checking the response.
Definition: memtest.cc:131
MemTest::noResponse
void noResponse()
Definition: memtest.cc:306
MemTest::uncacheAddr
Addr uncacheAddr
Definition: memtest.hh:155
TESTER_ALLOCATOR
unsigned int TESTER_ALLOCATOR
Definition: memtest.cc:53
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45
ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:153
MemTest::Params
MemTestParams Params
Definition: memtest.hh:72

Generated on Wed Sep 30 2020 14:02:09 for gem5 by doxygen 1.8.17