cpu.hh (12109:f29e9c5418aa) cpu.hh (12406:86bde4a026b5)
1/*
2 * Copyright (c) 2011, 2016 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 */
43
44#ifndef __CPU_CHECKER_CPU_HH__
45#define __CPU_CHECKER_CPU_HH__
46
47#include <list>
48#include <map>
49#include <queue>
50
51#include "arch/types.hh"
52#include "base/statistics.hh"
53#include "cpu/base.hh"
54#include "cpu/base_dyn_inst.hh"
55#include "cpu/exec_context.hh"
56#include "cpu/inst_res.hh"
57#include "cpu/pc_event.hh"
58#include "cpu/simple_thread.hh"
59#include "cpu/static_inst.hh"
60#include "debug/Checker.hh"
61#include "mem/request.hh"
62#include "params/CheckerCPU.hh"
63#include "sim/eventq.hh"
64
1/*
2 * Copyright (c) 2011, 2016 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
4 * All rights reserved
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Copyright (c) 2006 The Regents of The University of Michigan
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Kevin Lim
42 */
43
44#ifndef __CPU_CHECKER_CPU_HH__
45#define __CPU_CHECKER_CPU_HH__
46
47#include <list>
48#include <map>
49#include <queue>
50
51#include "arch/types.hh"
52#include "base/statistics.hh"
53#include "cpu/base.hh"
54#include "cpu/base_dyn_inst.hh"
55#include "cpu/exec_context.hh"
56#include "cpu/inst_res.hh"
57#include "cpu/pc_event.hh"
58#include "cpu/simple_thread.hh"
59#include "cpu/static_inst.hh"
60#include "debug/Checker.hh"
61#include "mem/request.hh"
62#include "params/CheckerCPU.hh"
63#include "sim/eventq.hh"
64
65// forward declarations
66namespace TheISA
67{
68 class TLB;
69}
70
65class BaseTLB;
71template <class>
72class BaseDynInst;
73class ThreadContext;
74class Request;
75
76/**
77 * CheckerCPU class. Dynamically verifies instructions as they are
78 * completed by making sure that the instruction and its results match
79 * the independent execution of the benchmark inside the checker. The
80 * checker verifies instructions in order, regardless of the order in
81 * which instructions complete. There are certain results that can
82 * not be verified, specifically the result of a store conditional or
83 * the values of uncached accesses. In these cases, and with
84 * instructions marked as "IsUnverifiable", the checker assumes that
85 * the value from the main CPU's execution is correct and simply
86 * copies that value. It provides a CheckerThreadContext (see
87 * checker/thread_context.hh) that provides hooks for updating the
88 * Checker's state through any ThreadContext accesses. This allows the
89 * checker to be able to correctly verify instructions, even with
90 * external accesses to the ThreadContext that change state.
91 */
92class CheckerCPU : public BaseCPU, public ExecContext
93{
94 protected:
95 typedef TheISA::MachInst MachInst;
96 typedef TheISA::FloatReg FloatReg;
97 typedef TheISA::FloatRegBits FloatRegBits;
98 typedef TheISA::MiscReg MiscReg;
99 using VecRegContainer = TheISA::VecRegContainer;
100
101 /** id attached to all issued requests */
102 MasterID masterId;
103 public:
104 void init() override;
105
106 typedef CheckerCPUParams Params;
107 CheckerCPU(Params *p);
108 virtual ~CheckerCPU();
109
110 void setSystem(System *system);
111
112 void setIcachePort(MasterPort *icache_port);
113
114 void setDcachePort(MasterPort *dcache_port);
115
116 MasterPort &getDataPort() override
117 {
118 // the checker does not have ports on its own so return the
119 // data port of the actual CPU core
120 assert(dcachePort);
121 return *dcachePort;
122 }
123
124 MasterPort &getInstPort() override
125 {
126 // the checker does not have ports on its own so return the
127 // data port of the actual CPU core
128 assert(icachePort);
129 return *icachePort;
130 }
131
132 protected:
133
134 std::vector<Process*> workload;
135
136 System *systemPtr;
137
138 MasterPort *icachePort;
139 MasterPort *dcachePort;
140
141 ThreadContext *tc;
142
66template <class>
67class BaseDynInst;
68class ThreadContext;
69class Request;
70
71/**
72 * CheckerCPU class. Dynamically verifies instructions as they are
73 * completed by making sure that the instruction and its results match
74 * the independent execution of the benchmark inside the checker. The
75 * checker verifies instructions in order, regardless of the order in
76 * which instructions complete. There are certain results that can
77 * not be verified, specifically the result of a store conditional or
78 * the values of uncached accesses. In these cases, and with
79 * instructions marked as "IsUnverifiable", the checker assumes that
80 * the value from the main CPU's execution is correct and simply
81 * copies that value. It provides a CheckerThreadContext (see
82 * checker/thread_context.hh) that provides hooks for updating the
83 * Checker's state through any ThreadContext accesses. This allows the
84 * checker to be able to correctly verify instructions, even with
85 * external accesses to the ThreadContext that change state.
86 */
87class CheckerCPU : public BaseCPU, public ExecContext
88{
89 protected:
90 typedef TheISA::MachInst MachInst;
91 typedef TheISA::FloatReg FloatReg;
92 typedef TheISA::FloatRegBits FloatRegBits;
93 typedef TheISA::MiscReg MiscReg;
94 using VecRegContainer = TheISA::VecRegContainer;
95
96 /** id attached to all issued requests */
97 MasterID masterId;
98 public:
99 void init() override;
100
101 typedef CheckerCPUParams Params;
102 CheckerCPU(Params *p);
103 virtual ~CheckerCPU();
104
105 void setSystem(System *system);
106
107 void setIcachePort(MasterPort *icache_port);
108
109 void setDcachePort(MasterPort *dcache_port);
110
111 MasterPort &getDataPort() override
112 {
113 // the checker does not have ports on its own so return the
114 // data port of the actual CPU core
115 assert(dcachePort);
116 return *dcachePort;
117 }
118
119 MasterPort &getInstPort() override
120 {
121 // the checker does not have ports on its own so return the
122 // data port of the actual CPU core
123 assert(icachePort);
124 return *icachePort;
125 }
126
127 protected:
128
129 std::vector<Process*> workload;
130
131 System *systemPtr;
132
133 MasterPort *icachePort;
134 MasterPort *dcachePort;
135
136 ThreadContext *tc;
137
143 TheISA::TLB *itb;
144 TheISA::TLB *dtb;
138 BaseTLB *itb;
139 BaseTLB *dtb;
145
146 Addr dbg_vtophys(Addr addr);
147
148 // ISAs like ARM can have multiple destination registers to check,
149 // keep them all in a std::queue
150 std::queue<InstResult> result;
151
152 // Pointer to the one memory request.
153 RequestPtr memReq;
154
155 StaticInstPtr curStaticInst;
156 StaticInstPtr curMacroStaticInst;
157
158 // number of simulated instructions
159 Counter numInst;
160 Counter startNumInst;
161
162 std::queue<int> miscRegIdxs;
163
164 public:
165
166 // Primary thread being run.
167 SimpleThread *thread;
168
140
141 Addr dbg_vtophys(Addr addr);
142
143 // ISAs like ARM can have multiple destination registers to check,
144 // keep them all in a std::queue
145 std::queue<InstResult> result;
146
147 // Pointer to the one memory request.
148 RequestPtr memReq;
149
150 StaticInstPtr curStaticInst;
151 StaticInstPtr curMacroStaticInst;
152
153 // number of simulated instructions
154 Counter numInst;
155 Counter startNumInst;
156
157 std::queue<int> miscRegIdxs;
158
159 public:
160
161 // Primary thread being run.
162 SimpleThread *thread;
163
169 TheISA::TLB* getITBPtr() { return itb; }
170 TheISA::TLB* getDTBPtr() { return dtb; }
164 BaseTLB* getITBPtr() { return itb; }
165 BaseTLB* getDTBPtr() { return dtb; }
171
172 virtual Counter totalInsts() const override
173 {
174 return 0;
175 }
176
177 virtual Counter totalOps() const override
178 {
179 return 0;
180 }
181
182 // number of simulated loads
183 Counter numLoad;
184 Counter startNumLoad;
185
186 void serialize(CheckpointOut &cp) const override;
187 void unserialize(CheckpointIn &cp) override;
188
189 // These functions are only used in CPU models that split
190 // effective address computation from the actual memory access.
191 void setEA(Addr EA) override
192 { panic("CheckerCPU::setEA() not implemented\n"); }
193 Addr getEA() const override
194 { panic("CheckerCPU::getEA() not implemented\n"); }
195
196 // The register accessor methods provide the index of the
197 // instruction's operand (e.g., 0 or 1), not the architectural
198 // register index, to simplify the implementation of register
199 // renaming. We find the architectural register index by indexing
200 // into the instruction's own operand index table. Note that a
201 // raw pointer to the StaticInst is provided instead of a
202 // ref-counted StaticInstPtr to redice overhead. This is fine as
203 // long as these methods don't copy the pointer into any long-term
204 // storage (which is pretty hard to imagine they would have reason
205 // to do).
206
207 IntReg readIntRegOperand(const StaticInst *si, int idx) override
208 {
209 const RegId& reg = si->srcRegIdx(idx);
210 assert(reg.isIntReg());
211 return thread->readIntReg(reg.index());
212 }
213
214 FloatReg readFloatRegOperand(const StaticInst *si, int idx) override
215 {
216 const RegId& reg = si->srcRegIdx(idx);
217 assert(reg.isFloatReg());
218 return thread->readFloatReg(reg.index());
219 }
220
221 FloatRegBits readFloatRegOperandBits(const StaticInst *si,
222 int idx) override
223 {
224 const RegId& reg = si->srcRegIdx(idx);
225 assert(reg.isFloatReg());
226 return thread->readFloatRegBits(reg.index());
227 }
228
229 /**
230 * Read source vector register operand.
231 */
232 const VecRegContainer& readVecRegOperand(const StaticInst *si,
233 int idx) const override
234 {
235 const RegId& reg = si->srcRegIdx(idx);
236 assert(reg.isVecReg());
237 return thread->readVecReg(reg);
238 }
239
240 /**
241 * Read destination vector register operand for modification.
242 */
243 VecRegContainer& getWritableVecRegOperand(const StaticInst *si,
244 int idx) override
245 {
246 const RegId& reg = si->destRegIdx(idx);
247 assert(reg.isVecReg());
248 return thread->getWritableVecReg(reg);
249 }
250
251 /** Vector Register Lane Interfaces. */
252 /** @{ */
253 /** Reads source vector 8bit operand. */
254 virtual ConstVecLane8
255 readVec8BitLaneOperand(const StaticInst *si, int idx) const
256 override
257 {
258 const RegId& reg = si->destRegIdx(idx);
259 assert(reg.isVecReg());
260 return thread->readVec8BitLaneReg(reg);
261 }
262
263 /** Reads source vector 16bit operand. */
264 virtual ConstVecLane16
265 readVec16BitLaneOperand(const StaticInst *si, int idx) const
266 override
267 {
268 const RegId& reg = si->destRegIdx(idx);
269 assert(reg.isVecReg());
270 return thread->readVec16BitLaneReg(reg);
271 }
272
273 /** Reads source vector 32bit operand. */
274 virtual ConstVecLane32
275 readVec32BitLaneOperand(const StaticInst *si, int idx) const
276 override
277 {
278 const RegId& reg = si->destRegIdx(idx);
279 assert(reg.isVecReg());
280 return thread->readVec32BitLaneReg(reg);
281 }
282
283 /** Reads source vector 64bit operand. */
284 virtual ConstVecLane64
285 readVec64BitLaneOperand(const StaticInst *si, int idx) const
286 override
287 {
288 const RegId& reg = si->destRegIdx(idx);
289 assert(reg.isVecReg());
290 return thread->readVec64BitLaneReg(reg);
291 }
292
293 /** Write a lane of the destination vector operand. */
294 template <typename LD>
295 void
296 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
297 {
298 const RegId& reg = si->destRegIdx(idx);
299 assert(reg.isVecReg());
300 return thread->setVecLane(reg, val);
301 }
302 virtual void
303 setVecLaneOperand(const StaticInst *si, int idx,
304 const LaneData<LaneSize::Byte>& val) override
305 {
306 setVecLaneOperandT(si, idx, val);
307 }
308 virtual void
309 setVecLaneOperand(const StaticInst *si, int idx,
310 const LaneData<LaneSize::TwoByte>& val) override
311 {
312 setVecLaneOperandT(si, idx, val);
313 }
314 virtual void
315 setVecLaneOperand(const StaticInst *si, int idx,
316 const LaneData<LaneSize::FourByte>& val) override
317 {
318 setVecLaneOperandT(si, idx, val);
319 }
320 virtual void
321 setVecLaneOperand(const StaticInst *si, int idx,
322 const LaneData<LaneSize::EightByte>& val) override
323 {
324 setVecLaneOperandT(si, idx, val);
325 }
326 /** @} */
327
328 VecElem readVecElemOperand(const StaticInst *si, int idx) const override
329 {
330 const RegId& reg = si->srcRegIdx(idx);
331 return thread->readVecElem(reg);
332 }
333
334 CCReg readCCRegOperand(const StaticInst *si, int idx) override
335 {
336 const RegId& reg = si->srcRegIdx(idx);
337 assert(reg.isCCReg());
338 return thread->readCCReg(reg.index());
339 }
340
341 template<typename T>
342 void setScalarResult(T&& t)
343 {
344 result.push(InstResult(std::forward<T>(t),
345 InstResult::ResultType::Scalar));
346 }
347
348 template<typename T>
349 void setVecResult(T&& t)
350 {
351 result.push(InstResult(std::forward<T>(t),
352 InstResult::ResultType::VecReg));
353 }
354
355 template<typename T>
356 void setVecElemResult(T&& t)
357 {
358 result.push(InstResult(std::forward<T>(t),
359 InstResult::ResultType::VecElem));
360 }
361
362 void setIntRegOperand(const StaticInst *si, int idx,
363 IntReg val) override
364 {
365 const RegId& reg = si->destRegIdx(idx);
366 assert(reg.isIntReg());
367 thread->setIntReg(reg.index(), val);
368 setScalarResult(val);
369 }
370
371 void setFloatRegOperand(const StaticInst *si, int idx,
372 FloatReg val) override
373 {
374 const RegId& reg = si->destRegIdx(idx);
375 assert(reg.isFloatReg());
376 thread->setFloatReg(reg.index(), val);
377 setScalarResult(val);
378 }
379
380 void setFloatRegOperandBits(const StaticInst *si, int idx,
381 FloatRegBits val) override
382 {
383 const RegId& reg = si->destRegIdx(idx);
384 assert(reg.isFloatReg());
385 thread->setFloatRegBits(reg.index(), val);
386 setScalarResult(val);
387 }
388
389 void setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
390 {
391 const RegId& reg = si->destRegIdx(idx);
392 assert(reg.isCCReg());
393 thread->setCCReg(reg.index(), val);
394 setScalarResult((uint64_t)val);
395 }
396
397 void setVecRegOperand(const StaticInst *si, int idx,
398 const VecRegContainer& val) override
399 {
400 const RegId& reg = si->destRegIdx(idx);
401 assert(reg.isVecReg());
402 thread->setVecReg(reg, val);
403 setVecResult(val);
404 }
405
406 void setVecElemOperand(const StaticInst *si, int idx,
407 const VecElem val) override
408 {
409 const RegId& reg = si->destRegIdx(idx);
410 assert(reg.isVecElem());
411 thread->setVecElem(reg, val);
412 setVecElemResult(val);
413 }
414
415 bool readPredicate() override { return thread->readPredicate(); }
416 void setPredicate(bool val) override
417 {
418 thread->setPredicate(val);
419 }
420
421 TheISA::PCState pcState() const override { return thread->pcState(); }
422 void pcState(const TheISA::PCState &val) override
423 {
424 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
425 val, thread->pcState());
426 thread->pcState(val);
427 }
428 Addr instAddr() { return thread->instAddr(); }
429 Addr nextInstAddr() { return thread->nextInstAddr(); }
430 MicroPC microPC() { return thread->microPC(); }
431 //////////////////////////////////////////
432
433 MiscReg readMiscRegNoEffect(int misc_reg) const
434 {
435 return thread->readMiscRegNoEffect(misc_reg);
436 }
437
438 MiscReg readMiscReg(int misc_reg) override
439 {
440 return thread->readMiscReg(misc_reg);
441 }
442
443 void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
444 {
445 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", misc_reg);
446 miscRegIdxs.push(misc_reg);
447 return thread->setMiscRegNoEffect(misc_reg, val);
448 }
449
450 void setMiscReg(int misc_reg, const MiscReg &val) override
451 {
452 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", misc_reg);
453 miscRegIdxs.push(misc_reg);
454 return thread->setMiscReg(misc_reg, val);
455 }
456
457 MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
458 {
459 const RegId& reg = si->srcRegIdx(idx);
460 assert(reg.isMiscReg());
461 return thread->readMiscReg(reg.index());
462 }
463
464 void setMiscRegOperand(const StaticInst *si, int idx,
465 const MiscReg &val) override
466 {
467 const RegId& reg = si->destRegIdx(idx);
468 assert(reg.isMiscReg());
469 return this->setMiscReg(reg.index(), val);
470 }
471
472#if THE_ISA == MIPS_ISA
473 MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid) override
474 {
475 panic("MIPS MT not defined for CheckerCPU.\n");
476 return 0;
477 }
478
479 void setRegOtherThread(const RegId& misc_reg, MiscReg val,
480 ThreadID tid) override
481 {
482 panic("MIPS MT not defined for CheckerCPU.\n");
483 }
484#endif
485
486 /////////////////////////////////////////
487
488 void recordPCChange(const TheISA::PCState &val)
489 {
490 changedPC = true;
491 newPCState = val;
492 }
493
494 void demapPage(Addr vaddr, uint64_t asn) override
495 {
496 this->itb->demapPage(vaddr, asn);
497 this->dtb->demapPage(vaddr, asn);
498 }
499
500 // monitor/mwait funtions
501 void armMonitor(Addr address) override
502 { BaseCPU::armMonitor(0, address); }
503 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
504 void mwaitAtomic(ThreadContext *tc) override
505 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
506 AddressMonitor *getAddrMonitor() override
507 { return BaseCPU::getCpuAddrMonitor(0); }
508
509 void demapInstPage(Addr vaddr, uint64_t asn)
510 {
511 this->itb->demapPage(vaddr, asn);
512 }
513
514 void demapDataPage(Addr vaddr, uint64_t asn)
515 {
516 this->dtb->demapPage(vaddr, asn);
517 }
518
519 Fault readMem(Addr addr, uint8_t *data, unsigned size,
520 Request::Flags flags) override;
521 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
522 Request::Flags flags, uint64_t *res) override;
523
524 unsigned int readStCondFailures() const override {
525 return thread->readStCondFailures();
526 }
527
528 void setStCondFailures(unsigned int sc_failures) override
529 {}
530 /////////////////////////////////////////////////////
531
532 Fault hwrei() override { return thread->hwrei(); }
533 bool simPalCheck(int palFunc) override
534 { return thread->simPalCheck(palFunc); }
535 void wakeup(ThreadID tid) override { }
536 // Assume that the normal CPU's call to syscall was successful.
537 // The checker's state would have already been updated by the syscall.
538 void syscall(int64_t callnum, Fault *fault) override { }
539
540 void handleError()
541 {
542 if (exitOnError)
543 dumpAndExit();
544 }
545
546 bool checkFlags(Request *unverified_req, Addr vAddr,
547 Addr pAddr, int flags);
548
549 void dumpAndExit();
550
551 ThreadContext *tcBase() override { return tc; }
552 SimpleThread *threadBase() { return thread; }
553
554 InstResult unverifiedResult;
555 Request *unverifiedReq;
556 uint8_t *unverifiedMemData;
557
558 bool changedPC;
559 bool willChangePC;
560 TheISA::PCState newPCState;
561 bool exitOnError;
562 bool updateOnError;
563 bool warnOnlyOnLoadError;
564
565 InstSeqNum youngestSN;
566};
567
568/**
569 * Templated Checker class. This Checker class is templated on the
570 * DynInstPtr of the instruction type that will be verified. Proper
571 * template instantiations of the Checker must be placed at the bottom
572 * of checker/cpu.cc.
573 */
574template <class Impl>
575class Checker : public CheckerCPU
576{
577 private:
578 typedef typename Impl::DynInstPtr DynInstPtr;
579
580 public:
581 Checker(Params *p)
582 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
583 { }
584
585 void switchOut();
586 void takeOverFrom(BaseCPU *oldCPU);
587
588 void advancePC(const Fault &fault);
589
590 void verify(DynInstPtr &inst);
591
592 void validateInst(DynInstPtr &inst);
593 void validateExecution(DynInstPtr &inst);
594 void validateState();
595
596 void copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
597 int start_idx);
598 void handlePendingInt();
599
600 private:
601 void handleError(DynInstPtr &inst)
602 {
603 if (exitOnError) {
604 dumpAndExit(inst);
605 } else if (updateOnError) {
606 updateThisCycle = true;
607 }
608 }
609
610 void dumpAndExit(DynInstPtr &inst);
611
612 bool updateThisCycle;
613
614 DynInstPtr unverifiedInst;
615
616 std::list<DynInstPtr> instList;
617 typedef typename std::list<DynInstPtr>::iterator InstListIt;
618 void dumpInsts();
619};
620
621#endif // __CPU_CHECKER_CPU_HH__
166
167 virtual Counter totalInsts() const override
168 {
169 return 0;
170 }
171
172 virtual Counter totalOps() const override
173 {
174 return 0;
175 }
176
177 // number of simulated loads
178 Counter numLoad;
179 Counter startNumLoad;
180
181 void serialize(CheckpointOut &cp) const override;
182 void unserialize(CheckpointIn &cp) override;
183
184 // These functions are only used in CPU models that split
185 // effective address computation from the actual memory access.
186 void setEA(Addr EA) override
187 { panic("CheckerCPU::setEA() not implemented\n"); }
188 Addr getEA() const override
189 { panic("CheckerCPU::getEA() not implemented\n"); }
190
191 // The register accessor methods provide the index of the
192 // instruction's operand (e.g., 0 or 1), not the architectural
193 // register index, to simplify the implementation of register
194 // renaming. We find the architectural register index by indexing
195 // into the instruction's own operand index table. Note that a
196 // raw pointer to the StaticInst is provided instead of a
197 // ref-counted StaticInstPtr to redice overhead. This is fine as
198 // long as these methods don't copy the pointer into any long-term
199 // storage (which is pretty hard to imagine they would have reason
200 // to do).
201
202 IntReg readIntRegOperand(const StaticInst *si, int idx) override
203 {
204 const RegId& reg = si->srcRegIdx(idx);
205 assert(reg.isIntReg());
206 return thread->readIntReg(reg.index());
207 }
208
209 FloatReg readFloatRegOperand(const StaticInst *si, int idx) override
210 {
211 const RegId& reg = si->srcRegIdx(idx);
212 assert(reg.isFloatReg());
213 return thread->readFloatReg(reg.index());
214 }
215
216 FloatRegBits readFloatRegOperandBits(const StaticInst *si,
217 int idx) override
218 {
219 const RegId& reg = si->srcRegIdx(idx);
220 assert(reg.isFloatReg());
221 return thread->readFloatRegBits(reg.index());
222 }
223
224 /**
225 * Read source vector register operand.
226 */
227 const VecRegContainer& readVecRegOperand(const StaticInst *si,
228 int idx) const override
229 {
230 const RegId& reg = si->srcRegIdx(idx);
231 assert(reg.isVecReg());
232 return thread->readVecReg(reg);
233 }
234
235 /**
236 * Read destination vector register operand for modification.
237 */
238 VecRegContainer& getWritableVecRegOperand(const StaticInst *si,
239 int idx) override
240 {
241 const RegId& reg = si->destRegIdx(idx);
242 assert(reg.isVecReg());
243 return thread->getWritableVecReg(reg);
244 }
245
246 /** Vector Register Lane Interfaces. */
247 /** @{ */
248 /** Reads source vector 8bit operand. */
249 virtual ConstVecLane8
250 readVec8BitLaneOperand(const StaticInst *si, int idx) const
251 override
252 {
253 const RegId& reg = si->destRegIdx(idx);
254 assert(reg.isVecReg());
255 return thread->readVec8BitLaneReg(reg);
256 }
257
258 /** Reads source vector 16bit operand. */
259 virtual ConstVecLane16
260 readVec16BitLaneOperand(const StaticInst *si, int idx) const
261 override
262 {
263 const RegId& reg = si->destRegIdx(idx);
264 assert(reg.isVecReg());
265 return thread->readVec16BitLaneReg(reg);
266 }
267
268 /** Reads source vector 32bit operand. */
269 virtual ConstVecLane32
270 readVec32BitLaneOperand(const StaticInst *si, int idx) const
271 override
272 {
273 const RegId& reg = si->destRegIdx(idx);
274 assert(reg.isVecReg());
275 return thread->readVec32BitLaneReg(reg);
276 }
277
278 /** Reads source vector 64bit operand. */
279 virtual ConstVecLane64
280 readVec64BitLaneOperand(const StaticInst *si, int idx) const
281 override
282 {
283 const RegId& reg = si->destRegIdx(idx);
284 assert(reg.isVecReg());
285 return thread->readVec64BitLaneReg(reg);
286 }
287
288 /** Write a lane of the destination vector operand. */
289 template <typename LD>
290 void
291 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
292 {
293 const RegId& reg = si->destRegIdx(idx);
294 assert(reg.isVecReg());
295 return thread->setVecLane(reg, val);
296 }
297 virtual void
298 setVecLaneOperand(const StaticInst *si, int idx,
299 const LaneData<LaneSize::Byte>& val) override
300 {
301 setVecLaneOperandT(si, idx, val);
302 }
303 virtual void
304 setVecLaneOperand(const StaticInst *si, int idx,
305 const LaneData<LaneSize::TwoByte>& val) override
306 {
307 setVecLaneOperandT(si, idx, val);
308 }
309 virtual void
310 setVecLaneOperand(const StaticInst *si, int idx,
311 const LaneData<LaneSize::FourByte>& val) override
312 {
313 setVecLaneOperandT(si, idx, val);
314 }
315 virtual void
316 setVecLaneOperand(const StaticInst *si, int idx,
317 const LaneData<LaneSize::EightByte>& val) override
318 {
319 setVecLaneOperandT(si, idx, val);
320 }
321 /** @} */
322
323 VecElem readVecElemOperand(const StaticInst *si, int idx) const override
324 {
325 const RegId& reg = si->srcRegIdx(idx);
326 return thread->readVecElem(reg);
327 }
328
329 CCReg readCCRegOperand(const StaticInst *si, int idx) override
330 {
331 const RegId& reg = si->srcRegIdx(idx);
332 assert(reg.isCCReg());
333 return thread->readCCReg(reg.index());
334 }
335
336 template<typename T>
337 void setScalarResult(T&& t)
338 {
339 result.push(InstResult(std::forward<T>(t),
340 InstResult::ResultType::Scalar));
341 }
342
343 template<typename T>
344 void setVecResult(T&& t)
345 {
346 result.push(InstResult(std::forward<T>(t),
347 InstResult::ResultType::VecReg));
348 }
349
350 template<typename T>
351 void setVecElemResult(T&& t)
352 {
353 result.push(InstResult(std::forward<T>(t),
354 InstResult::ResultType::VecElem));
355 }
356
357 void setIntRegOperand(const StaticInst *si, int idx,
358 IntReg val) override
359 {
360 const RegId& reg = si->destRegIdx(idx);
361 assert(reg.isIntReg());
362 thread->setIntReg(reg.index(), val);
363 setScalarResult(val);
364 }
365
366 void setFloatRegOperand(const StaticInst *si, int idx,
367 FloatReg val) override
368 {
369 const RegId& reg = si->destRegIdx(idx);
370 assert(reg.isFloatReg());
371 thread->setFloatReg(reg.index(), val);
372 setScalarResult(val);
373 }
374
375 void setFloatRegOperandBits(const StaticInst *si, int idx,
376 FloatRegBits val) override
377 {
378 const RegId& reg = si->destRegIdx(idx);
379 assert(reg.isFloatReg());
380 thread->setFloatRegBits(reg.index(), val);
381 setScalarResult(val);
382 }
383
384 void setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
385 {
386 const RegId& reg = si->destRegIdx(idx);
387 assert(reg.isCCReg());
388 thread->setCCReg(reg.index(), val);
389 setScalarResult((uint64_t)val);
390 }
391
392 void setVecRegOperand(const StaticInst *si, int idx,
393 const VecRegContainer& val) override
394 {
395 const RegId& reg = si->destRegIdx(idx);
396 assert(reg.isVecReg());
397 thread->setVecReg(reg, val);
398 setVecResult(val);
399 }
400
401 void setVecElemOperand(const StaticInst *si, int idx,
402 const VecElem val) override
403 {
404 const RegId& reg = si->destRegIdx(idx);
405 assert(reg.isVecElem());
406 thread->setVecElem(reg, val);
407 setVecElemResult(val);
408 }
409
410 bool readPredicate() override { return thread->readPredicate(); }
411 void setPredicate(bool val) override
412 {
413 thread->setPredicate(val);
414 }
415
416 TheISA::PCState pcState() const override { return thread->pcState(); }
417 void pcState(const TheISA::PCState &val) override
418 {
419 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
420 val, thread->pcState());
421 thread->pcState(val);
422 }
423 Addr instAddr() { return thread->instAddr(); }
424 Addr nextInstAddr() { return thread->nextInstAddr(); }
425 MicroPC microPC() { return thread->microPC(); }
426 //////////////////////////////////////////
427
428 MiscReg readMiscRegNoEffect(int misc_reg) const
429 {
430 return thread->readMiscRegNoEffect(misc_reg);
431 }
432
433 MiscReg readMiscReg(int misc_reg) override
434 {
435 return thread->readMiscReg(misc_reg);
436 }
437
438 void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
439 {
440 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n", misc_reg);
441 miscRegIdxs.push(misc_reg);
442 return thread->setMiscRegNoEffect(misc_reg, val);
443 }
444
445 void setMiscReg(int misc_reg, const MiscReg &val) override
446 {
447 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n", misc_reg);
448 miscRegIdxs.push(misc_reg);
449 return thread->setMiscReg(misc_reg, val);
450 }
451
452 MiscReg readMiscRegOperand(const StaticInst *si, int idx) override
453 {
454 const RegId& reg = si->srcRegIdx(idx);
455 assert(reg.isMiscReg());
456 return thread->readMiscReg(reg.index());
457 }
458
459 void setMiscRegOperand(const StaticInst *si, int idx,
460 const MiscReg &val) override
461 {
462 const RegId& reg = si->destRegIdx(idx);
463 assert(reg.isMiscReg());
464 return this->setMiscReg(reg.index(), val);
465 }
466
467#if THE_ISA == MIPS_ISA
468 MiscReg readRegOtherThread(const RegId& misc_reg, ThreadID tid) override
469 {
470 panic("MIPS MT not defined for CheckerCPU.\n");
471 return 0;
472 }
473
474 void setRegOtherThread(const RegId& misc_reg, MiscReg val,
475 ThreadID tid) override
476 {
477 panic("MIPS MT not defined for CheckerCPU.\n");
478 }
479#endif
480
481 /////////////////////////////////////////
482
483 void recordPCChange(const TheISA::PCState &val)
484 {
485 changedPC = true;
486 newPCState = val;
487 }
488
489 void demapPage(Addr vaddr, uint64_t asn) override
490 {
491 this->itb->demapPage(vaddr, asn);
492 this->dtb->demapPage(vaddr, asn);
493 }
494
495 // monitor/mwait funtions
496 void armMonitor(Addr address) override
497 { BaseCPU::armMonitor(0, address); }
498 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
499 void mwaitAtomic(ThreadContext *tc) override
500 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
501 AddressMonitor *getAddrMonitor() override
502 { return BaseCPU::getCpuAddrMonitor(0); }
503
504 void demapInstPage(Addr vaddr, uint64_t asn)
505 {
506 this->itb->demapPage(vaddr, asn);
507 }
508
509 void demapDataPage(Addr vaddr, uint64_t asn)
510 {
511 this->dtb->demapPage(vaddr, asn);
512 }
513
514 Fault readMem(Addr addr, uint8_t *data, unsigned size,
515 Request::Flags flags) override;
516 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
517 Request::Flags flags, uint64_t *res) override;
518
519 unsigned int readStCondFailures() const override {
520 return thread->readStCondFailures();
521 }
522
523 void setStCondFailures(unsigned int sc_failures) override
524 {}
525 /////////////////////////////////////////////////////
526
527 Fault hwrei() override { return thread->hwrei(); }
528 bool simPalCheck(int palFunc) override
529 { return thread->simPalCheck(palFunc); }
530 void wakeup(ThreadID tid) override { }
531 // Assume that the normal CPU's call to syscall was successful.
532 // The checker's state would have already been updated by the syscall.
533 void syscall(int64_t callnum, Fault *fault) override { }
534
535 void handleError()
536 {
537 if (exitOnError)
538 dumpAndExit();
539 }
540
541 bool checkFlags(Request *unverified_req, Addr vAddr,
542 Addr pAddr, int flags);
543
544 void dumpAndExit();
545
546 ThreadContext *tcBase() override { return tc; }
547 SimpleThread *threadBase() { return thread; }
548
549 InstResult unverifiedResult;
550 Request *unverifiedReq;
551 uint8_t *unverifiedMemData;
552
553 bool changedPC;
554 bool willChangePC;
555 TheISA::PCState newPCState;
556 bool exitOnError;
557 bool updateOnError;
558 bool warnOnlyOnLoadError;
559
560 InstSeqNum youngestSN;
561};
562
563/**
564 * Templated Checker class. This Checker class is templated on the
565 * DynInstPtr of the instruction type that will be verified. Proper
566 * template instantiations of the Checker must be placed at the bottom
567 * of checker/cpu.cc.
568 */
569template <class Impl>
570class Checker : public CheckerCPU
571{
572 private:
573 typedef typename Impl::DynInstPtr DynInstPtr;
574
575 public:
576 Checker(Params *p)
577 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
578 { }
579
580 void switchOut();
581 void takeOverFrom(BaseCPU *oldCPU);
582
583 void advancePC(const Fault &fault);
584
585 void verify(DynInstPtr &inst);
586
587 void validateInst(DynInstPtr &inst);
588 void validateExecution(DynInstPtr &inst);
589 void validateState();
590
591 void copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
592 int start_idx);
593 void handlePendingInt();
594
595 private:
596 void handleError(DynInstPtr &inst)
597 {
598 if (exitOnError) {
599 dumpAndExit(inst);
600 } else if (updateOnError) {
601 updateThisCycle = true;
602 }
603 }
604
605 void dumpAndExit(DynInstPtr &inst);
606
607 bool updateThisCycle;
608
609 DynInstPtr unverifiedInst;
610
611 std::list<DynInstPtr> instList;
612 typedef typename std::list<DynInstPtr>::iterator InstListIt;
613 void dumpInsts();
614};
615
616#endif // __CPU_CHECKER_CPU_HH__