gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cpu.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011,2013,2017-2018 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) 2006 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  * Authors: Kevin Lim
41  * Geoffrey Blake
42  */
43 
44 #include "cpu/checker/cpu.hh"
45 
46 #include <list>
47 #include <string>
48 
49 #include "arch/generic/tlb.hh"
50 #include "arch/vtophys.hh"
51 #include "cpu/base.hh"
52 #include "cpu/simple_thread.hh"
53 #include "cpu/static_inst.hh"
54 #include "cpu/thread_context.hh"
55 #include "cpu/utils.hh"
56 #include "params/CheckerCPU.hh"
57 #include "sim/full_system.hh"
58 
59 using namespace std;
60 using namespace TheISA;
61 
62 void
64 {
65  masterId = systemPtr->getMasterId(this);
66 }
67 
69  : BaseCPU(p, true), systemPtr(NULL), icachePort(NULL), dcachePort(NULL),
70  tc(NULL), thread(NULL),
71  unverifiedReq(nullptr),
72  unverifiedMemData(nullptr)
73 {
74  curStaticInst = NULL;
75  curMacroStaticInst = NULL;
76 
77  numInst = 0;
78  startNumInst = 0;
79  numLoad = 0;
80  startNumLoad = 0;
81  youngestSN = 0;
82 
83  changedPC = willChangePC = false;
84 
85  exitOnError = p->exitOnError;
86  warnOnlyOnLoadError = p->warnOnlyOnLoadError;
87  itb = p->itb;
88  dtb = p->dtb;
89  workload = p->workload;
90 
91  updateOnError = true;
92 }
93 
95 {
96 }
97 
98 void
100 {
101  const Params *p(dynamic_cast<const Params *>(_params));
102 
103  systemPtr = system;
104 
105  if (FullSystem) {
106  thread = new SimpleThread(this, 0, systemPtr, itb, dtb,
107  p->isa[0], false);
108  } else {
109  thread = new SimpleThread(this, 0, systemPtr,
110  workload.size() ? workload[0] : NULL,
111  itb, dtb, p->isa[0]);
112  }
113 
114  tc = thread->getTC();
115  threadContexts.push_back(tc);
116  thread->kernelStats = NULL;
117  // Thread should never be null after this
118  assert(thread != NULL);
119 }
120 
121 void
123 {
124  icachePort = icache_port;
125 }
126 
127 void
129 {
130  dcachePort = dcache_port;
131 }
132 
133 void
134 CheckerCPU::serialize(ostream &os) const
135 {
136 }
137 
138 void
140 {
141 }
142 
145  Request::Flags flags,
146  const std::vector<bool>& byte_enable,
147  int& frag_size, int& size_left) const
148 {
149  frag_size = std::min(
150  cacheLineSize() - addrBlockOffset(frag_addr, cacheLineSize()),
151  (Addr) size_left);
152  size_left -= frag_size;
153 
154  RequestPtr mem_req;
155 
156  if (!byte_enable.empty()) {
157  // Set up byte-enable mask for the current fragment
158  auto it_start = byte_enable.cbegin() + (size - (frag_size +
159  size_left));
160  auto it_end = byte_enable.cbegin() + (size - size_left);
161  if (isAnyActiveElement(it_start, it_end)) {
162  mem_req = std::make_shared<Request>(0, frag_addr, frag_size,
163  flags, masterId, thread->pcState().instAddr(),
164  tc->contextId());
165  mem_req->setByteEnable(std::vector<bool>(it_start, it_end));
166  }
167  } else {
168  mem_req = std::make_shared<Request>(0, frag_addr, frag_size,
169  flags, masterId, thread->pcState().instAddr(),
170  tc->contextId());
171  }
172 
173  return mem_req;
174 }
175 
176 Fault
177 CheckerCPU::readMem(Addr addr, uint8_t *data, unsigned size,
178  Request::Flags flags,
179  const std::vector<bool>& byte_enable)
180 {
181  assert(byte_enable.empty() || byte_enable.size() == size);
182 
183  Fault fault = NoFault;
184  bool checked_flags = false;
185  bool flags_match = true;
186  Addr pAddr = 0x0;
187 
188  Addr frag_addr = addr;
189  int frag_size = 0;
190  int size_left = size;
191  bool predicate;
192 
193  // Need to account for multiple accesses like the Atomic and TimingSimple
194  while (1) {
195  RequestPtr mem_req = genMemFragmentRequest(frag_addr, size, flags,
196  byte_enable, frag_size,
197  size_left);
198 
199  predicate = (mem_req != nullptr);
200 
201  // translate to physical address
202  if (predicate) {
203  fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Read);
204  }
205 
206  if (predicate && !checked_flags && fault == NoFault && unverifiedReq) {
207  flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(),
208  mem_req->getPaddr(), mem_req->getFlags());
209  pAddr = mem_req->getPaddr();
210  checked_flags = true;
211  }
212 
213  // Now do the access
214  if (predicate && fault == NoFault &&
215  !mem_req->getFlags().isSet(Request::NO_ACCESS)) {
216  PacketPtr pkt = Packet::createRead(mem_req);
217 
218  pkt->dataStatic(data);
219 
220  if (!(mem_req->isUncacheable() || mem_req->isMmappedIpr())) {
221  // Access memory to see if we have the same data
223  } else {
224  // Assume the data is correct if it's an uncached access
225  memcpy(data, unverifiedMemData, frag_size);
226  }
227 
228  delete pkt;
229  }
230 
231  if (fault != NoFault) {
232  if (mem_req->isPrefetch()) {
233  fault = NoFault;
234  }
235  break;
236  }
237 
238  //If we don't need to access a second cache line, stop now.
239  if (size_left == 0)
240  {
241  break;
242  }
243 
244  // Setup for accessing next cache line
245  frag_addr += frag_size;
246  data += frag_size;
247  unverifiedMemData += frag_size;
248  }
249 
250  if (!flags_match) {
251  warn("%lli: Flags do not match CPU:%#x %#x %#x Checker:%#x %#x %#x\n",
252  curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
253  unverifiedReq->getFlags(), frag_addr, pAddr, flags);
254  handleError();
255  }
256 
257  return fault;
258 }
259 
260 Fault
261 CheckerCPU::writeMem(uint8_t *data, unsigned size,
262  Addr addr, Request::Flags flags, uint64_t *res,
263  const std::vector<bool>& byte_enable)
264 {
265  assert(byte_enable.empty() || byte_enable.size() == size);
266 
267  Fault fault = NoFault;
268  bool checked_flags = false;
269  bool flags_match = true;
270  Addr pAddr = 0x0;
271  static uint8_t zero_data[64] = {};
272 
273  Addr frag_addr = addr;
274  int frag_size = 0;
275  int size_left = size;
276  bool predicate;
277 
278  // Need to account for a multiple access like Atomic and Timing CPUs
279  while (1) {
280  RequestPtr mem_req = genMemFragmentRequest(frag_addr, size, flags,
281  byte_enable, frag_size,
282  size_left);
283 
284  predicate = (mem_req != nullptr);
285 
286  if (predicate) {
287  fault = dtb->translateFunctional(mem_req, tc, BaseTLB::Write);
288  }
289 
290  if (predicate && !checked_flags && fault == NoFault && unverifiedReq) {
291  flags_match = checkFlags(unverifiedReq, mem_req->getVaddr(),
292  mem_req->getPaddr(), mem_req->getFlags());
293  pAddr = mem_req->getPaddr();
294  checked_flags = true;
295  }
296 
297  /*
298  * We don't actually check memory for the store because there
299  * is no guarantee it has left the lsq yet, and therefore we
300  * can't verify the memory on stores without lsq snooping
301  * enabled. This is left as future work for the Checker: LSQ snooping
302  * and memory validation after stores have committed.
303  */
304  bool was_prefetch = mem_req->isPrefetch();
305 
306  //If we don't need to access a second cache line, stop now.
307  if (fault != NoFault || size_left == 0)
308  {
309  if (fault != NoFault && was_prefetch) {
310  fault = NoFault;
311  }
312  break;
313  }
314 
315  frag_addr += frag_size;
316  }
317 
318  if (!flags_match) {
319  warn("%lli: Flags do not match CPU:%#x %#x Checker:%#x %#x %#x\n",
320  curTick(), unverifiedReq->getVaddr(), unverifiedReq->getPaddr(),
321  unverifiedReq->getFlags(), frag_addr, pAddr, flags);
322  handleError();
323  }
324 
325  // Assume the result was the same as the one passed in. This checker
326  // doesn't check if the SC should succeed or fail, it just checks the
327  // value.
328  if (unverifiedReq && res && unverifiedReq->extraDataValid())
329  *res = unverifiedReq->getExtraData();
330 
331  // Entire purpose here is to make sure we are getting the
332  // same data to send to the mem system as the CPU did.
333  // Cannot check this is actually what went to memory because
334  // there stores can be in ld/st queue or coherent operations
335  // overwriting values.
336  bool extraData = false;
337  if (unverifiedReq) {
338  extraData = unverifiedReq->extraDataValid() ?
339  unverifiedReq->getExtraData() : true;
340  }
341 
342  // If the request is to ZERO a cache block, there is no data to check
343  // against, but it's all zero. We need something to compare to, so use a
344  // const set of zeros.
345  if (flags & Request::STORE_NO_DATA) {
346  assert(!data);
347  assert(sizeof(zero_data) <= size);
348  data = zero_data;
349  }
350 
352  memcmp(data, unverifiedMemData, size) && extraData) {
353  warn("%lli: Store value does not match value sent to memory! "
354  "data: %#x inst_data: %#x", curTick(), data,
356  handleError();
357  }
358 
359  return fault;
360 }
361 
362 Addr
364 {
365  return vtophys(tc, addr);
366 }
367 
371 bool
372 CheckerCPU::checkFlags(const RequestPtr &unverified_req, Addr vAddr,
373  Addr pAddr, int flags)
374 {
375  Addr unverifiedVAddr = unverified_req->getVaddr();
376  Addr unverifiedPAddr = unverified_req->getPaddr();
377  int unverifiedFlags = unverified_req->getFlags();
378 
379  if (unverifiedVAddr != vAddr ||
380  unverifiedPAddr != pAddr ||
381  unverifiedFlags != flags) {
382  return false;
383  }
384 
385  return true;
386 }
387 
388 void
390 {
391  warn("%lli: Checker PC:%s",
392  curTick(), thread->pcState());
393  panic("Checker found an error!");
394 }
A MasterPort is a specialisation of a BaseMasterPort, which implements the default protocol for the t...
Definition: port.hh:75
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
RequestPtr unverifiedReq
Definition: cpu.hh:602
Addr addrBlockOffset(Addr addr, Addr block_size)
Calculates the offset of a given address wrt aligned fixed-size blocks.
Definition: utils.hh:52
BaseCPUParams Params
Definition: base.hh:310
decltype(nullptr) constexpr NoFault
Definition: types.hh:245
bool changedPC
Definition: cpu.hh:605
std::shared_ptr< Request > RequestPtr
Definition: request.hh:83
ip6_addr_t addr
Definition: inet.hh:335
bool checkFlags(const RequestPtr &unverified_req, Addr vAddr, Addr pAddr, int flags)
Checks if the flags set by the Checker and Checkee match.
Definition: cpu.cc:372
bool FullSystem
The FullSystem variable can be used to determine the current mode of simulation.
Definition: root.cc:136
TheISA::PCState pcState() const override
The SimpleThread object provides a combination of the ThreadState object and the ThreadContext interf...
System * systemPtr
Definition: cpu.hh:130
Definition: system.hh:77
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:586
System * system
Definition: base.hh:386
Definition: cprintf.cc:42
bool willChangePC
Definition: cpu.hh:606
StaticInstPtr curMacroStaticInst
Definition: cpu.hh:147
void setDcachePort(MasterPort *dcache_port)
Definition: cpu.cc:128
Bitfield< 17 > os
Definition: misc.hh:805
bool updateOnError
Definition: cpu.hh:609
void dataStatic(T *p)
Set the data pointer to the following value that should not be freed.
Definition: packet.hh:1040
std::vector< ThreadContext * > threadContexts
Definition: base.hh:267
Tick curTick()
The current simulated tick.
Definition: core.hh:47
ThreadContext * tc
Definition: cpu.hh:135
MasterID masterId
id attached to all issued requests
Definition: cpu.hh:94
RequestPtr genMemFragmentRequest(Addr frag_addr, int size, Request::Flags flags, const std::vector< bool > &byte_enable, int &frag_size, int &size_left) const
Helper function used to generate the request for a single fragment of a memory access.
Definition: cpu.cc:144
Kernel::Statistics * kernelStats
uint8_t * unverifiedMemData
Definition: cpu.hh:603
bool exitOnError
Definition: cpu.hh:608
static const FlagsType STORE_NO_DATA
Definition: request.hh:200
Counter startNumInst
Definition: cpu.hh:151
Fault writeMem(uint8_t *data, unsigned size, Addr addr, Request::Flags flags, uint64_t *res, const std::vector< bool > &byte_enable=std::vector< bool >()) override
Definition: cpu.cc:261
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
ThreadContext * getTC()
Returns the pointer to this SimpleThread&#39;s ThreadContext.
static PacketPtr createRead(const RequestPtr &req)
Constructor-like methods that return Packets based on Request objects.
Definition: packet.hh:913
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
SimpleThread * thread
Definition: cpu.hh:158
Addr dbg_vtophys(Addr addr)
Definition: cpu.cc:363
Fault readMem(Addr addr, uint8_t *data, unsigned size, Request::Flags flags, const std::vector< bool > &byte_enable=std::vector< bool >()) override
Definition: cpu.cc:177
void serialize(CheckpointOut &cp) const override
Serialize this object to the given output stream.
Definition: cpu.cc:134
The request should not cause a memory access.
Definition: request.hh:138
unsigned int cacheLineSize() const
Get the cache line size of the system.
Definition: base.hh:391
Counter startNumLoad
Definition: cpu.hh:175
void setIcachePort(MasterPort *icache_port)
Definition: cpu.cc:122
Counter numInst
Definition: cpu.hh:150
Addr vtophys(Addr vaddr)
Definition: vtophys.cc:75
MasterPort * icachePort
Definition: cpu.hh:132
std::vector< Process * > workload
Definition: cpu.hh:128
void setSystem(System *system)
Definition: cpu.cc:99
virtual ~CheckerCPU()
Definition: cpu.cc:94
bool warnOnlyOnLoadError
Definition: cpu.hh:610
const SimObjectParams * _params
Cached copy of the object parameters.
Definition: sim_object.hh:110
virtual ContextID contextId() const =0
bool isAnyActiveElement(const std::vector< bool >::const_iterator &it_start, const std::vector< bool >::const_iterator &it_end)
Test if there is any active element in an enablement range.
Definition: utils.hh:88
Counter numLoad
Definition: cpu.hh:174
BaseTLB * itb
Definition: cpu.hh:137
void sendFunctional(PacketPtr pkt) const
Send a functional request packet, where the data is instantly updated everywhere in the memory system...
Definition: port.hh:439
#define warn(...)
Definition: logging.hh:212
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: cpu.cc:63
CheckerCPU(Params *p)
Definition: cpu.cc:68
Bitfield< 0 > p
StaticInstPtr curStaticInst
Definition: cpu.hh:146
const char data[]
std::shared_ptr< FaultBase > Fault
Definition: types.hh:240
BaseTLB * dtb
Definition: cpu.hh:138
InstSeqNum youngestSN
Definition: cpu.hh:612
void unserialize(CheckpointIn &cp) override
Reconstruct the state of this object from a checkpoint.
Definition: cpu.cc:139
MasterPort * dcachePort
Definition: cpu.hh:133
void dumpAndExit()
Definition: cpu.cc:389
void handleError()
Definition: cpu.hh:587
virtual Fault translateFunctional(const RequestPtr &req, ThreadContext *tc, Mode mode)
Definition: tlb.hh:98

Generated on Fri Feb 28 2020 16:26:56 for gem5 by doxygen 1.8.13