9d6061ad8a056e4ad3c4794ce073ebbb7a91f40f
[gem5.git] / src / cpu / checker / cpu.hh
1 /*
2 * Copyright (c) 2011, 2016-2017 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 class BaseTLB;
66 template <class>
67 class BaseDynInst;
68 class ThreadContext;
69 class 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 */
87 class CheckerCPU : public BaseCPU, public ExecContext
88 {
89 protected:
90 typedef TheISA::MachInst MachInst;
91 using VecRegContainer = TheISA::VecRegContainer;
92
93 /** id attached to all issued requests */
94 MasterID masterId;
95 public:
96 void init() override;
97
98 typedef CheckerCPUParams Params;
99 CheckerCPU(Params *p);
100 virtual ~CheckerCPU();
101
102 void setSystem(System *system);
103
104 void setIcachePort(MasterPort *icache_port);
105
106 void setDcachePort(MasterPort *dcache_port);
107
108 MasterPort &getDataPort() override
109 {
110 // the checker does not have ports on its own so return the
111 // data port of the actual CPU core
112 assert(dcachePort);
113 return *dcachePort;
114 }
115
116 MasterPort &getInstPort() 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(icachePort);
121 return *icachePort;
122 }
123
124 protected:
125
126 std::vector<Process*> workload;
127
128 System *systemPtr;
129
130 MasterPort *icachePort;
131 MasterPort *dcachePort;
132
133 ThreadContext *tc;
134
135 BaseTLB *itb;
136 BaseTLB *dtb;
137
138 Addr dbg_vtophys(Addr addr);
139
140 // ISAs like ARM can have multiple destination registers to check,
141 // keep them all in a std::queue
142 std::queue<InstResult> result;
143
144 StaticInstPtr curStaticInst;
145 StaticInstPtr curMacroStaticInst;
146
147 // number of simulated instructions
148 Counter numInst;
149 Counter startNumInst;
150
151 std::queue<int> miscRegIdxs;
152
153 public:
154
155 // Primary thread being run.
156 SimpleThread *thread;
157
158 BaseTLB* getITBPtr() { return itb; }
159 BaseTLB* getDTBPtr() { return dtb; }
160
161 virtual Counter totalInsts() const override
162 {
163 return 0;
164 }
165
166 virtual Counter totalOps() const override
167 {
168 return 0;
169 }
170
171 // number of simulated loads
172 Counter numLoad;
173 Counter startNumLoad;
174
175 void serialize(CheckpointOut &cp) const override;
176 void unserialize(CheckpointIn &cp) override;
177
178 // The register accessor methods provide the index of the
179 // instruction's operand (e.g., 0 or 1), not the architectural
180 // register index, to simplify the implementation of register
181 // renaming. We find the architectural register index by indexing
182 // into the instruction's own operand index table. Note that a
183 // raw pointer to the StaticInst is provided instead of a
184 // ref-counted StaticInstPtr to redice overhead. This is fine as
185 // long as these methods don't copy the pointer into any long-term
186 // storage (which is pretty hard to imagine they would have reason
187 // to do).
188
189 RegVal
190 readIntRegOperand(const StaticInst *si, int idx) override
191 {
192 const RegId& reg = si->srcRegIdx(idx);
193 assert(reg.isIntReg());
194 return thread->readIntReg(reg.index());
195 }
196
197 RegVal
198 readFloatRegOperandBits(const StaticInst *si, int idx) override
199 {
200 const RegId& reg = si->srcRegIdx(idx);
201 assert(reg.isFloatReg());
202 return thread->readFloatRegBits(reg.index());
203 }
204
205 /**
206 * Read source vector register operand.
207 */
208 const VecRegContainer &
209 readVecRegOperand(const StaticInst *si, int idx) const override
210 {
211 const RegId& reg = si->srcRegIdx(idx);
212 assert(reg.isVecReg());
213 return thread->readVecReg(reg);
214 }
215
216 /**
217 * Read destination vector register operand for modification.
218 */
219 VecRegContainer &
220 getWritableVecRegOperand(const StaticInst *si, int idx) override
221 {
222 const RegId& reg = si->destRegIdx(idx);
223 assert(reg.isVecReg());
224 return thread->getWritableVecReg(reg);
225 }
226
227 /** Vector Register Lane Interfaces. */
228 /** @{ */
229 /** Reads source vector 8bit operand. */
230 virtual ConstVecLane8
231 readVec8BitLaneOperand(const StaticInst *si, int idx) const override
232 {
233 const RegId& reg = si->destRegIdx(idx);
234 assert(reg.isVecReg());
235 return thread->readVec8BitLaneReg(reg);
236 }
237
238 /** Reads source vector 16bit operand. */
239 virtual ConstVecLane16
240 readVec16BitLaneOperand(const StaticInst *si, int idx) const override
241 {
242 const RegId& reg = si->destRegIdx(idx);
243 assert(reg.isVecReg());
244 return thread->readVec16BitLaneReg(reg);
245 }
246
247 /** Reads source vector 32bit operand. */
248 virtual ConstVecLane32
249 readVec32BitLaneOperand(const StaticInst *si, int idx) const override
250 {
251 const RegId& reg = si->destRegIdx(idx);
252 assert(reg.isVecReg());
253 return thread->readVec32BitLaneReg(reg);
254 }
255
256 /** Reads source vector 64bit operand. */
257 virtual ConstVecLane64
258 readVec64BitLaneOperand(const StaticInst *si, int idx) const override
259 {
260 const RegId& reg = si->destRegIdx(idx);
261 assert(reg.isVecReg());
262 return thread->readVec64BitLaneReg(reg);
263 }
264
265 /** Write a lane of the destination vector operand. */
266 template <typename LD>
267 void
268 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
269 {
270 const RegId& reg = si->destRegIdx(idx);
271 assert(reg.isVecReg());
272 return thread->setVecLane(reg, val);
273 }
274 virtual void
275 setVecLaneOperand(const StaticInst *si, int idx,
276 const LaneData<LaneSize::Byte>& val) override
277 {
278 setVecLaneOperandT(si, idx, val);
279 }
280 virtual void
281 setVecLaneOperand(const StaticInst *si, int idx,
282 const LaneData<LaneSize::TwoByte>& val) override
283 {
284 setVecLaneOperandT(si, idx, val);
285 }
286 virtual void
287 setVecLaneOperand(const StaticInst *si, int idx,
288 const LaneData<LaneSize::FourByte>& val) override
289 {
290 setVecLaneOperandT(si, idx, val);
291 }
292 virtual void
293 setVecLaneOperand(const StaticInst *si, int idx,
294 const LaneData<LaneSize::EightByte>& val) override
295 {
296 setVecLaneOperandT(si, idx, val);
297 }
298 /** @} */
299
300 VecElem
301 readVecElemOperand(const StaticInst *si, int idx) const override
302 {
303 const RegId& reg = si->srcRegIdx(idx);
304 return thread->readVecElem(reg);
305 }
306
307 const VecPredRegContainer&
308 readVecPredRegOperand(const StaticInst *si, int idx) const override
309 {
310 const RegId& reg = si->srcRegIdx(idx);
311 assert(reg.isVecPredReg());
312 return thread->readVecPredReg(reg);
313 }
314
315 VecPredRegContainer&
316 getWritableVecPredRegOperand(const StaticInst *si, int idx) override
317 {
318 const RegId& reg = si->destRegIdx(idx);
319 assert(reg.isVecPredReg());
320 return thread->getWritableVecPredReg(reg);
321 }
322
323 CCReg
324 readCCRegOperand(const StaticInst *si, int idx) override
325 {
326 const RegId& reg = si->srcRegIdx(idx);
327 assert(reg.isCCReg());
328 return thread->readCCReg(reg.index());
329 }
330
331 template<typename T>
332 void
333 setScalarResult(T&& t)
334 {
335 result.push(InstResult(std::forward<T>(t),
336 InstResult::ResultType::Scalar));
337 }
338
339 template<typename T>
340 void
341 setVecResult(T&& t)
342 {
343 result.push(InstResult(std::forward<T>(t),
344 InstResult::ResultType::VecReg));
345 }
346
347 template<typename T>
348 void
349 setVecElemResult(T&& t)
350 {
351 result.push(InstResult(std::forward<T>(t),
352 InstResult::ResultType::VecElem));
353 }
354
355 template<typename T>
356 void
357 setVecPredResult(T&& t)
358 {
359 result.push(InstResult(std::forward<T>(t),
360 InstResult::ResultType::VecPredReg));
361 }
362
363 void
364 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
365 {
366 const RegId& reg = si->destRegIdx(idx);
367 assert(reg.isIntReg());
368 thread->setIntReg(reg.index(), val);
369 setScalarResult(val);
370 }
371
372 void
373 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
374 {
375 const RegId& reg = si->destRegIdx(idx);
376 assert(reg.isFloatReg());
377 thread->setFloatRegBits(reg.index(), val);
378 setScalarResult(val);
379 }
380
381 void
382 setCCRegOperand(const StaticInst *si, int idx, CCReg val) override
383 {
384 const RegId& reg = si->destRegIdx(idx);
385 assert(reg.isCCReg());
386 thread->setCCReg(reg.index(), val);
387 setScalarResult((uint64_t)val);
388 }
389
390 void
391 setVecRegOperand(const StaticInst *si, int idx,
392 const VecRegContainer& val) override
393 {
394 const RegId& reg = si->destRegIdx(idx);
395 assert(reg.isVecReg());
396 thread->setVecReg(reg, val);
397 setVecResult(val);
398 }
399
400 void
401 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 void setVecPredRegOperand(const StaticInst *si, int idx,
411 const VecPredRegContainer& val) override
412 {
413 const RegId& reg = si->destRegIdx(idx);
414 assert(reg.isVecPredReg());
415 thread->setVecPredReg(reg, val);
416 setVecPredResult(val);
417 }
418
419 bool readPredicate() const override { return thread->readPredicate(); }
420
421 void
422 setPredicate(bool val) override
423 {
424 thread->setPredicate(val);
425 }
426
427 TheISA::PCState pcState() const override { return thread->pcState(); }
428 void
429 pcState(const TheISA::PCState &val) override
430 {
431 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
432 val, thread->pcState());
433 thread->pcState(val);
434 }
435 Addr instAddr() { return thread->instAddr(); }
436 Addr nextInstAddr() { return thread->nextInstAddr(); }
437 MicroPC microPC() { return thread->microPC(); }
438 //////////////////////////////////////////
439
440 RegVal
441 readMiscRegNoEffect(int misc_reg) const
442 {
443 return thread->readMiscRegNoEffect(misc_reg);
444 }
445
446 RegVal
447 readMiscReg(int misc_reg) override
448 {
449 return thread->readMiscReg(misc_reg);
450 }
451
452 void
453 setMiscRegNoEffect(int misc_reg, RegVal val)
454 {
455 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n",
456 misc_reg);
457 miscRegIdxs.push(misc_reg);
458 return thread->setMiscRegNoEffect(misc_reg, val);
459 }
460
461 void
462 setMiscReg(int misc_reg, RegVal val) override
463 {
464 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n",
465 misc_reg);
466 miscRegIdxs.push(misc_reg);
467 return thread->setMiscReg(misc_reg, val);
468 }
469
470 RegVal
471 readMiscRegOperand(const StaticInst *si, int idx) override
472 {
473 const RegId& reg = si->srcRegIdx(idx);
474 assert(reg.isMiscReg());
475 return thread->readMiscReg(reg.index());
476 }
477
478 void
479 setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
480 {
481 const RegId& reg = si->destRegIdx(idx);
482 assert(reg.isMiscReg());
483 return this->setMiscReg(reg.index(), val);
484 }
485
486 #if THE_ISA == MIPS_ISA
487 RegVal
488 readRegOtherThread(const RegId &misc_reg, ThreadID tid) override
489 {
490 panic("MIPS MT not defined for CheckerCPU.\n");
491 return 0;
492 }
493
494 void
495 setRegOtherThread(const RegId& misc_reg, RegVal val, ThreadID tid) override
496 {
497 panic("MIPS MT not defined for CheckerCPU.\n");
498 }
499 #endif
500
501 /////////////////////////////////////////
502
503 void
504 recordPCChange(const TheISA::PCState &val)
505 {
506 changedPC = true;
507 newPCState = val;
508 }
509
510 void
511 demapPage(Addr vaddr, uint64_t asn) override
512 {
513 this->itb->demapPage(vaddr, asn);
514 this->dtb->demapPage(vaddr, asn);
515 }
516
517 // monitor/mwait funtions
518 void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); }
519 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
520 void mwaitAtomic(ThreadContext *tc) override
521 { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
522 AddressMonitor *getAddrMonitor() override
523 { return BaseCPU::getCpuAddrMonitor(0); }
524
525 void
526 demapInstPage(Addr vaddr, uint64_t asn)
527 {
528 this->itb->demapPage(vaddr, asn);
529 }
530
531 void
532 demapDataPage(Addr vaddr, uint64_t asn)
533 {
534 this->dtb->demapPage(vaddr, asn);
535 }
536
537 Fault readMem(Addr addr, uint8_t *data, unsigned size,
538 Request::Flags flags) override;
539 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
540 Request::Flags flags, uint64_t *res) override;
541
542 unsigned int
543 readStCondFailures() const override {
544 return thread->readStCondFailures();
545 }
546
547 void setStCondFailures(unsigned int sc_failures) override {}
548 /////////////////////////////////////////////////////
549
550 Fault hwrei() override { return thread->hwrei(); }
551 bool simPalCheck(int palFunc) override
552 { return thread->simPalCheck(palFunc); }
553 void wakeup(ThreadID tid) override { }
554 // Assume that the normal CPU's call to syscall was successful.
555 // The checker's state would have already been updated by the syscall.
556 void syscall(int64_t callnum, Fault *fault) override { }
557
558 void
559 handleError()
560 {
561 if (exitOnError)
562 dumpAndExit();
563 }
564
565 bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
566 Addr pAddr, int flags);
567
568 void dumpAndExit();
569
570 ThreadContext *tcBase() override { return tc; }
571 SimpleThread *threadBase() { return thread; }
572
573 InstResult unverifiedResult;
574 RequestPtr unverifiedReq;
575 uint8_t *unverifiedMemData;
576
577 bool changedPC;
578 bool willChangePC;
579 TheISA::PCState newPCState;
580 bool exitOnError;
581 bool updateOnError;
582 bool warnOnlyOnLoadError;
583
584 InstSeqNum youngestSN;
585 };
586
587 /**
588 * Templated Checker class. This Checker class is templated on the
589 * DynInstPtr of the instruction type that will be verified. Proper
590 * template instantiations of the Checker must be placed at the bottom
591 * of checker/cpu.cc.
592 */
593 template <class Impl>
594 class Checker : public CheckerCPU
595 {
596 private:
597 typedef typename Impl::DynInstPtr DynInstPtr;
598
599 public:
600 Checker(Params *p)
601 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
602 { }
603
604 void switchOut();
605 void takeOverFrom(BaseCPU *oldCPU);
606
607 void advancePC(const Fault &fault);
608
609 void verify(const DynInstPtr &inst);
610
611 void validateInst(const DynInstPtr &inst);
612 void validateExecution(const DynInstPtr &inst);
613 void validateState();
614
615 void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
616 int start_idx);
617 void handlePendingInt();
618
619 private:
620 void handleError(const DynInstPtr &inst)
621 {
622 if (exitOnError) {
623 dumpAndExit(inst);
624 } else if (updateOnError) {
625 updateThisCycle = true;
626 }
627 }
628
629 void dumpAndExit(const DynInstPtr &inst);
630
631 bool updateThisCycle;
632
633 DynInstPtr unverifiedInst;
634
635 std::list<DynInstPtr> instList;
636 typedef typename std::list<DynInstPtr>::iterator InstListIt;
637 void dumpInsts();
638 };
639
640 #endif // __CPU_CHECKER_CPU_HH__