2 * Copyright (c) 2011, 2016-2018, 2020 ARM Limited
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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.
15 * Copyright (c) 2006 The Regents of The University of Michigan
16 * All rights reserved.
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.
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.
42 #ifndef __CPU_CHECKER_CPU_HH__
43 #define __CPU_CHECKER_CPU_HH__
49 #include "arch/types.hh"
50 #include "base/statistics.hh"
51 #include "cpu/base.hh"
52 #include "cpu/base_dyn_inst.hh"
53 #include "cpu/exec_context.hh"
54 #include "cpu/inst_res.hh"
55 #include "cpu/pc_event.hh"
56 #include "cpu/simple_thread.hh"
57 #include "cpu/static_inst.hh"
58 #include "debug/Checker.hh"
59 #include "mem/request.hh"
60 #include "params/CheckerCPU.hh"
61 #include "sim/eventq.hh"
70 * CheckerCPU class. Dynamically verifies instructions as they are
71 * completed by making sure that the instruction and its results match
72 * the independent execution of the benchmark inside the checker. The
73 * checker verifies instructions in order, regardless of the order in
74 * which instructions complete. There are certain results that can
75 * not be verified, specifically the result of a store conditional or
76 * the values of uncached accesses. In these cases, and with
77 * instructions marked as "IsUnverifiable", the checker assumes that
78 * the value from the main CPU's execution is correct and simply
79 * copies that value. It provides a CheckerThreadContext (see
80 * checker/thread_context.hh) that provides hooks for updating the
81 * Checker's state through any ThreadContext accesses. This allows the
82 * checker to be able to correctly verify instructions, even with
83 * external accesses to the ThreadContext that change state.
85 class CheckerCPU : public BaseCPU, public ExecContext
88 typedef TheISA::MachInst MachInst;
89 using VecRegContainer = TheISA::VecRegContainer;
91 /** id attached to all issued requests */
92 RequestorID requestorId;
96 typedef CheckerCPUParams Params;
97 CheckerCPU(const Params &p);
98 virtual ~CheckerCPU();
100 void setSystem(System *system);
102 void setIcachePort(RequestPort *icache_port);
104 void setDcachePort(RequestPort *dcache_port);
107 getDataPort() override
109 // the checker does not have ports on its own so return the
110 // data port of the actual CPU core
116 getInstPort() override
118 // the checker does not have ports on its own so return the
119 // data port of the actual CPU core
126 std::vector<Process*> workload;
130 RequestPort *icachePort;
131 RequestPort *dcachePort;
137 // ISAs like ARM can have multiple destination registers to check,
138 // keep them all in a std::queue
139 std::queue<InstResult> result;
141 StaticInstPtr curStaticInst;
142 StaticInstPtr curMacroStaticInst;
144 // number of simulated instructions
146 Counter startNumInst;
148 std::queue<int> miscRegIdxs;
152 // Primary thread being run.
153 SimpleThread *thread;
155 BaseTLB* getITBPtr() { return mmu->itb; }
156 BaseTLB* getDTBPtr() { return mmu->dtb; }
158 BaseMMU* getMMUPtr() { return mmu; }
160 virtual Counter totalInsts() const override
165 virtual Counter totalOps() const override
170 // number of simulated loads
172 Counter startNumLoad;
174 void serialize(CheckpointOut &cp) const override;
175 void unserialize(CheckpointIn &cp) override;
177 // The register accessor methods provide the index of the
178 // instruction's operand (e.g., 0 or 1), not the architectural
179 // register index, to simplify the implementation of register
180 // renaming. We find the architectural register index by indexing
181 // into the instruction's own operand index table. Note that a
182 // raw pointer to the StaticInst is provided instead of a
183 // ref-counted StaticInstPtr to redice overhead. This is fine as
184 // long as these methods don't copy the pointer into any long-term
185 // storage (which is pretty hard to imagine they would have reason
189 readIntRegOperand(const StaticInst *si, int idx) override
191 const RegId& reg = si->srcRegIdx(idx);
192 assert(reg.isIntReg());
193 return thread->readIntReg(reg.index());
197 readFloatRegOperandBits(const StaticInst *si, int idx) override
199 const RegId& reg = si->srcRegIdx(idx);
200 assert(reg.isFloatReg());
201 return thread->readFloatReg(reg.index());
205 * Read source vector register operand.
207 const VecRegContainer &
208 readVecRegOperand(const StaticInst *si, int idx) const override
210 const RegId& reg = si->srcRegIdx(idx);
211 assert(reg.isVecReg());
212 return thread->readVecReg(reg);
216 * Read destination vector register operand for modification.
219 getWritableVecRegOperand(const StaticInst *si, int idx) override
221 const RegId& reg = si->destRegIdx(idx);
222 assert(reg.isVecReg());
223 return thread->getWritableVecReg(reg);
226 /** Vector Register Lane Interfaces. */
228 /** Reads source vector 8bit operand. */
229 virtual ConstVecLane8
230 readVec8BitLaneOperand(const StaticInst *si, int idx) const override
232 const RegId& reg = si->destRegIdx(idx);
233 assert(reg.isVecReg());
234 return thread->readVec8BitLaneReg(reg);
237 /** Reads source vector 16bit operand. */
238 virtual ConstVecLane16
239 readVec16BitLaneOperand(const StaticInst *si, int idx) const override
241 const RegId& reg = si->destRegIdx(idx);
242 assert(reg.isVecReg());
243 return thread->readVec16BitLaneReg(reg);
246 /** Reads source vector 32bit operand. */
247 virtual ConstVecLane32
248 readVec32BitLaneOperand(const StaticInst *si, int idx) const override
250 const RegId& reg = si->destRegIdx(idx);
251 assert(reg.isVecReg());
252 return thread->readVec32BitLaneReg(reg);
255 /** Reads source vector 64bit operand. */
256 virtual ConstVecLane64
257 readVec64BitLaneOperand(const StaticInst *si, int idx) const override
259 const RegId& reg = si->destRegIdx(idx);
260 assert(reg.isVecReg());
261 return thread->readVec64BitLaneReg(reg);
264 /** Write a lane of the destination vector operand. */
265 template <typename LD>
267 setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
269 const RegId& reg = si->destRegIdx(idx);
270 assert(reg.isVecReg());
271 return thread->setVecLane(reg, val);
274 setVecLaneOperand(const StaticInst *si, int idx,
275 const LaneData<LaneSize::Byte>& val) override
277 setVecLaneOperandT(si, idx, val);
280 setVecLaneOperand(const StaticInst *si, int idx,
281 const LaneData<LaneSize::TwoByte>& val) override
283 setVecLaneOperandT(si, idx, val);
286 setVecLaneOperand(const StaticInst *si, int idx,
287 const LaneData<LaneSize::FourByte>& val) override
289 setVecLaneOperandT(si, idx, val);
292 setVecLaneOperand(const StaticInst *si, int idx,
293 const LaneData<LaneSize::EightByte>& val) override
295 setVecLaneOperandT(si, idx, val);
300 readVecElemOperand(const StaticInst *si, int idx) const override
302 const RegId& reg = si->srcRegIdx(idx);
303 return thread->readVecElem(reg);
306 const VecPredRegContainer&
307 readVecPredRegOperand(const StaticInst *si, int idx) const override
309 const RegId& reg = si->srcRegIdx(idx);
310 assert(reg.isVecPredReg());
311 return thread->readVecPredReg(reg);
315 getWritableVecPredRegOperand(const StaticInst *si, int idx) override
317 const RegId& reg = si->destRegIdx(idx);
318 assert(reg.isVecPredReg());
319 return thread->getWritableVecPredReg(reg);
323 readCCRegOperand(const StaticInst *si, int idx) override
325 const RegId& reg = si->srcRegIdx(idx);
326 assert(reg.isCCReg());
327 return thread->readCCReg(reg.index());
332 setScalarResult(T&& t)
334 result.push(InstResult(std::forward<T>(t),
335 InstResult::ResultType::Scalar));
342 result.push(InstResult(std::forward<T>(t),
343 InstResult::ResultType::VecReg));
348 setVecElemResult(T&& t)
350 result.push(InstResult(std::forward<T>(t),
351 InstResult::ResultType::VecElem));
356 setVecPredResult(T&& t)
358 result.push(InstResult(std::forward<T>(t),
359 InstResult::ResultType::VecPredReg));
363 setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
365 const RegId& reg = si->destRegIdx(idx);
366 assert(reg.isIntReg());
367 thread->setIntReg(reg.index(), val);
368 setScalarResult(val);
372 setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
374 const RegId& reg = si->destRegIdx(idx);
375 assert(reg.isFloatReg());
376 thread->setFloatReg(reg.index(), val);
377 setScalarResult(val);
381 setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
383 const RegId& reg = si->destRegIdx(idx);
384 assert(reg.isCCReg());
385 thread->setCCReg(reg.index(), val);
386 setScalarResult((uint64_t)val);
390 setVecRegOperand(const StaticInst *si, int idx,
391 const VecRegContainer& val) override
393 const RegId& reg = si->destRegIdx(idx);
394 assert(reg.isVecReg());
395 thread->setVecReg(reg, val);
400 setVecElemOperand(const StaticInst *si, int idx,
401 const VecElem val) override
403 const RegId& reg = si->destRegIdx(idx);
404 assert(reg.isVecElem());
405 thread->setVecElem(reg, val);
406 setVecElemResult(val);
409 void setVecPredRegOperand(const StaticInst *si, int idx,
410 const VecPredRegContainer& val) override
412 const RegId& reg = si->destRegIdx(idx);
413 assert(reg.isVecPredReg());
414 thread->setVecPredReg(reg, val);
415 setVecPredResult(val);
418 bool readPredicate() const override { return thread->readPredicate(); }
421 setPredicate(bool val) override
423 thread->setPredicate(val);
427 readMemAccPredicate() const override
429 return thread->readMemAccPredicate();
433 setMemAccPredicate(bool val) override
435 thread->setMemAccPredicate(val);
439 getHtmTransactionUid() const override
441 panic("not yet supported!");
446 newHtmTransactionUid() const override
448 panic("not yet supported!");
453 initiateHtmCmd(Request::Flags flags) override
455 panic("not yet supported!");
460 inHtmTransactionalState() const override
462 panic("not yet supported!");
467 getHtmTransactionalDepth() const override
469 panic("not yet supported!");
473 TheISA::PCState pcState() const override { return thread->pcState(); }
475 pcState(const TheISA::PCState &val) override
477 DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
478 val, thread->pcState());
479 thread->pcState(val);
481 Addr instAddr() { return thread->instAddr(); }
482 Addr nextInstAddr() { return thread->nextInstAddr(); }
483 MicroPC microPC() { return thread->microPC(); }
484 //////////////////////////////////////////
487 readMiscRegNoEffect(int misc_reg) const
489 return thread->readMiscRegNoEffect(misc_reg);
493 readMiscReg(int misc_reg) override
495 return thread->readMiscReg(misc_reg);
499 setMiscRegNoEffect(int misc_reg, RegVal val)
501 DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n",
503 miscRegIdxs.push(misc_reg);
504 return thread->setMiscRegNoEffect(misc_reg, val);
508 setMiscReg(int misc_reg, RegVal val) override
510 DPRINTF(Checker, "Setting misc reg %d with effect to check later\n",
512 miscRegIdxs.push(misc_reg);
513 return thread->setMiscReg(misc_reg, val);
517 readMiscRegOperand(const StaticInst *si, int idx) override
519 const RegId& reg = si->srcRegIdx(idx);
520 assert(reg.isMiscReg());
521 return thread->readMiscReg(reg.index());
525 setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
527 const RegId& reg = si->destRegIdx(idx);
528 assert(reg.isMiscReg());
529 return this->setMiscReg(reg.index(), val);
532 /////////////////////////////////////////
535 recordPCChange(const TheISA::PCState &val)
542 demapPage(Addr vaddr, uint64_t asn) override
544 mmu->demapPage(vaddr, asn);
547 // monitor/mwait funtions
548 void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); }
549 bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
552 mwaitAtomic(ThreadContext *tc) override
554 return BaseCPU::mwaitAtomic(0, tc, thread->mmu);
557 AddressMonitor *getAddrMonitor() override
558 { return BaseCPU::getCpuAddrMonitor(0); }
561 demapInstPage(Addr vaddr, uint64_t asn)
563 mmu->itb->demapPage(vaddr, asn);
567 demapDataPage(Addr vaddr, uint64_t asn)
569 mmu->dtb->demapPage(vaddr, asn);
573 * Helper function used to generate the request for a single fragment of a
576 * Takes care of setting up the appropriate byte-enable mask for the
577 * fragment, given the mask for the entire memory access.
579 * @param frag_addr Start address of the fragment.
580 * @param size Total size of the memory access in bytes.
581 * @param flags Request flags.
582 * @param byte_enable Byte-enable mask for the entire memory access.
583 * @param[out] frag_size Fragment size.
584 * @param[in,out] size_left Size left to be processed in the memory access.
585 * @return Pointer to the allocated Request, nullptr if the byte-enable
586 * mask is all-false for the fragment.
588 RequestPtr genMemFragmentRequest(Addr frag_addr, int size,
589 Request::Flags flags,
590 const std::vector<bool>& byte_enable,
591 int& frag_size, int& size_left) const;
593 Fault readMem(Addr addr, uint8_t *data, unsigned size,
594 Request::Flags flags,
595 const std::vector<bool>& byte_enable)
598 Fault writeMem(uint8_t *data, unsigned size, Addr addr,
599 Request::Flags flags, uint64_t *res,
600 const std::vector<bool>& byte_enable)
603 Fault amoMem(Addr addr, uint8_t* data, unsigned size,
604 Request::Flags flags, AtomicOpFunctorPtr amo_op) override
606 panic("AMO is not supported yet in CPU checker\n");
610 readStCondFailures() const override {
611 return thread->readStCondFailures();
614 void setStCondFailures(unsigned int sc_failures) override {}
615 /////////////////////////////////////////////////////
617 void wakeup(ThreadID tid) override { }
626 bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
627 Addr pAddr, int flags);
631 ThreadContext *tcBase() const override { return tc; }
632 SimpleThread *threadBase() { return thread; }
634 InstResult unverifiedResult;
635 RequestPtr unverifiedReq;
636 uint8_t *unverifiedMemData;
640 TheISA::PCState newPCState;
643 bool warnOnlyOnLoadError;
645 InstSeqNum youngestSN;
649 * Templated Checker class. This Checker class is templated on the
650 * DynInstPtr of the instruction type that will be verified. Proper
651 * template instantiations of the Checker must be placed at the bottom
654 template <class Impl>
655 class Checker : public CheckerCPU
658 typedef typename Impl::DynInstPtr DynInstPtr;
661 Checker(const Params &p)
662 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
666 void takeOverFrom(BaseCPU *oldCPU);
668 void advancePC(const Fault &fault);
670 void verify(const DynInstPtr &inst);
672 void validateInst(const DynInstPtr &inst);
673 void validateExecution(const DynInstPtr &inst);
674 void validateState();
676 void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
678 void handlePendingInt();
681 void handleError(const DynInstPtr &inst)
685 } else if (updateOnError) {
686 updateThisCycle = true;
690 void dumpAndExit(const DynInstPtr &inst);
692 bool updateThisCycle;
694 DynInstPtr unverifiedInst;
696 std::list<DynInstPtr> instList;
697 typedef typename std::list<DynInstPtr>::iterator InstListIt;
701 #endif // __CPU_CHECKER_CPU_HH__