cpu.hh revision 13953
17753SWilliam.Wang@arm.com/*
210839Sandreas.sandberg@arm.com * Copyright (c) 2011, 2016-2018 ARM Limited
37753SWilliam.Wang@arm.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
47753SWilliam.Wang@arm.com * All rights reserved
57753SWilliam.Wang@arm.com *
67753SWilliam.Wang@arm.com * The license below extends only to copyright in the software and shall
77753SWilliam.Wang@arm.com * not be construed as granting a license to any other intellectual
87753SWilliam.Wang@arm.com * property including but not limited to intellectual property relating
97753SWilliam.Wang@arm.com * to a hardware implementation of the functionality of the software
107753SWilliam.Wang@arm.com * licensed hereunder.  You may use the software subject to the license
117753SWilliam.Wang@arm.com * terms below provided that you ensure that this notice is replicated
127753SWilliam.Wang@arm.com * unmodified and in its entirety in all distributions of the software,
137753SWilliam.Wang@arm.com * modified or unmodified, in source code or in binary form.
147753SWilliam.Wang@arm.com *
157753SWilliam.Wang@arm.com * Copyright (c) 2006 The Regents of The University of Michigan
167753SWilliam.Wang@arm.com * All rights reserved.
177753SWilliam.Wang@arm.com *
187753SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without
197753SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are
207753SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright
217753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer;
227753SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright
237753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the
247753SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution;
257753SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its
267753SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from
277753SWilliam.Wang@arm.com * this software without specific prior written permission.
287753SWilliam.Wang@arm.com *
297753SWilliam.Wang@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
307753SWilliam.Wang@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
317753SWilliam.Wang@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
327753SWilliam.Wang@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
337753SWilliam.Wang@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
347753SWilliam.Wang@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
357753SWilliam.Wang@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
367753SWilliam.Wang@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
377753SWilliam.Wang@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
387950SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
397753SWilliam.Wang@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
407753SWilliam.Wang@arm.com *
4111793Sbrandon.potter@amd.com * Authors: Kevin Lim
4211793Sbrandon.potter@amd.com */
437950SAli.Saidi@ARM.com
447753SWilliam.Wang@arm.com#ifndef __CPU_CHECKER_CPU_HH__
4511793Sbrandon.potter@amd.com#define __CPU_CHECKER_CPU_HH__
468245Snate@binkert.org
478245Snate@binkert.org#include <list>
487753SWilliam.Wang@arm.com#include <map>
499525SAndreas.Sandberg@ARM.com#include <queue>
507753SWilliam.Wang@arm.com
517753SWilliam.Wang@arm.com#include "arch/types.hh"
529525SAndreas.Sandberg@ARM.com#include "base/statistics.hh"
537753SWilliam.Wang@arm.com#include "cpu/base.hh"
548737Skoansin.tan@gmail.com#include "cpu/base_dyn_inst.hh"
558737Skoansin.tan@gmail.com#include "cpu/exec_context.hh"
568737Skoansin.tan@gmail.com#include "cpu/inst_res.hh"
578737Skoansin.tan@gmail.com#include "cpu/pc_event.hh"
587753SWilliam.Wang@arm.com#include "cpu/simple_thread.hh"
597753SWilliam.Wang@arm.com#include "cpu/static_inst.hh"
607753SWilliam.Wang@arm.com#include "debug/Checker.hh"
617753SWilliam.Wang@arm.com#include "mem/request.hh"
627950SAli.Saidi@ARM.com#include "params/CheckerCPU.hh"
637753SWilliam.Wang@arm.com#include "sim/eventq.hh"
647753SWilliam.Wang@arm.com
659157Sandreas.hansson@arm.comclass BaseTLB;
6610839Sandreas.sandberg@arm.comtemplate <class>
6710839Sandreas.sandberg@arm.comclass BaseDynInst;
6810839Sandreas.sandberg@arm.comclass ThreadContext;
699530SChris.Emmons@arm.comclass Request;
707950SAli.Saidi@ARM.com
7112086Sspwilson2@wisc.edu/**
7212086Sspwilson2@wisc.edu * CheckerCPU class.  Dynamically verifies instructions as they are
7312086Sspwilson2@wisc.edu * completed by making sure that the instruction and its results match
749395SAndreas.Sandberg@ARM.com * the independent execution of the benchmark inside the checker.  The
759395SAndreas.Sandberg@ARM.com * checker verifies instructions in order, regardless of the order in
7612086Sspwilson2@wisc.edu * which instructions complete.  There are certain results that can
7712086Sspwilson2@wisc.edu * not be verified, specifically the result of a store conditional or
787753SWilliam.Wang@arm.com * the values of uncached accesses.  In these cases, and with
797753SWilliam.Wang@arm.com * instructions marked as "IsUnverifiable", the checker assumes that
807753SWilliam.Wang@arm.com * the value from the main CPU's execution is correct and simply
818737Skoansin.tan@gmail.com * copies that value.  It provides a CheckerThreadContext (see
827950SAli.Saidi@ARM.com * checker/thread_context.hh) that provides hooks for updating the
837753SWilliam.Wang@arm.com * Checker's state through any ThreadContext accesses.  This allows the
847753SWilliam.Wang@arm.com * checker to be able to correctly verify instructions, even with
858737Skoansin.tan@gmail.com * external accesses to the ThreadContext that change state.
867950SAli.Saidi@ARM.com */
879395SAndreas.Sandberg@ARM.comclass CheckerCPU : public BaseCPU, public ExecContext
889395SAndreas.Sandberg@ARM.com{
899395SAndreas.Sandberg@ARM.com  protected:
909330Schander.sudanthi@arm.com    typedef TheISA::MachInst MachInst;
9110839Sandreas.sandberg@arm.com    using VecRegContainer = TheISA::VecRegContainer;
927753SWilliam.Wang@arm.com
937753SWilliam.Wang@arm.com    /** id attached to all issued requests */
949086Sandreas.hansson@arm.com    MasterID masterId;
959086Sandreas.hansson@arm.com  public:
969086Sandreas.hansson@arm.com    void init() override;
979086Sandreas.hansson@arm.com
989086Sandreas.hansson@arm.com    typedef CheckerCPUParams Params;
997753SWilliam.Wang@arm.com    CheckerCPU(Params *p);
1007753SWilliam.Wang@arm.com    virtual ~CheckerCPU();
1017753SWilliam.Wang@arm.com
1027753SWilliam.Wang@arm.com    void setSystem(System *system);
1037753SWilliam.Wang@arm.com
1047753SWilliam.Wang@arm.com    void setIcachePort(MasterPort *icache_port);
1057753SWilliam.Wang@arm.com
1067753SWilliam.Wang@arm.com    void setDcachePort(MasterPort *dcache_port);
1077753SWilliam.Wang@arm.com
1087950SAli.Saidi@ARM.com    MasterPort &getDataPort() override
1097950SAli.Saidi@ARM.com    {
1107753SWilliam.Wang@arm.com        // the checker does not have ports on its own so return the
1117950SAli.Saidi@ARM.com        // data port of the actual CPU core
1127753SWilliam.Wang@arm.com        assert(dcachePort);
1137950SAli.Saidi@ARM.com        return *dcachePort;
1147753SWilliam.Wang@arm.com    }
1157950SAli.Saidi@ARM.com
1167950SAli.Saidi@ARM.com    MasterPort &getInstPort() override
1177950SAli.Saidi@ARM.com    {
1187950SAli.Saidi@ARM.com        // the checker does not have ports on its own so return the
1197950SAli.Saidi@ARM.com        // data port of the actual CPU core
1207950SAli.Saidi@ARM.com        assert(icachePort);
1217950SAli.Saidi@ARM.com        return *icachePort;
1227950SAli.Saidi@ARM.com    }
1237950SAli.Saidi@ARM.com
1247950SAli.Saidi@ARM.com  protected:
1257950SAli.Saidi@ARM.com
1267950SAli.Saidi@ARM.com    std::vector<Process*> workload;
1277950SAli.Saidi@ARM.com
1287950SAli.Saidi@ARM.com    System *systemPtr;
1297950SAli.Saidi@ARM.com
1307950SAli.Saidi@ARM.com    MasterPort *icachePort;
1317950SAli.Saidi@ARM.com    MasterPort *dcachePort;
1327950SAli.Saidi@ARM.com
1337950SAli.Saidi@ARM.com    ThreadContext *tc;
1347950SAli.Saidi@ARM.com
1357950SAli.Saidi@ARM.com    BaseTLB *itb;
1367950SAli.Saidi@ARM.com    BaseTLB *dtb;
1377950SAli.Saidi@ARM.com
1387950SAli.Saidi@ARM.com    Addr dbg_vtophys(Addr addr);
1397950SAli.Saidi@ARM.com
1407950SAli.Saidi@ARM.com    // ISAs like ARM can have multiple destination registers to check,
1417950SAli.Saidi@ARM.com    // keep them all in a std::queue
1427950SAli.Saidi@ARM.com    std::queue<InstResult> result;
1437950SAli.Saidi@ARM.com
1447950SAli.Saidi@ARM.com    StaticInstPtr curStaticInst;
1457950SAli.Saidi@ARM.com    StaticInstPtr curMacroStaticInst;
1467950SAli.Saidi@ARM.com
1477950SAli.Saidi@ARM.com    // number of simulated instructions
1487950SAli.Saidi@ARM.com    Counter numInst;
1497950SAli.Saidi@ARM.com    Counter startNumInst;
1507950SAli.Saidi@ARM.com
1517950SAli.Saidi@ARM.com    std::queue<int> miscRegIdxs;
1527950SAli.Saidi@ARM.com
1537950SAli.Saidi@ARM.com  public:
1547950SAli.Saidi@ARM.com
1557950SAli.Saidi@ARM.com    // Primary thread being run.
1567950SAli.Saidi@ARM.com    SimpleThread *thread;
1577950SAli.Saidi@ARM.com
1587950SAli.Saidi@ARM.com    BaseTLB* getITBPtr() { return itb; }
1597950SAli.Saidi@ARM.com    BaseTLB* getDTBPtr() { return dtb; }
1607950SAli.Saidi@ARM.com
1617950SAli.Saidi@ARM.com    virtual Counter totalInsts() const override
1627950SAli.Saidi@ARM.com    {
1637950SAli.Saidi@ARM.com        return 0;
1647950SAli.Saidi@ARM.com    }
1657950SAli.Saidi@ARM.com
1667950SAli.Saidi@ARM.com    virtual Counter totalOps() const override
1677950SAli.Saidi@ARM.com    {
1687950SAli.Saidi@ARM.com        return 0;
1697950SAli.Saidi@ARM.com    }
1707950SAli.Saidi@ARM.com
1717950SAli.Saidi@ARM.com    // number of simulated loads
1727950SAli.Saidi@ARM.com    Counter numLoad;
1737950SAli.Saidi@ARM.com    Counter startNumLoad;
1747950SAli.Saidi@ARM.com
1757950SAli.Saidi@ARM.com    void serialize(CheckpointOut &cp) const override;
1767950SAli.Saidi@ARM.com    void unserialize(CheckpointIn &cp) override;
1777950SAli.Saidi@ARM.com
1787950SAli.Saidi@ARM.com    // The register accessor methods provide the index of the
1797950SAli.Saidi@ARM.com    // instruction's operand (e.g., 0 or 1), not the architectural
1807950SAli.Saidi@ARM.com    // register index, to simplify the implementation of register
1817950SAli.Saidi@ARM.com    // renaming.  We find the architectural register index by indexing
1827950SAli.Saidi@ARM.com    // into the instruction's own operand index table.  Note that a
1837950SAli.Saidi@ARM.com    // raw pointer to the StaticInst is provided instead of a
1847950SAli.Saidi@ARM.com    // ref-counted StaticInstPtr to redice overhead.  This is fine as
1857950SAli.Saidi@ARM.com    // long as these methods don't copy the pointer into any long-term
1869806Sstever@gmail.com    // storage (which is pretty hard to imagine they would have reason
1877950SAli.Saidi@ARM.com    // to do).
18813230Sgabeblack@google.com
1897753SWilliam.Wang@arm.com    RegVal
1907950SAli.Saidi@ARM.com    readIntRegOperand(const StaticInst *si, int idx) override
1917950SAli.Saidi@ARM.com    {
1927950SAli.Saidi@ARM.com        const RegId& reg = si->srcRegIdx(idx);
1937950SAli.Saidi@ARM.com        assert(reg.isIntReg());
1947950SAli.Saidi@ARM.com        return thread->readIntReg(reg.index());
1957753SWilliam.Wang@arm.com    }
1967950SAli.Saidi@ARM.com
1977950SAli.Saidi@ARM.com    RegVal
1987950SAli.Saidi@ARM.com    readFloatRegOperandBits(const StaticInst *si, int idx) override
1997950SAli.Saidi@ARM.com    {
2007950SAli.Saidi@ARM.com        const RegId& reg = si->srcRegIdx(idx);
2017753SWilliam.Wang@arm.com        assert(reg.isFloatReg());
2027950SAli.Saidi@ARM.com        return thread->readFloatReg(reg.index());
20310367SAndrew.Bardsley@arm.com    }
20410367SAndrew.Bardsley@arm.com
2057753SWilliam.Wang@arm.com    /**
2067753SWilliam.Wang@arm.com     * Read source vector register operand.
2077753SWilliam.Wang@arm.com     */
2087753SWilliam.Wang@arm.com    const VecRegContainer &
2097753SWilliam.Wang@arm.com    readVecRegOperand(const StaticInst *si, int idx) const override
2107753SWilliam.Wang@arm.com    {
21113230Sgabeblack@google.com        const RegId& reg = si->srcRegIdx(idx);
2127753SWilliam.Wang@arm.com        assert(reg.isVecReg());
2137753SWilliam.Wang@arm.com        return thread->readVecReg(reg);
21413230Sgabeblack@google.com    }
2157753SWilliam.Wang@arm.com
2167753SWilliam.Wang@arm.com    /**
21713230Sgabeblack@google.com     * Read destination vector register operand for modification.
2187753SWilliam.Wang@arm.com     */
2197753SWilliam.Wang@arm.com    VecRegContainer &
2207753SWilliam.Wang@arm.com    getWritableVecRegOperand(const StaticInst *si, int idx) override
2217753SWilliam.Wang@arm.com    {
2227753SWilliam.Wang@arm.com        const RegId& reg = si->destRegIdx(idx);
2237753SWilliam.Wang@arm.com        assert(reg.isVecReg());
2247753SWilliam.Wang@arm.com        return thread->getWritableVecReg(reg);
2257753SWilliam.Wang@arm.com    }
2267753SWilliam.Wang@arm.com
2277753SWilliam.Wang@arm.com    /** Vector Register Lane Interfaces. */
2287753SWilliam.Wang@arm.com    /** @{ */
2297753SWilliam.Wang@arm.com    /** Reads source vector 8bit operand. */
2307753SWilliam.Wang@arm.com    virtual ConstVecLane8
2317753SWilliam.Wang@arm.com    readVec8BitLaneOperand(const StaticInst *si, int idx) const override
2327753SWilliam.Wang@arm.com    {
2337753SWilliam.Wang@arm.com        const RegId& reg = si->destRegIdx(idx);
2347753SWilliam.Wang@arm.com        assert(reg.isVecReg());
2357753SWilliam.Wang@arm.com        return thread->readVec8BitLaneReg(reg);
2367753SWilliam.Wang@arm.com    }
2377753SWilliam.Wang@arm.com
2387753SWilliam.Wang@arm.com    /** Reads source vector 16bit operand. */
23913230Sgabeblack@google.com    virtual ConstVecLane16
2407753SWilliam.Wang@arm.com    readVec16BitLaneOperand(const StaticInst *si, int idx) const override
2417753SWilliam.Wang@arm.com    {
24213230Sgabeblack@google.com        const RegId& reg = si->destRegIdx(idx);
2437753SWilliam.Wang@arm.com        assert(reg.isVecReg());
2447753SWilliam.Wang@arm.com        return thread->readVec16BitLaneReg(reg);
24513230Sgabeblack@google.com    }
2467753SWilliam.Wang@arm.com
2477753SWilliam.Wang@arm.com    /** Reads source vector 32bit operand. */
2487753SWilliam.Wang@arm.com    virtual ConstVecLane32
2497753SWilliam.Wang@arm.com    readVec32BitLaneOperand(const StaticInst *si, int idx) const override
2507753SWilliam.Wang@arm.com    {
2517753SWilliam.Wang@arm.com        const RegId& reg = si->destRegIdx(idx);
2527950SAli.Saidi@ARM.com        assert(reg.isVecReg());
2537950SAli.Saidi@ARM.com        return thread->readVec32BitLaneReg(reg);
2547753SWilliam.Wang@arm.com    }
2557950SAli.Saidi@ARM.com
2567753SWilliam.Wang@arm.com    /** Reads source vector 64bit operand. */
2577950SAli.Saidi@ARM.com    virtual ConstVecLane64
25813230Sgabeblack@google.com    readVec64BitLaneOperand(const StaticInst *si, int idx) const override
2597753SWilliam.Wang@arm.com    {
2607950SAli.Saidi@ARM.com        const RegId& reg = si->destRegIdx(idx);
2617950SAli.Saidi@ARM.com        assert(reg.isVecReg());
2627950SAli.Saidi@ARM.com        return thread->readVec64BitLaneReg(reg);
2637950SAli.Saidi@ARM.com    }
2647950SAli.Saidi@ARM.com
2657950SAli.Saidi@ARM.com    /** Write a lane of the destination vector operand. */
2667950SAli.Saidi@ARM.com    template <typename LD>
2677950SAli.Saidi@ARM.com    void
2687950SAli.Saidi@ARM.com    setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
2697950SAli.Saidi@ARM.com    {
2707950SAli.Saidi@ARM.com        const RegId& reg = si->destRegIdx(idx);
2717950SAli.Saidi@ARM.com        assert(reg.isVecReg());
2727950SAli.Saidi@ARM.com        return thread->setVecLane(reg, val);
2737950SAli.Saidi@ARM.com    }
2747950SAli.Saidi@ARM.com    virtual void
2757950SAli.Saidi@ARM.com    setVecLaneOperand(const StaticInst *si, int idx,
2767950SAli.Saidi@ARM.com            const LaneData<LaneSize::Byte>& val) override
2777950SAli.Saidi@ARM.com    {
2787950SAli.Saidi@ARM.com        setVecLaneOperandT(si, idx, val);
2797950SAli.Saidi@ARM.com    }
2807950SAli.Saidi@ARM.com    virtual void
2817950SAli.Saidi@ARM.com    setVecLaneOperand(const StaticInst *si, int idx,
2828508SAli.Saidi@ARM.com            const LaneData<LaneSize::TwoByte>& val) override
2837950SAli.Saidi@ARM.com    {
2847950SAli.Saidi@ARM.com        setVecLaneOperandT(si, idx, val);
2857950SAli.Saidi@ARM.com    }
2867950SAli.Saidi@ARM.com    virtual void
2877950SAli.Saidi@ARM.com    setVecLaneOperand(const StaticInst *si, int idx,
2887950SAli.Saidi@ARM.com            const LaneData<LaneSize::FourByte>& val) override
2897950SAli.Saidi@ARM.com    {
2907753SWilliam.Wang@arm.com        setVecLaneOperandT(si, idx, val);
2917950SAli.Saidi@ARM.com    }
2927950SAli.Saidi@ARM.com    virtual void
2937950SAli.Saidi@ARM.com    setVecLaneOperand(const StaticInst *si, int idx,
2947950SAli.Saidi@ARM.com            const LaneData<LaneSize::EightByte>& val) override
2957950SAli.Saidi@ARM.com    {
2967950SAli.Saidi@ARM.com        setVecLaneOperandT(si, idx, val);
2977950SAli.Saidi@ARM.com    }
2987950SAli.Saidi@ARM.com    /** @} */
2997950SAli.Saidi@ARM.com
3007950SAli.Saidi@ARM.com    VecElem
3017950SAli.Saidi@ARM.com    readVecElemOperand(const StaticInst *si, int idx) const override
3027950SAli.Saidi@ARM.com    {
3037950SAli.Saidi@ARM.com        const RegId& reg = si->srcRegIdx(idx);
3047950SAli.Saidi@ARM.com        return thread->readVecElem(reg);
3057950SAli.Saidi@ARM.com    }
3067950SAli.Saidi@ARM.com
3077950SAli.Saidi@ARM.com    const VecPredRegContainer&
3087950SAli.Saidi@ARM.com    readVecPredRegOperand(const StaticInst *si, int idx) const override
3097950SAli.Saidi@ARM.com    {
3107950SAli.Saidi@ARM.com        const RegId& reg = si->srcRegIdx(idx);
3117950SAli.Saidi@ARM.com        assert(reg.isVecPredReg());
3127950SAli.Saidi@ARM.com        return thread->readVecPredReg(reg);
3137950SAli.Saidi@ARM.com    }
3147950SAli.Saidi@ARM.com
3157950SAli.Saidi@ARM.com    VecPredRegContainer&
3167950SAli.Saidi@ARM.com    getWritableVecPredRegOperand(const StaticInst *si, int idx) override
3177950SAli.Saidi@ARM.com    {
3187950SAli.Saidi@ARM.com        const RegId& reg = si->destRegIdx(idx);
3197950SAli.Saidi@ARM.com        assert(reg.isVecPredReg());
3207950SAli.Saidi@ARM.com        return thread->getWritableVecPredReg(reg);
3217950SAli.Saidi@ARM.com    }
3227950SAli.Saidi@ARM.com
3237950SAli.Saidi@ARM.com    RegVal
3247950SAli.Saidi@ARM.com    readCCRegOperand(const StaticInst *si, int idx) override
3257950SAli.Saidi@ARM.com    {
3267950SAli.Saidi@ARM.com        const RegId& reg = si->srcRegIdx(idx);
3277950SAli.Saidi@ARM.com        assert(reg.isCCReg());
3287950SAli.Saidi@ARM.com        return thread->readCCReg(reg.index());
3297950SAli.Saidi@ARM.com    }
3307950SAli.Saidi@ARM.com
3317950SAli.Saidi@ARM.com    template<typename T>
3327950SAli.Saidi@ARM.com    void
3337950SAli.Saidi@ARM.com    setScalarResult(T&& t)
3347950SAli.Saidi@ARM.com    {
3357950SAli.Saidi@ARM.com        result.push(InstResult(std::forward<T>(t),
3367950SAli.Saidi@ARM.com                               InstResult::ResultType::Scalar));
3377950SAli.Saidi@ARM.com    }
3387950SAli.Saidi@ARM.com
3397950SAli.Saidi@ARM.com    template<typename T>
3407950SAli.Saidi@ARM.com    void
3417950SAli.Saidi@ARM.com    setVecResult(T&& t)
3427950SAli.Saidi@ARM.com    {
3437950SAli.Saidi@ARM.com        result.push(InstResult(std::forward<T>(t),
3447950SAli.Saidi@ARM.com                               InstResult::ResultType::VecReg));
3457950SAli.Saidi@ARM.com    }
3467950SAli.Saidi@ARM.com
3477950SAli.Saidi@ARM.com    template<typename T>
3487950SAli.Saidi@ARM.com    void
3497950SAli.Saidi@ARM.com    setVecElemResult(T&& t)
3507950SAli.Saidi@ARM.com    {
3517950SAli.Saidi@ARM.com        result.push(InstResult(std::forward<T>(t),
3527950SAli.Saidi@ARM.com                               InstResult::ResultType::VecElem));
3537950SAli.Saidi@ARM.com    }
3547950SAli.Saidi@ARM.com
3557950SAli.Saidi@ARM.com    template<typename T>
3567950SAli.Saidi@ARM.com    void
3577950SAli.Saidi@ARM.com    setVecPredResult(T&& t)
3587950SAli.Saidi@ARM.com    {
3597950SAli.Saidi@ARM.com        result.push(InstResult(std::forward<T>(t),
3607950SAli.Saidi@ARM.com                               InstResult::ResultType::VecPredReg));
3617950SAli.Saidi@ARM.com    }
3627950SAli.Saidi@ARM.com
3637950SAli.Saidi@ARM.com    void
3647950SAli.Saidi@ARM.com    setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
3657950SAli.Saidi@ARM.com    {
3667950SAli.Saidi@ARM.com        const RegId& reg = si->destRegIdx(idx);
3677950SAli.Saidi@ARM.com        assert(reg.isIntReg());
3687753SWilliam.Wang@arm.com        thread->setIntReg(reg.index(), val);
3697950SAli.Saidi@ARM.com        setScalarResult(val);
3707950SAli.Saidi@ARM.com    }
3717950SAli.Saidi@ARM.com
3727950SAli.Saidi@ARM.com    void
3737950SAli.Saidi@ARM.com    setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
3747753SWilliam.Wang@arm.com    {
3757950SAli.Saidi@ARM.com        const RegId& reg = si->destRegIdx(idx);
37610367SAndrew.Bardsley@arm.com        assert(reg.isFloatReg());
37710367SAndrew.Bardsley@arm.com        thread->setFloatReg(reg.index(), val);
3787753SWilliam.Wang@arm.com        setScalarResult(val);
3797753SWilliam.Wang@arm.com    }
3807753SWilliam.Wang@arm.com
3817753SWilliam.Wang@arm.com    void
3827753SWilliam.Wang@arm.com    setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
3837753SWilliam.Wang@arm.com    {
3847753SWilliam.Wang@arm.com        const RegId& reg = si->destRegIdx(idx);
3857753SWilliam.Wang@arm.com        assert(reg.isCCReg());
38610839Sandreas.sandberg@arm.com        thread->setCCReg(reg.index(), val);
38710839Sandreas.sandberg@arm.com        setScalarResult((uint64_t)val);
38810839Sandreas.sandberg@arm.com    }
38910839Sandreas.sandberg@arm.com
39010839Sandreas.sandberg@arm.com    void
39110839Sandreas.sandberg@arm.com    setVecRegOperand(const StaticInst *si, int idx,
39210839Sandreas.sandberg@arm.com                     const VecRegContainer& val) override
39310839Sandreas.sandberg@arm.com    {
39410839Sandreas.sandberg@arm.com        const RegId& reg = si->destRegIdx(idx);
39510839Sandreas.sandberg@arm.com        assert(reg.isVecReg());
39610839Sandreas.sandberg@arm.com        thread->setVecReg(reg, val);
39710839Sandreas.sandberg@arm.com        setVecResult(val);
39810839Sandreas.sandberg@arm.com    }
39910839Sandreas.sandberg@arm.com
40010839Sandreas.sandberg@arm.com    void
40110839Sandreas.sandberg@arm.com    setVecElemOperand(const StaticInst *si, int idx,
40210839Sandreas.sandberg@arm.com                      const VecElem val) override
40310839Sandreas.sandberg@arm.com    {
40410839Sandreas.sandberg@arm.com        const RegId& reg = si->destRegIdx(idx);
40510839Sandreas.sandberg@arm.com        assert(reg.isVecElem());
40610839Sandreas.sandberg@arm.com        thread->setVecElem(reg, val);
40710839Sandreas.sandberg@arm.com        setVecElemResult(val);
40810839Sandreas.sandberg@arm.com    }
40910839Sandreas.sandberg@arm.com
41010839Sandreas.sandberg@arm.com    void setVecPredRegOperand(const StaticInst *si, int idx,
41110839Sandreas.sandberg@arm.com                              const VecPredRegContainer& val) override
41210839Sandreas.sandberg@arm.com    {
41310839Sandreas.sandberg@arm.com        const RegId& reg = si->destRegIdx(idx);
41410839Sandreas.sandberg@arm.com        assert(reg.isVecPredReg());
41510839Sandreas.sandberg@arm.com        thread->setVecPredReg(reg, val);
41610839Sandreas.sandberg@arm.com        setVecPredResult(val);
41710839Sandreas.sandberg@arm.com    }
41810839Sandreas.sandberg@arm.com
41910839Sandreas.sandberg@arm.com    bool readPredicate() const override { return thread->readPredicate(); }
42010839Sandreas.sandberg@arm.com
42110839Sandreas.sandberg@arm.com    void
42210839Sandreas.sandberg@arm.com    setPredicate(bool val) override
42310839Sandreas.sandberg@arm.com    {
42410839Sandreas.sandberg@arm.com        thread->setPredicate(val);
42510839Sandreas.sandberg@arm.com    }
42610839Sandreas.sandberg@arm.com
42710839Sandreas.sandberg@arm.com    bool
4287753SWilliam.Wang@arm.com    readMemAccPredicate() const override
4297950SAli.Saidi@ARM.com    {
4307950SAli.Saidi@ARM.com        return thread->readMemAccPredicate();
43110839Sandreas.sandberg@arm.com    }
43210839Sandreas.sandberg@arm.com
43310839Sandreas.sandberg@arm.com    void
43410839Sandreas.sandberg@arm.com    setMemAccPredicate(bool val) override
43510839Sandreas.sandberg@arm.com    {
4367950SAli.Saidi@ARM.com        thread->setMemAccPredicate(val);
43710839Sandreas.sandberg@arm.com    }
43810839Sandreas.sandberg@arm.com
4397950SAli.Saidi@ARM.com    TheISA::PCState pcState() const override { return thread->pcState(); }
44010839Sandreas.sandberg@arm.com    void
44110839Sandreas.sandberg@arm.com    pcState(const TheISA::PCState &val) override
44210839Sandreas.sandberg@arm.com    {
44310839Sandreas.sandberg@arm.com        DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
44410839Sandreas.sandberg@arm.com                         val, thread->pcState());
44510839Sandreas.sandberg@arm.com        thread->pcState(val);
4467950SAli.Saidi@ARM.com    }
4477950SAli.Saidi@ARM.com    Addr instAddr() { return thread->instAddr(); }
4487950SAli.Saidi@ARM.com    Addr nextInstAddr() { return thread->nextInstAddr(); }
4497950SAli.Saidi@ARM.com    MicroPC microPC() { return thread->microPC(); }
4507950SAli.Saidi@ARM.com    //////////////////////////////////////////
4517950SAli.Saidi@ARM.com
4527950SAli.Saidi@ARM.com    RegVal
4537950SAli.Saidi@ARM.com    readMiscRegNoEffect(int misc_reg) const
4547950SAli.Saidi@ARM.com    {
4557950SAli.Saidi@ARM.com        return thread->readMiscRegNoEffect(misc_reg);
4567950SAli.Saidi@ARM.com    }
4577753SWilliam.Wang@arm.com
4587753SWilliam.Wang@arm.com    RegVal
4597753SWilliam.Wang@arm.com    readMiscReg(int misc_reg) override
4607950SAli.Saidi@ARM.com    {
4617950SAli.Saidi@ARM.com        return thread->readMiscReg(misc_reg);
4627753SWilliam.Wang@arm.com    }
4637950SAli.Saidi@ARM.com
4647950SAli.Saidi@ARM.com    void
4657950SAli.Saidi@ARM.com    setMiscRegNoEffect(int misc_reg, RegVal val)
4667950SAli.Saidi@ARM.com    {
4679648Sdam.sunwoo@arm.com        DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n",
4687950SAli.Saidi@ARM.com                misc_reg);
4697753SWilliam.Wang@arm.com        miscRegIdxs.push(misc_reg);
4709394Sandreas.hansson@arm.com        return thread->setMiscRegNoEffect(misc_reg, val);
4717950SAli.Saidi@ARM.com    }
4727950SAli.Saidi@ARM.com
4737950SAli.Saidi@ARM.com    void
4747950SAli.Saidi@ARM.com    setMiscReg(int misc_reg, RegVal val) override
4757950SAli.Saidi@ARM.com    {
4767753SWilliam.Wang@arm.com        DPRINTF(Checker, "Setting misc reg %d with effect to check later\n",
4777753SWilliam.Wang@arm.com                misc_reg);
4787753SWilliam.Wang@arm.com        miscRegIdxs.push(misc_reg);
4797753SWilliam.Wang@arm.com        return thread->setMiscReg(misc_reg, val);
4807753SWilliam.Wang@arm.com    }
4817753SWilliam.Wang@arm.com
4827753SWilliam.Wang@arm.com    RegVal
4837753SWilliam.Wang@arm.com    readMiscRegOperand(const StaticInst *si, int idx) override
4847753SWilliam.Wang@arm.com    {
4857753SWilliam.Wang@arm.com        const RegId& reg = si->srcRegIdx(idx);
4867950SAli.Saidi@ARM.com        assert(reg.isMiscReg());
4879395SAndreas.Sandberg@ARM.com        return thread->readMiscReg(reg.index());
4889395SAndreas.Sandberg@ARM.com    }
4899395SAndreas.Sandberg@ARM.com
4909395SAndreas.Sandberg@ARM.com    void
4917950SAli.Saidi@ARM.com    setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
4927950SAli.Saidi@ARM.com    {
4937950SAli.Saidi@ARM.com        const RegId& reg = si->destRegIdx(idx);
4947950SAli.Saidi@ARM.com        assert(reg.isMiscReg());
4957950SAli.Saidi@ARM.com        return this->setMiscReg(reg.index(), val);
4968851Sandreas.hansson@arm.com    }
4979395SAndreas.Sandberg@ARM.com
4988851Sandreas.hansson@arm.com    /////////////////////////////////////////
4997753SWilliam.Wang@arm.com
5007753SWilliam.Wang@arm.com    void
5017753SWilliam.Wang@arm.com    recordPCChange(const TheISA::PCState &val)
5027753SWilliam.Wang@arm.com    {
5037753SWilliam.Wang@arm.com       changedPC = true;
5047753SWilliam.Wang@arm.com       newPCState = val;
5057753SWilliam.Wang@arm.com    }
5069394Sandreas.hansson@arm.com
5079394Sandreas.hansson@arm.com    void
5089394Sandreas.hansson@arm.com    demapPage(Addr vaddr, uint64_t asn) override
5097753SWilliam.Wang@arm.com    {
5107753SWilliam.Wang@arm.com        this->itb->demapPage(vaddr, asn);
5117753SWilliam.Wang@arm.com        this->dtb->demapPage(vaddr, asn);
5127753SWilliam.Wang@arm.com    }
5139394Sandreas.hansson@arm.com
5149394Sandreas.hansson@arm.com    // monitor/mwait funtions
5157823Ssteve.reinhardt@amd.com    void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); }
5167950SAli.Saidi@ARM.com    bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
5177950SAli.Saidi@ARM.com    void mwaitAtomic(ThreadContext *tc) override
5189648Sdam.sunwoo@arm.com    { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
5197950SAli.Saidi@ARM.com    AddressMonitor *getAddrMonitor() override
5207753SWilliam.Wang@arm.com    { return BaseCPU::getCpuAddrMonitor(0); }
5217753SWilliam.Wang@arm.com
52210839Sandreas.sandberg@arm.com    void
5239330Schander.sudanthi@arm.com    demapInstPage(Addr vaddr, uint64_t asn)
5249330Schander.sudanthi@arm.com    {
5257753SWilliam.Wang@arm.com        this->itb->demapPage(vaddr, asn);
5269939Sdam.sunwoo@arm.com    }
5279939Sdam.sunwoo@arm.com
5287950SAli.Saidi@ARM.com    void
5299939Sdam.sunwoo@arm.com    demapDataPage(Addr vaddr, uint64_t asn)
53011359Sandreas@sandberg.pp.se    {
53111359Sandreas@sandberg.pp.se        this->dtb->demapPage(vaddr, asn);
5329530SChris.Emmons@arm.com    }
5339939Sdam.sunwoo@arm.com
53411359Sandreas@sandberg.pp.se    Fault readMem(Addr addr, uint8_t *data, unsigned size,
53511359Sandreas@sandberg.pp.se                  Request::Flags flags) override;
5369939Sdam.sunwoo@arm.com
5377753SWilliam.Wang@arm.com    Fault writeMem(uint8_t *data, unsigned size, Addr addr,
5389179Sandreas.hansson@arm.com                   Request::Flags flags, uint64_t *res) override;
5399179Sandreas.hansson@arm.com
5409394Sandreas.hansson@arm.com    Fault amoMem(Addr addr, uint8_t* data, unsigned size,
5417950SAli.Saidi@ARM.com                 Request::Flags flags, AtomicOpFunctor *amo_op) override
5429394Sandreas.hansson@arm.com    {
5439394Sandreas.hansson@arm.com        panic("AMO is not supported yet in CPU checker\n");
5449394Sandreas.hansson@arm.com    }
5457753SWilliam.Wang@arm.com
5467753SWilliam.Wang@arm.com    unsigned int
5477753SWilliam.Wang@arm.com    readStCondFailures() const override {
5487753SWilliam.Wang@arm.com        return thread->readStCondFailures();
5497753SWilliam.Wang@arm.com    }
5507753SWilliam.Wang@arm.com
5519648Sdam.sunwoo@arm.com    void setStCondFailures(unsigned int sc_failures) override {}
5527950SAli.Saidi@ARM.com    /////////////////////////////////////////////////////
5537753SWilliam.Wang@arm.com
5547753SWilliam.Wang@arm.com    void wakeup(ThreadID tid) override { }
55510905Sandreas.sandberg@arm.com    // Assume that the normal CPU's call to syscall was successful.
5567753SWilliam.Wang@arm.com    // The checker's state would have already been updated by the syscall.
5577753SWilliam.Wang@arm.com    void syscall(int64_t callnum, Fault *fault) override { }
5587753SWilliam.Wang@arm.com
5597753SWilliam.Wang@arm.com    void
5607753SWilliam.Wang@arm.com    handleError()
5617753SWilliam.Wang@arm.com    {
5627753SWilliam.Wang@arm.com        if (exitOnError)
5637753SWilliam.Wang@arm.com            dumpAndExit();
5647753SWilliam.Wang@arm.com    }
5657753SWilliam.Wang@arm.com
5667753SWilliam.Wang@arm.com    bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
5677753SWilliam.Wang@arm.com                    Addr pAddr, int flags);
5687753SWilliam.Wang@arm.com
5697753SWilliam.Wang@arm.com    void dumpAndExit();
5707753SWilliam.Wang@arm.com
5717753SWilliam.Wang@arm.com    ThreadContext *tcBase() override { return tc; }
5727753SWilliam.Wang@arm.com    SimpleThread *threadBase() { return thread; }
5737753SWilliam.Wang@arm.com
5747753SWilliam.Wang@arm.com    InstResult unverifiedResult;
5757753SWilliam.Wang@arm.com    RequestPtr unverifiedReq;
5767753SWilliam.Wang@arm.com    uint8_t *unverifiedMemData;
5777753SWilliam.Wang@arm.com
5787753SWilliam.Wang@arm.com    bool changedPC;
5797753SWilliam.Wang@arm.com    bool willChangePC;
5807753SWilliam.Wang@arm.com    TheISA::PCState newPCState;
5817753SWilliam.Wang@arm.com    bool exitOnError;
5827753SWilliam.Wang@arm.com    bool updateOnError;
5837753SWilliam.Wang@arm.com    bool warnOnlyOnLoadError;
5847753SWilliam.Wang@arm.com
5857753SWilliam.Wang@arm.com    InstSeqNum youngestSN;
5867753SWilliam.Wang@arm.com};
5877753SWilliam.Wang@arm.com
5887753SWilliam.Wang@arm.com/**
5897753SWilliam.Wang@arm.com * Templated Checker class.  This Checker class is templated on the
5907753SWilliam.Wang@arm.com * DynInstPtr of the instruction type that will be verified.  Proper
5917753SWilliam.Wang@arm.com * template instantiations of the Checker must be placed at the bottom
5927753SWilliam.Wang@arm.com * of checker/cpu.cc.
5937753SWilliam.Wang@arm.com */
5947753SWilliam.Wang@arm.comtemplate <class Impl>
5957753SWilliam.Wang@arm.comclass Checker : public CheckerCPU
5967753SWilliam.Wang@arm.com{
5977753SWilliam.Wang@arm.com  private:
5987753SWilliam.Wang@arm.com    typedef typename Impl::DynInstPtr DynInstPtr;
5997753SWilliam.Wang@arm.com
6007753SWilliam.Wang@arm.com  public:
6017753SWilliam.Wang@arm.com    Checker(Params *p)
6027753SWilliam.Wang@arm.com        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
6037753SWilliam.Wang@arm.com    { }
6047753SWilliam.Wang@arm.com
6057753SWilliam.Wang@arm.com    void switchOut();
6067753SWilliam.Wang@arm.com    void takeOverFrom(BaseCPU *oldCPU);
6077753SWilliam.Wang@arm.com
6087753SWilliam.Wang@arm.com    void advancePC(const Fault &fault);
6097753SWilliam.Wang@arm.com
6107950SAli.Saidi@ARM.com    void verify(const DynInstPtr &inst);
6117753SWilliam.Wang@arm.com
6129415SChander.Sudanthi@arm.com    void validateInst(const DynInstPtr &inst);
6137753SWilliam.Wang@arm.com    void validateExecution(const DynInstPtr &inst);
6147753SWilliam.Wang@arm.com    void validateState();
6157753SWilliam.Wang@arm.com
6167753SWilliam.Wang@arm.com    void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
6177753SWilliam.Wang@arm.com                    int start_idx);
6187753SWilliam.Wang@arm.com    void handlePendingInt();
6198062SAli.Saidi@ARM.com
6208062SAli.Saidi@ARM.com  private:
6218062SAli.Saidi@ARM.com    void handleError(const DynInstPtr &inst)
6228062SAli.Saidi@ARM.com    {
6238062SAli.Saidi@ARM.com        if (exitOnError) {
6248062SAli.Saidi@ARM.com            dumpAndExit(inst);
6258062SAli.Saidi@ARM.com        } else if (updateOnError) {
6268062SAli.Saidi@ARM.com            updateThisCycle = true;
6278062SAli.Saidi@ARM.com        }
6288062SAli.Saidi@ARM.com    }
6298062SAli.Saidi@ARM.com
6308062SAli.Saidi@ARM.com    void dumpAndExit(const DynInstPtr &inst);
6318062SAli.Saidi@ARM.com
6328062SAli.Saidi@ARM.com    bool updateThisCycle;
6338062SAli.Saidi@ARM.com
6348062SAli.Saidi@ARM.com    DynInstPtr unverifiedInst;
6358062SAli.Saidi@ARM.com
6368062SAli.Saidi@ARM.com    std::list<DynInstPtr> instList;
6378062SAli.Saidi@ARM.com    typedef typename std::list<DynInstPtr>::iterator InstListIt;
6389395SAndreas.Sandberg@ARM.com    void dumpInsts();
6399395SAndreas.Sandberg@ARM.com};
6408062SAli.Saidi@ARM.com
64110905Sandreas.sandberg@arm.com#endif // __CPU_CHECKER_CPU_HH__
6427753SWilliam.Wang@arm.com