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