12315SN/A/*
213953Sgiacomo.gabrielli@arm.com * Copyright (c) 2011, 2016-2018 ARM Limited
39920Syasuko.eckert@amd.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
48733Sgeoffrey.blake@arm.com * All rights reserved
58733Sgeoffrey.blake@arm.com *
68733Sgeoffrey.blake@arm.com * The license below extends only to copyright in the software and shall
78733Sgeoffrey.blake@arm.com * not be construed as granting a license to any other intellectual
88733Sgeoffrey.blake@arm.com * property including but not limited to intellectual property relating
98733Sgeoffrey.blake@arm.com * to a hardware implementation of the functionality of the software
108733Sgeoffrey.blake@arm.com * licensed hereunder.  You may use the software subject to the license
118733Sgeoffrey.blake@arm.com * terms below provided that you ensure that this notice is replicated
128733Sgeoffrey.blake@arm.com * unmodified and in its entirety in all distributions of the software,
138733Sgeoffrey.blake@arm.com * modified or unmodified, in source code or in binary form.
148733Sgeoffrey.blake@arm.com *
152332SN/A * Copyright (c) 2006 The Regents of The University of Michigan
162315SN/A * All rights reserved.
172315SN/A *
182315SN/A * Redistribution and use in source and binary forms, with or without
192315SN/A * modification, are permitted provided that the following conditions are
202315SN/A * met: redistributions of source code must retain the above copyright
212315SN/A * notice, this list of conditions and the following disclaimer;
222315SN/A * redistributions in binary form must reproduce the above copyright
232315SN/A * notice, this list of conditions and the following disclaimer in the
242315SN/A * documentation and/or other materials provided with the distribution;
252315SN/A * neither the name of the copyright holders nor the names of its
262315SN/A * contributors may be used to endorse or promote products derived from
272315SN/A * this software without specific prior written permission.
282315SN/A *
292315SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
302315SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
312315SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
322315SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
332315SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
342315SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
352315SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
362315SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
372315SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
382315SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
392315SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
402689Sktlim@umich.edu *
412689Sktlim@umich.edu * Authors: Kevin Lim
422315SN/A */
432315SN/A
442315SN/A#ifndef __CPU_CHECKER_CPU_HH__
452315SN/A#define __CPU_CHECKER_CPU_HH__
462315SN/A
472315SN/A#include <list>
488229Snate@binkert.org#include <map>
492315SN/A#include <queue>
502315SN/A
512669Sktlim@umich.edu#include "arch/types.hh"
522315SN/A#include "base/statistics.hh"
532315SN/A#include "cpu/base.hh"
542315SN/A#include "cpu/base_dyn_inst.hh"
5510319SAndreas.Sandberg@ARM.com#include "cpu/exec_context.hh"
5612107SRekai.GonzalezAlberquilla@arm.com#include "cpu/inst_res.hh"
578229Snate@binkert.org#include "cpu/pc_event.hh"
582683Sktlim@umich.edu#include "cpu/simple_thread.hh"
592315SN/A#include "cpu/static_inst.hh"
608733Sgeoffrey.blake@arm.com#include "debug/Checker.hh"
6111608Snikos.nikoleris@arm.com#include "mem/request.hh"
628733Sgeoffrey.blake@arm.com#include "params/CheckerCPU.hh"
632315SN/A#include "sim/eventq.hh"
642315SN/A
6512406Sgabeblack@google.comclass BaseTLB;
662315SN/Atemplate <class>
672315SN/Aclass BaseDynInst;
682680Sktlim@umich.educlass ThreadContext;
692669Sktlim@umich.educlass Request;
702315SN/A
712350SN/A/**
722350SN/A * CheckerCPU class.  Dynamically verifies instructions as they are
732350SN/A * completed by making sure that the instruction and its results match
742350SN/A * the independent execution of the benchmark inside the checker.  The
752350SN/A * checker verifies instructions in order, regardless of the order in
762350SN/A * which instructions complete.  There are certain results that can
772350SN/A * not be verified, specifically the result of a store conditional or
782350SN/A * the values of uncached accesses.  In these cases, and with
792350SN/A * instructions marked as "IsUnverifiable", the checker assumes that
802350SN/A * the value from the main CPU's execution is correct and simply
812680Sktlim@umich.edu * copies that value.  It provides a CheckerThreadContext (see
822683Sktlim@umich.edu * checker/thread_context.hh) that provides hooks for updating the
832680Sktlim@umich.edu * Checker's state through any ThreadContext accesses.  This allows the
842350SN/A * checker to be able to correctly verify instructions, even with
852680Sktlim@umich.edu * external accesses to the ThreadContext that change state.
862350SN/A */
8710319SAndreas.Sandberg@ARM.comclass CheckerCPU : public BaseCPU, public ExecContext
882315SN/A{
892315SN/A  protected:
902315SN/A    typedef TheISA::MachInst MachInst;
9112109SRekai.GonzalezAlberquilla@arm.com    using VecRegContainer = TheISA::VecRegContainer;
928832SAli.Saidi@ARM.com
938832SAli.Saidi@ARM.com    /** id attached to all issued requests */
948832SAli.Saidi@ARM.com    MasterID masterId;
952315SN/A  public:
9611169Sandreas.hansson@arm.com    void init() override;
972315SN/A
985529Snate@binkert.org    typedef CheckerCPUParams Params;
992315SN/A    CheckerCPU(Params *p);
1002315SN/A    virtual ~CheckerCPU();
1012315SN/A
1022315SN/A    void setSystem(System *system);
1032315SN/A
1049608Sandreas.hansson@arm.com    void setIcachePort(MasterPort *icache_port);
1052679Sktlim@umich.edu
1069608Sandreas.hansson@arm.com    void setDcachePort(MasterPort *dcache_port);
1072679Sktlim@umich.edu
10814198Sgabeblack@google.com    Port &
10914198Sgabeblack@google.com    getDataPort() override
1108887Sgeoffrey.blake@arm.com    {
1119176Sandreas.hansson@arm.com        // the checker does not have ports on its own so return the
1129176Sandreas.hansson@arm.com        // data port of the actual CPU core
1139176Sandreas.hansson@arm.com        assert(dcachePort);
1148887Sgeoffrey.blake@arm.com        return *dcachePort;
1158887Sgeoffrey.blake@arm.com    }
1168887Sgeoffrey.blake@arm.com
11714198Sgabeblack@google.com    Port &
11814198Sgabeblack@google.com    getInstPort() override
1198887Sgeoffrey.blake@arm.com    {
1209176Sandreas.hansson@arm.com        // the checker does not have ports on its own so return the
1219176Sandreas.hansson@arm.com        // data port of the actual CPU core
1229176Sandreas.hansson@arm.com        assert(icachePort);
1238887Sgeoffrey.blake@arm.com        return *icachePort;
1248887Sgeoffrey.blake@arm.com    }
1252679Sktlim@umich.edu
1269176Sandreas.hansson@arm.com  protected:
1279176Sandreas.hansson@arm.com
1289176Sandreas.hansson@arm.com    std::vector<Process*> workload;
1299176Sandreas.hansson@arm.com
1309176Sandreas.hansson@arm.com    System *systemPtr;
1319176Sandreas.hansson@arm.com
1329608Sandreas.hansson@arm.com    MasterPort *icachePort;
1339608Sandreas.hansson@arm.com    MasterPort *dcachePort;
1342315SN/A
1352680Sktlim@umich.edu    ThreadContext *tc;
1362315SN/A
13712406Sgabeblack@google.com    BaseTLB *itb;
13812406Sgabeblack@google.com    BaseTLB *dtb;
1392315SN/A
1402315SN/A    Addr dbg_vtophys(Addr addr);
1412315SN/A
1428733Sgeoffrey.blake@arm.com    // ISAs like ARM can have multiple destination registers to check,
1438733Sgeoffrey.blake@arm.com    // keep them all in a std::queue
14412107SRekai.GonzalezAlberquilla@arm.com    std::queue<InstResult> result;
1452315SN/A
1462315SN/A    StaticInstPtr curStaticInst;
1478733Sgeoffrey.blake@arm.com    StaticInstPtr curMacroStaticInst;
1482315SN/A
1492315SN/A    // number of simulated instructions
1502315SN/A    Counter numInst;
1512315SN/A    Counter startNumInst;
1522315SN/A
1532315SN/A    std::queue<int> miscRegIdxs;
1542315SN/A
1559176Sandreas.hansson@arm.com  public:
1569176Sandreas.hansson@arm.com
1579176Sandreas.hansson@arm.com    // Primary thread being run.
1589176Sandreas.hansson@arm.com    SimpleThread *thread;
1599176Sandreas.hansson@arm.com
16012406Sgabeblack@google.com    BaseTLB* getITBPtr() { return itb; }
16112406Sgabeblack@google.com    BaseTLB* getDTBPtr() { return dtb; }
1628733Sgeoffrey.blake@arm.com
16311169Sandreas.hansson@arm.com    virtual Counter totalInsts() const override
1648887Sgeoffrey.blake@arm.com    {
1658887Sgeoffrey.blake@arm.com        return 0;
1668887Sgeoffrey.blake@arm.com    }
1678887Sgeoffrey.blake@arm.com
16811169Sandreas.hansson@arm.com    virtual Counter totalOps() const override
1692315SN/A    {
1702930Sktlim@umich.edu        return 0;
1712315SN/A    }
1722315SN/A
1732315SN/A    // number of simulated loads
1742315SN/A    Counter numLoad;
1752315SN/A    Counter startNumLoad;
1762315SN/A
17711168Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
17811168Sandreas.hansson@arm.com    void unserialize(CheckpointIn &cp) override;
1792315SN/A
1802315SN/A    // The register accessor methods provide the index of the
1812315SN/A    // instruction's operand (e.g., 0 or 1), not the architectural
1822315SN/A    // register index, to simplify the implementation of register
1832315SN/A    // renaming.  We find the architectural register index by indexing
1842315SN/A    // into the instruction's own operand index table.  Note that a
1852315SN/A    // raw pointer to the StaticInst is provided instead of a
1862315SN/A    // ref-counted StaticInstPtr to redice overhead.  This is fine as
1872315SN/A    // long as these methods don't copy the pointer into any long-term
1882315SN/A    // storage (which is pretty hard to imagine they would have reason
1892315SN/A    // to do).
1902315SN/A
19113557Sgabeblack@google.com    RegVal
19213557Sgabeblack@google.com    readIntRegOperand(const StaticInst *si, int idx) override
1932315SN/A    {
19412106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->srcRegIdx(idx);
19512106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isIntReg());
19612106SRekai.GonzalezAlberquilla@arm.com        return thread->readIntReg(reg.index());
1972315SN/A    }
1982315SN/A
19913557Sgabeblack@google.com    RegVal
20013557Sgabeblack@google.com    readFloatRegOperandBits(const StaticInst *si, int idx) override
2012669Sktlim@umich.edu    {
20212106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->srcRegIdx(idx);
20312106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isFloatReg());
20413611Sgabeblack@google.com        return thread->readFloatReg(reg.index());
2052315SN/A    }
2062315SN/A
20712109SRekai.GonzalezAlberquilla@arm.com    /**
20812109SRekai.GonzalezAlberquilla@arm.com     * Read source vector register operand.
20912109SRekai.GonzalezAlberquilla@arm.com     */
21013557Sgabeblack@google.com    const VecRegContainer &
21113557Sgabeblack@google.com    readVecRegOperand(const StaticInst *si, int idx) const override
21212109SRekai.GonzalezAlberquilla@arm.com    {
21312109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->srcRegIdx(idx);
21412109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
21512109SRekai.GonzalezAlberquilla@arm.com        return thread->readVecReg(reg);
21612109SRekai.GonzalezAlberquilla@arm.com    }
21712109SRekai.GonzalezAlberquilla@arm.com
21812109SRekai.GonzalezAlberquilla@arm.com    /**
21912109SRekai.GonzalezAlberquilla@arm.com     * Read destination vector register operand for modification.
22012109SRekai.GonzalezAlberquilla@arm.com     */
22113557Sgabeblack@google.com    VecRegContainer &
22213557Sgabeblack@google.com    getWritableVecRegOperand(const StaticInst *si, int idx) override
22312109SRekai.GonzalezAlberquilla@arm.com    {
22412109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
22512109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
22612109SRekai.GonzalezAlberquilla@arm.com        return thread->getWritableVecReg(reg);
22712109SRekai.GonzalezAlberquilla@arm.com    }
22812109SRekai.GonzalezAlberquilla@arm.com
22912109SRekai.GonzalezAlberquilla@arm.com    /** Vector Register Lane Interfaces. */
23012109SRekai.GonzalezAlberquilla@arm.com    /** @{ */
23112109SRekai.GonzalezAlberquilla@arm.com    /** Reads source vector 8bit operand. */
23212109SRekai.GonzalezAlberquilla@arm.com    virtual ConstVecLane8
23313557Sgabeblack@google.com    readVec8BitLaneOperand(const StaticInst *si, int idx) const override
23412109SRekai.GonzalezAlberquilla@arm.com    {
23512109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
23612109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
23712109SRekai.GonzalezAlberquilla@arm.com        return thread->readVec8BitLaneReg(reg);
23812109SRekai.GonzalezAlberquilla@arm.com    }
23912109SRekai.GonzalezAlberquilla@arm.com
24012109SRekai.GonzalezAlberquilla@arm.com    /** Reads source vector 16bit operand. */
24112109SRekai.GonzalezAlberquilla@arm.com    virtual ConstVecLane16
24213557Sgabeblack@google.com    readVec16BitLaneOperand(const StaticInst *si, int idx) const override
24312109SRekai.GonzalezAlberquilla@arm.com    {
24412109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
24512109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
24612109SRekai.GonzalezAlberquilla@arm.com        return thread->readVec16BitLaneReg(reg);
24712109SRekai.GonzalezAlberquilla@arm.com    }
24812109SRekai.GonzalezAlberquilla@arm.com
24912109SRekai.GonzalezAlberquilla@arm.com    /** Reads source vector 32bit operand. */
25012109SRekai.GonzalezAlberquilla@arm.com    virtual ConstVecLane32
25113557Sgabeblack@google.com    readVec32BitLaneOperand(const StaticInst *si, int idx) const override
25212109SRekai.GonzalezAlberquilla@arm.com    {
25312109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
25412109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
25512109SRekai.GonzalezAlberquilla@arm.com        return thread->readVec32BitLaneReg(reg);
25612109SRekai.GonzalezAlberquilla@arm.com    }
25712109SRekai.GonzalezAlberquilla@arm.com
25812109SRekai.GonzalezAlberquilla@arm.com    /** Reads source vector 64bit operand. */
25912109SRekai.GonzalezAlberquilla@arm.com    virtual ConstVecLane64
26013557Sgabeblack@google.com    readVec64BitLaneOperand(const StaticInst *si, int idx) const override
26112109SRekai.GonzalezAlberquilla@arm.com    {
26212109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
26312109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
26412109SRekai.GonzalezAlberquilla@arm.com        return thread->readVec64BitLaneReg(reg);
26512109SRekai.GonzalezAlberquilla@arm.com    }
26612109SRekai.GonzalezAlberquilla@arm.com
26712109SRekai.GonzalezAlberquilla@arm.com    /** Write a lane of the destination vector operand. */
26812109SRekai.GonzalezAlberquilla@arm.com    template <typename LD>
26912109SRekai.GonzalezAlberquilla@arm.com    void
27012109SRekai.GonzalezAlberquilla@arm.com    setVecLaneOperandT(const StaticInst *si, int idx, const LD& val)
27112109SRekai.GonzalezAlberquilla@arm.com    {
27212109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
27312109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
27412109SRekai.GonzalezAlberquilla@arm.com        return thread->setVecLane(reg, val);
27512109SRekai.GonzalezAlberquilla@arm.com    }
27612109SRekai.GonzalezAlberquilla@arm.com    virtual void
27712109SRekai.GonzalezAlberquilla@arm.com    setVecLaneOperand(const StaticInst *si, int idx,
27812109SRekai.GonzalezAlberquilla@arm.com            const LaneData<LaneSize::Byte>& val) override
27912109SRekai.GonzalezAlberquilla@arm.com    {
28012109SRekai.GonzalezAlberquilla@arm.com        setVecLaneOperandT(si, idx, val);
28112109SRekai.GonzalezAlberquilla@arm.com    }
28212109SRekai.GonzalezAlberquilla@arm.com    virtual void
28312109SRekai.GonzalezAlberquilla@arm.com    setVecLaneOperand(const StaticInst *si, int idx,
28412109SRekai.GonzalezAlberquilla@arm.com            const LaneData<LaneSize::TwoByte>& val) override
28512109SRekai.GonzalezAlberquilla@arm.com    {
28612109SRekai.GonzalezAlberquilla@arm.com        setVecLaneOperandT(si, idx, val);
28712109SRekai.GonzalezAlberquilla@arm.com    }
28812109SRekai.GonzalezAlberquilla@arm.com    virtual void
28912109SRekai.GonzalezAlberquilla@arm.com    setVecLaneOperand(const StaticInst *si, int idx,
29012109SRekai.GonzalezAlberquilla@arm.com            const LaneData<LaneSize::FourByte>& val) override
29112109SRekai.GonzalezAlberquilla@arm.com    {
29212109SRekai.GonzalezAlberquilla@arm.com        setVecLaneOperandT(si, idx, val);
29312109SRekai.GonzalezAlberquilla@arm.com    }
29412109SRekai.GonzalezAlberquilla@arm.com    virtual void
29512109SRekai.GonzalezAlberquilla@arm.com    setVecLaneOperand(const StaticInst *si, int idx,
29612109SRekai.GonzalezAlberquilla@arm.com            const LaneData<LaneSize::EightByte>& val) override
29712109SRekai.GonzalezAlberquilla@arm.com    {
29812109SRekai.GonzalezAlberquilla@arm.com        setVecLaneOperandT(si, idx, val);
29912109SRekai.GonzalezAlberquilla@arm.com    }
30012109SRekai.GonzalezAlberquilla@arm.com    /** @} */
30112109SRekai.GonzalezAlberquilla@arm.com
30213557Sgabeblack@google.com    VecElem
30313557Sgabeblack@google.com    readVecElemOperand(const StaticInst *si, int idx) const override
30412109SRekai.GonzalezAlberquilla@arm.com    {
30512109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->srcRegIdx(idx);
30612109SRekai.GonzalezAlberquilla@arm.com        return thread->readVecElem(reg);
30712109SRekai.GonzalezAlberquilla@arm.com    }
30812109SRekai.GonzalezAlberquilla@arm.com
30913610Sgiacomo.gabrielli@arm.com    const VecPredRegContainer&
31013610Sgiacomo.gabrielli@arm.com    readVecPredRegOperand(const StaticInst *si, int idx) const override
31113610Sgiacomo.gabrielli@arm.com    {
31213610Sgiacomo.gabrielli@arm.com        const RegId& reg = si->srcRegIdx(idx);
31313610Sgiacomo.gabrielli@arm.com        assert(reg.isVecPredReg());
31413610Sgiacomo.gabrielli@arm.com        return thread->readVecPredReg(reg);
31513610Sgiacomo.gabrielli@arm.com    }
31613610Sgiacomo.gabrielli@arm.com
31713610Sgiacomo.gabrielli@arm.com    VecPredRegContainer&
31813610Sgiacomo.gabrielli@arm.com    getWritableVecPredRegOperand(const StaticInst *si, int idx) override
31913610Sgiacomo.gabrielli@arm.com    {
32013610Sgiacomo.gabrielli@arm.com        const RegId& reg = si->destRegIdx(idx);
32113610Sgiacomo.gabrielli@arm.com        assert(reg.isVecPredReg());
32213610Sgiacomo.gabrielli@arm.com        return thread->getWritableVecPredReg(reg);
32313610Sgiacomo.gabrielli@arm.com    }
32413610Sgiacomo.gabrielli@arm.com
32513622Sgabeblack@google.com    RegVal
32613557Sgabeblack@google.com    readCCRegOperand(const StaticInst *si, int idx) override
3279920Syasuko.eckert@amd.com    {
32812106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->srcRegIdx(idx);
32912106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isCCReg());
33012106SRekai.GonzalezAlberquilla@arm.com        return thread->readCCReg(reg.index());
3319920Syasuko.eckert@amd.com    }
3329920Syasuko.eckert@amd.com
33312107SRekai.GonzalezAlberquilla@arm.com    template<typename T>
33413557Sgabeblack@google.com    void
33513557Sgabeblack@google.com    setScalarResult(T&& t)
3368733Sgeoffrey.blake@arm.com    {
33712107SRekai.GonzalezAlberquilla@arm.com        result.push(InstResult(std::forward<T>(t),
33813557Sgabeblack@google.com                               InstResult::ResultType::Scalar));
3398733Sgeoffrey.blake@arm.com    }
3408733Sgeoffrey.blake@arm.com
34112109SRekai.GonzalezAlberquilla@arm.com    template<typename T>
34213557Sgabeblack@google.com    void
34313557Sgabeblack@google.com    setVecResult(T&& t)
34412109SRekai.GonzalezAlberquilla@arm.com    {
34512109SRekai.GonzalezAlberquilla@arm.com        result.push(InstResult(std::forward<T>(t),
34613557Sgabeblack@google.com                               InstResult::ResultType::VecReg));
34712109SRekai.GonzalezAlberquilla@arm.com    }
34812109SRekai.GonzalezAlberquilla@arm.com
34912109SRekai.GonzalezAlberquilla@arm.com    template<typename T>
35013557Sgabeblack@google.com    void
35113557Sgabeblack@google.com    setVecElemResult(T&& t)
35212109SRekai.GonzalezAlberquilla@arm.com    {
35312109SRekai.GonzalezAlberquilla@arm.com        result.push(InstResult(std::forward<T>(t),
35413557Sgabeblack@google.com                               InstResult::ResultType::VecElem));
35512109SRekai.GonzalezAlberquilla@arm.com    }
35612109SRekai.GonzalezAlberquilla@arm.com
35713610Sgiacomo.gabrielli@arm.com    template<typename T>
35813610Sgiacomo.gabrielli@arm.com    void
35913610Sgiacomo.gabrielli@arm.com    setVecPredResult(T&& t)
36013610Sgiacomo.gabrielli@arm.com    {
36113610Sgiacomo.gabrielli@arm.com        result.push(InstResult(std::forward<T>(t),
36213610Sgiacomo.gabrielli@arm.com                               InstResult::ResultType::VecPredReg));
36313610Sgiacomo.gabrielli@arm.com    }
36413610Sgiacomo.gabrielli@arm.com
36513557Sgabeblack@google.com    void
36613557Sgabeblack@google.com    setIntRegOperand(const StaticInst *si, int idx, RegVal val) override
3672315SN/A    {
36812106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
36912106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isIntReg());
37012106SRekai.GonzalezAlberquilla@arm.com        thread->setIntReg(reg.index(), val);
37112107SRekai.GonzalezAlberquilla@arm.com        setScalarResult(val);
3722315SN/A    }
3732315SN/A
37413557Sgabeblack@google.com    void
37513557Sgabeblack@google.com    setFloatRegOperandBits(const StaticInst *si, int idx, RegVal val) override
3762315SN/A    {
37712106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
37812106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isFloatReg());
37913611Sgabeblack@google.com        thread->setFloatReg(reg.index(), val);
38012107SRekai.GonzalezAlberquilla@arm.com        setScalarResult(val);
3812315SN/A    }
3822315SN/A
38313557Sgabeblack@google.com    void
38413622Sgabeblack@google.com    setCCRegOperand(const StaticInst *si, int idx, RegVal val) override
3859920Syasuko.eckert@amd.com    {
38612106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
38712106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isCCReg());
38812106SRekai.GonzalezAlberquilla@arm.com        thread->setCCReg(reg.index(), val);
38912107SRekai.GonzalezAlberquilla@arm.com        setScalarResult((uint64_t)val);
3909920Syasuko.eckert@amd.com    }
3919920Syasuko.eckert@amd.com
39213557Sgabeblack@google.com    void
39313557Sgabeblack@google.com    setVecRegOperand(const StaticInst *si, int idx,
39413557Sgabeblack@google.com                     const VecRegContainer& val) override
39512109SRekai.GonzalezAlberquilla@arm.com    {
39612109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
39712109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecReg());
39812109SRekai.GonzalezAlberquilla@arm.com        thread->setVecReg(reg, val);
39912109SRekai.GonzalezAlberquilla@arm.com        setVecResult(val);
40012109SRekai.GonzalezAlberquilla@arm.com    }
40112109SRekai.GonzalezAlberquilla@arm.com
40213557Sgabeblack@google.com    void
40313557Sgabeblack@google.com    setVecElemOperand(const StaticInst *si, int idx,
40413557Sgabeblack@google.com                      const VecElem val) override
40512109SRekai.GonzalezAlberquilla@arm.com    {
40612109SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
40712109SRekai.GonzalezAlberquilla@arm.com        assert(reg.isVecElem());
40812109SRekai.GonzalezAlberquilla@arm.com        thread->setVecElem(reg, val);
40912109SRekai.GonzalezAlberquilla@arm.com        setVecElemResult(val);
41012109SRekai.GonzalezAlberquilla@arm.com    }
41112109SRekai.GonzalezAlberquilla@arm.com
41213610Sgiacomo.gabrielli@arm.com    void setVecPredRegOperand(const StaticInst *si, int idx,
41313610Sgiacomo.gabrielli@arm.com                              const VecPredRegContainer& val) override
41413610Sgiacomo.gabrielli@arm.com    {
41513610Sgiacomo.gabrielli@arm.com        const RegId& reg = si->destRegIdx(idx);
41613610Sgiacomo.gabrielli@arm.com        assert(reg.isVecPredReg());
41713610Sgiacomo.gabrielli@arm.com        thread->setVecPredReg(reg, val);
41813610Sgiacomo.gabrielli@arm.com        setVecPredResult(val);
41913610Sgiacomo.gabrielli@arm.com    }
42013610Sgiacomo.gabrielli@arm.com
42113429Srekai.gonzalezalberquilla@arm.com    bool readPredicate() const override { return thread->readPredicate(); }
42213429Srekai.gonzalezalberquilla@arm.com
42313557Sgabeblack@google.com    void
42413557Sgabeblack@google.com    setPredicate(bool val) override
4258733Sgeoffrey.blake@arm.com    {
4268733Sgeoffrey.blake@arm.com        thread->setPredicate(val);
4278733Sgeoffrey.blake@arm.com    }
4282669Sktlim@umich.edu
42913953Sgiacomo.gabrielli@arm.com    bool
43013953Sgiacomo.gabrielli@arm.com    readMemAccPredicate() const override
43113953Sgiacomo.gabrielli@arm.com    {
43213953Sgiacomo.gabrielli@arm.com        return thread->readMemAccPredicate();
43313953Sgiacomo.gabrielli@arm.com    }
43413953Sgiacomo.gabrielli@arm.com
43513953Sgiacomo.gabrielli@arm.com    void
43613953Sgiacomo.gabrielli@arm.com    setMemAccPredicate(bool val) override
43713953Sgiacomo.gabrielli@arm.com    {
43813953Sgiacomo.gabrielli@arm.com        thread->setMemAccPredicate(val);
43913953Sgiacomo.gabrielli@arm.com    }
44013953Sgiacomo.gabrielli@arm.com
44111169Sandreas.hansson@arm.com    TheISA::PCState pcState() const override { return thread->pcState(); }
44213557Sgabeblack@google.com    void
44313557Sgabeblack@google.com    pcState(const TheISA::PCState &val) override
4448733Sgeoffrey.blake@arm.com    {
4458733Sgeoffrey.blake@arm.com        DPRINTF(Checker, "Changing PC to %s, old PC %s.\n",
4468733Sgeoffrey.blake@arm.com                         val, thread->pcState());
4478733Sgeoffrey.blake@arm.com        thread->pcState(val);
4488733Sgeoffrey.blake@arm.com    }
4498733Sgeoffrey.blake@arm.com    Addr instAddr() { return thread->instAddr(); }
4508733Sgeoffrey.blake@arm.com    Addr nextInstAddr() { return thread->nextInstAddr(); }
4518733Sgeoffrey.blake@arm.com    MicroPC microPC() { return thread->microPC(); }
4528733Sgeoffrey.blake@arm.com    //////////////////////////////////////////
4532315SN/A
45413557Sgabeblack@google.com    RegVal
45513557Sgabeblack@google.com    readMiscRegNoEffect(int misc_reg) const
4564172Ssaidi@eecs.umich.edu    {
4574172Ssaidi@eecs.umich.edu        return thread->readMiscRegNoEffect(misc_reg);
4584172Ssaidi@eecs.umich.edu    }
4594172Ssaidi@eecs.umich.edu
46013557Sgabeblack@google.com    RegVal
46113557Sgabeblack@google.com    readMiscReg(int misc_reg) override
4622315SN/A    {
4632683Sktlim@umich.edu        return thread->readMiscReg(misc_reg);
4642315SN/A    }
4652315SN/A
46613557Sgabeblack@google.com    void
46713582Sgabeblack@google.com    setMiscRegNoEffect(int misc_reg, RegVal val)
4682315SN/A    {
46913557Sgabeblack@google.com        DPRINTF(Checker, "Setting misc reg %d with no effect to check later\n",
47013557Sgabeblack@google.com                misc_reg);
4714172Ssaidi@eecs.umich.edu        miscRegIdxs.push(misc_reg);
4724172Ssaidi@eecs.umich.edu        return thread->setMiscRegNoEffect(misc_reg, val);
4732315SN/A    }
4742315SN/A
47513557Sgabeblack@google.com    void
47613582Sgabeblack@google.com    setMiscReg(int misc_reg, RegVal val) override
4772315SN/A    {
47813557Sgabeblack@google.com        DPRINTF(Checker, "Setting misc reg %d with effect to check later\n",
47913557Sgabeblack@google.com                misc_reg);
4802315SN/A        miscRegIdxs.push(misc_reg);
4812683Sktlim@umich.edu        return thread->setMiscReg(misc_reg, val);
4822315SN/A    }
4832315SN/A
48413557Sgabeblack@google.com    RegVal
48513557Sgabeblack@google.com    readMiscRegOperand(const StaticInst *si, int idx) override
4868733Sgeoffrey.blake@arm.com    {
48712106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->srcRegIdx(idx);
48812106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isMiscReg());
48912106SRekai.GonzalezAlberquilla@arm.com        return thread->readMiscReg(reg.index());
4908733Sgeoffrey.blake@arm.com    }
4918733Sgeoffrey.blake@arm.com
49213557Sgabeblack@google.com    void
49313582Sgabeblack@google.com    setMiscRegOperand(const StaticInst *si, int idx, RegVal val) override
4948733Sgeoffrey.blake@arm.com    {
49512106SRekai.GonzalezAlberquilla@arm.com        const RegId& reg = si->destRegIdx(idx);
49612106SRekai.GonzalezAlberquilla@arm.com        assert(reg.isMiscReg());
49712106SRekai.GonzalezAlberquilla@arm.com        return this->setMiscReg(reg.index(), val);
4988733Sgeoffrey.blake@arm.com    }
4998888Sgeoffrey.blake@arm.com
5008733Sgeoffrey.blake@arm.com    /////////////////////////////////////////
5018733Sgeoffrey.blake@arm.com
50213557Sgabeblack@google.com    void
50313557Sgabeblack@google.com    recordPCChange(const TheISA::PCState &val)
5048733Sgeoffrey.blake@arm.com    {
5058733Sgeoffrey.blake@arm.com       changedPC = true;
5068733Sgeoffrey.blake@arm.com       newPCState = val;
5078733Sgeoffrey.blake@arm.com    }
5082315SN/A
50913557Sgabeblack@google.com    void
51013557Sgabeblack@google.com    demapPage(Addr vaddr, uint64_t asn) override
5115358Sgblack@eecs.umich.edu    {
5125358Sgblack@eecs.umich.edu        this->itb->demapPage(vaddr, asn);
5135358Sgblack@eecs.umich.edu        this->dtb->demapPage(vaddr, asn);
5145358Sgblack@eecs.umich.edu    }
5155358Sgblack@eecs.umich.edu
51610529Smorr@cs.wisc.edu    // monitor/mwait funtions
51713557Sgabeblack@google.com    void armMonitor(Addr address) override { BaseCPU::armMonitor(0, address); }
51811169Sandreas.hansson@arm.com    bool mwait(PacketPtr pkt) override { return BaseCPU::mwait(0, pkt); }
51911169Sandreas.hansson@arm.com    void mwaitAtomic(ThreadContext *tc) override
52011148Smitch.hayenga@arm.com    { return BaseCPU::mwaitAtomic(0, tc, thread->dtb); }
52111169Sandreas.hansson@arm.com    AddressMonitor *getAddrMonitor() override
52211169Sandreas.hansson@arm.com    { return BaseCPU::getCpuAddrMonitor(0); }
52310529Smorr@cs.wisc.edu
52413557Sgabeblack@google.com    void
52513557Sgabeblack@google.com    demapInstPage(Addr vaddr, uint64_t asn)
5265358Sgblack@eecs.umich.edu    {
5275358Sgblack@eecs.umich.edu        this->itb->demapPage(vaddr, asn);
5285358Sgblack@eecs.umich.edu    }
5295358Sgblack@eecs.umich.edu
53013557Sgabeblack@google.com    void
53113557Sgabeblack@google.com    demapDataPage(Addr vaddr, uint64_t asn)
5325358Sgblack@eecs.umich.edu    {
5335358Sgblack@eecs.umich.edu        this->dtb->demapPage(vaddr, asn);
5345358Sgblack@eecs.umich.edu    }
5355358Sgblack@eecs.umich.edu
53613954Sgiacomo.gabrielli@arm.com    /**
53713954Sgiacomo.gabrielli@arm.com     * Helper function used to generate the request for a single fragment of a
53813954Sgiacomo.gabrielli@arm.com     * memory access.
53913954Sgiacomo.gabrielli@arm.com     *
54013954Sgiacomo.gabrielli@arm.com     * Takes care of setting up the appropriate byte-enable mask for the
54113954Sgiacomo.gabrielli@arm.com     * fragment, given the mask for the entire memory access.
54213954Sgiacomo.gabrielli@arm.com     *
54313954Sgiacomo.gabrielli@arm.com     * @param frag_addr Start address of the fragment.
54413954Sgiacomo.gabrielli@arm.com     * @param size Total size of the memory access in bytes.
54513954Sgiacomo.gabrielli@arm.com     * @param flags Request flags.
54613954Sgiacomo.gabrielli@arm.com     * @param byte_enable Byte-enable mask for the entire memory access.
54713954Sgiacomo.gabrielli@arm.com     * @param[out] frag_size Fragment size.
54813954Sgiacomo.gabrielli@arm.com     * @param[in,out] size_left Size left to be processed in the memory access.
54913954Sgiacomo.gabrielli@arm.com     * @return Pointer to the allocated Request, nullptr if the byte-enable
55013954Sgiacomo.gabrielli@arm.com     * mask is all-false for the fragment.
55113954Sgiacomo.gabrielli@arm.com     */
55213954Sgiacomo.gabrielli@arm.com    RequestPtr genMemFragmentRequest(Addr frag_addr, int size,
55313954Sgiacomo.gabrielli@arm.com                                     Request::Flags flags,
55413954Sgiacomo.gabrielli@arm.com                                     const std::vector<bool>& byte_enable,
55513954Sgiacomo.gabrielli@arm.com                                     int& frag_size, int& size_left) const;
55613954Sgiacomo.gabrielli@arm.com
55711169Sandreas.hansson@arm.com    Fault readMem(Addr addr, uint8_t *data, unsigned size,
55813954Sgiacomo.gabrielli@arm.com                  Request::Flags flags,
55913954Sgiacomo.gabrielli@arm.com                  const std::vector<bool>& byteEnable = std::vector<bool>())
56013954Sgiacomo.gabrielli@arm.com        override;
56113652Sqtt2@cornell.edu
56211608Snikos.nikoleris@arm.com    Fault writeMem(uint8_t *data, unsigned size, Addr addr,
56313954Sgiacomo.gabrielli@arm.com                   Request::Flags flags, uint64_t *res,
56413954Sgiacomo.gabrielli@arm.com                   const std::vector<bool>& byteEnable = std::vector<bool>())
56513954Sgiacomo.gabrielli@arm.com        override;
5668733Sgeoffrey.blake@arm.com
56713652Sqtt2@cornell.edu    Fault amoMem(Addr addr, uint8_t* data, unsigned size,
56814297Sjordi.vaquero@metempsy.com                 Request::Flags flags, AtomicOpFunctorPtr amo_op) override
56913652Sqtt2@cornell.edu    {
57013652Sqtt2@cornell.edu        panic("AMO is not supported yet in CPU checker\n");
57113652Sqtt2@cornell.edu    }
57213652Sqtt2@cornell.edu
57313557Sgabeblack@google.com    unsigned int
57413557Sgabeblack@google.com    readStCondFailures() const override {
57510319SAndreas.Sandberg@ARM.com        return thread->readStCondFailures();
57610319SAndreas.Sandberg@ARM.com    }
57710319SAndreas.Sandberg@ARM.com
57813557Sgabeblack@google.com    void setStCondFailures(unsigned int sc_failures) override {}
5798733Sgeoffrey.blake@arm.com    /////////////////////////////////////////////////////
5808733Sgeoffrey.blake@arm.com
58111168Sandreas.hansson@arm.com    void wakeup(ThreadID tid) override { }
5822315SN/A    // Assume that the normal CPU's call to syscall was successful.
5832332SN/A    // The checker's state would have already been updated by the syscall.
58411877Sbrandon.potter@amd.com    void syscall(int64_t callnum, Fault *fault) override { }
5852315SN/A
58613557Sgabeblack@google.com    void
58713557Sgabeblack@google.com    handleError()
5882315SN/A    {
5892315SN/A        if (exitOnError)
5902732Sktlim@umich.edu            dumpAndExit();
5912315SN/A    }
5922732Sktlim@umich.edu
59312749Sgiacomo.travaglini@arm.com    bool checkFlags(const RequestPtr &unverified_req, Addr vAddr,
5948733Sgeoffrey.blake@arm.com                    Addr pAddr, int flags);
5952315SN/A
5962732Sktlim@umich.edu    void dumpAndExit();
5972732Sktlim@umich.edu
59811169Sandreas.hansson@arm.com    ThreadContext *tcBase() override { return tc; }
5992683Sktlim@umich.edu    SimpleThread *threadBase() { return thread; }
6002315SN/A
60112107SRekai.GonzalezAlberquilla@arm.com    InstResult unverifiedResult;
60212748Sgiacomo.travaglini@arm.com    RequestPtr unverifiedReq;
6032679Sktlim@umich.edu    uint8_t *unverifiedMemData;
6042315SN/A
6052315SN/A    bool changedPC;
6062315SN/A    bool willChangePC;
6078733Sgeoffrey.blake@arm.com    TheISA::PCState newPCState;
6082315SN/A    bool exitOnError;
6092354SN/A    bool updateOnError;
6102732Sktlim@umich.edu    bool warnOnlyOnLoadError;
6112315SN/A
6122315SN/A    InstSeqNum youngestSN;
6132315SN/A};
6142315SN/A
6152350SN/A/**
6162350SN/A * Templated Checker class.  This Checker class is templated on the
6172350SN/A * DynInstPtr of the instruction type that will be verified.  Proper
6182350SN/A * template instantiations of the Checker must be placed at the bottom
6192350SN/A * of checker/cpu.cc.
6202350SN/A */
6218733Sgeoffrey.blake@arm.comtemplate <class Impl>
6222315SN/Aclass Checker : public CheckerCPU
6232315SN/A{
6248733Sgeoffrey.blake@arm.com  private:
6258733Sgeoffrey.blake@arm.com    typedef typename Impl::DynInstPtr DynInstPtr;
6268733Sgeoffrey.blake@arm.com
6272315SN/A  public:
6282315SN/A    Checker(Params *p)
6299023Sgblack@eecs.umich.edu        : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
6302315SN/A    { }
6312315SN/A
6322840Sktlim@umich.edu    void switchOut();
6332315SN/A    void takeOverFrom(BaseCPU *oldCPU);
6342315SN/A
63510379Sandreas.hansson@arm.com    void advancePC(const Fault &fault);
6368733Sgeoffrey.blake@arm.com
63713429Srekai.gonzalezalberquilla@arm.com    void verify(const DynInstPtr &inst);
6382315SN/A
63913429Srekai.gonzalezalberquilla@arm.com    void validateInst(const DynInstPtr &inst);
64013429Srekai.gonzalezalberquilla@arm.com    void validateExecution(const DynInstPtr &inst);
6412315SN/A    void validateState();
6422315SN/A
64313429Srekai.gonzalezalberquilla@arm.com    void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
64412107SRekai.GonzalezAlberquilla@arm.com                    int start_idx);
6458733Sgeoffrey.blake@arm.com    void handlePendingInt();
6462732Sktlim@umich.edu
6472732Sktlim@umich.edu  private:
64813429Srekai.gonzalezalberquilla@arm.com    void handleError(const DynInstPtr &inst)
6492732Sktlim@umich.edu    {
6502360SN/A        if (exitOnError) {
6512732Sktlim@umich.edu            dumpAndExit(inst);
6522360SN/A        } else if (updateOnError) {
6532354SN/A            updateThisCycle = true;
6542360SN/A        }
6552732Sktlim@umich.edu    }
6562732Sktlim@umich.edu
65713429Srekai.gonzalezalberquilla@arm.com    void dumpAndExit(const DynInstPtr &inst);
6582732Sktlim@umich.edu
6592354SN/A    bool updateThisCycle;
6602354SN/A
6612354SN/A    DynInstPtr unverifiedInst;
6622354SN/A
6632315SN/A    std::list<DynInstPtr> instList;
6642315SN/A    typedef typename std::list<DynInstPtr>::iterator InstListIt;
6652315SN/A    void dumpInsts();
6662315SN/A};
6672315SN/A
6682315SN/A#endif // __CPU_CHECKER_CPU_HH__
669