base_dyn_inst.hh revision 2632
11060SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31060SN/A * All rights reserved.
41060SN/A *
51060SN/A * Redistribution and use in source and binary forms, with or without
61060SN/A * modification, are permitted provided that the following conditions are
71060SN/A * met: redistributions of source code must retain the above copyright
81060SN/A * notice, this list of conditions and the following disclaimer;
91060SN/A * redistributions in binary form must reproduce the above copyright
101060SN/A * notice, this list of conditions and the following disclaimer in the
111060SN/A * documentation and/or other materials provided with the distribution;
121060SN/A * neither the name of the copyright holders nor the names of its
131060SN/A * contributors may be used to endorse or promote products derived from
141060SN/A * this software without specific prior written permission.
151060SN/A *
161060SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171060SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181060SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201060SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211060SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231060SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241060SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261060SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271060SN/A */
281060SN/A
291464SN/A#ifndef __CPU_BASE_DYN_INST_HH__
301464SN/A#define __CPU_BASE_DYN_INST_HH__
311060SN/A
321464SN/A#include <string>
331060SN/A#include <vector>
341060SN/A
351060SN/A#include "base/fast_alloc.hh"
361060SN/A#include "base/trace.hh"
371858SN/A#include "config/full_system.hh"
381464SN/A#include "cpu/exetrace.hh"
391464SN/A#include "cpu/inst_seq.hh"
401717SN/A#include "cpu/o3/comm.hh"
411060SN/A#include "cpu/static_inst.hh"
421717SN/A#include "encumbered/cpu/full/bpred_update.hh"
431717SN/A#include "encumbered/cpu/full/op_class.hh"
441717SN/A#include "encumbered/cpu/full/spec_memory.hh"
451717SN/A#include "encumbered/cpu/full/spec_state.hh"
461717SN/A#include "encumbered/mem/functional/main.hh"
471060SN/A
481060SN/A/**
491060SN/A * @file
501060SN/A * Defines a dynamic instruction context.
511060SN/A */
521060SN/A
531061SN/A// Forward declaration.
541061SN/Aclass StaticInstPtr;
551060SN/A
561060SN/Atemplate <class Impl>
571061SN/Aclass BaseDynInst : public FastAlloc, public RefCounted
581060SN/A{
591060SN/A  public:
601060SN/A    // Typedef for the CPU.
611060SN/A    typedef typename Impl::FullCPU FullCPU;
621060SN/A
631060SN/A    /// Binary machine instruction type.
642107SN/A    typedef TheISA::MachInst MachInst;
651060SN/A    /// Logical register index type.
662107SN/A    typedef TheISA::RegIndex RegIndex;
671060SN/A    /// Integer register index type.
682107SN/A    typedef TheISA::IntReg IntReg;
691060SN/A
701060SN/A    enum {
712107SN/A        MaxInstSrcRegs = TheISA::MaxInstSrcRegs,        //< Max source regs
722107SN/A        MaxInstDestRegs = TheISA::MaxInstDestRegs,      //< Max dest regs
731060SN/A    };
741060SN/A
751684SN/A    /** The static inst used by this dyn inst. */
762107SN/A    StaticInstPtr staticInst;
771060SN/A
781060SN/A    ////////////////////////////////////////////
791060SN/A    //
801060SN/A    // INSTRUCTION EXECUTION
811060SN/A    //
821060SN/A    ////////////////////////////////////////////
831060SN/A    Trace::InstRecord *traceData;
841060SN/A
851060SN/A    template <class T>
862132SN/A    Fault read(Addr addr, T &data, unsigned flags);
871060SN/A
881060SN/A    template <class T>
892132SN/A    Fault write(T data, Addr addr, unsigned flags,
901060SN/A                        uint64_t *res);
911060SN/A
921060SN/A    void prefetch(Addr addr, unsigned flags);
931060SN/A    void writeHint(Addr addr, int size, unsigned flags);
942132SN/A    Fault copySrcTranslate(Addr src);
952132SN/A    Fault copy(Addr dest);
961060SN/A
971684SN/A    /** @todo: Consider making this private. */
981060SN/A  public:
991060SN/A    /** Is this instruction valid. */
1001060SN/A    bool valid;
1011060SN/A
1021060SN/A    /** The sequence number of the instruction. */
1031060SN/A    InstSeqNum seqNum;
1041060SN/A
1051060SN/A    /** How many source registers are ready. */
1061060SN/A    unsigned readyRegs;
1071060SN/A
1081464SN/A    /** Is the instruction completed. */
1091464SN/A    bool completed;
1101464SN/A
1111060SN/A    /** Can this instruction issue. */
1121060SN/A    bool canIssue;
1131060SN/A
1141060SN/A    /** Has this instruction issued. */
1151060SN/A    bool issued;
1161060SN/A
1171060SN/A    /** Has this instruction executed (or made it through execute) yet. */
1181060SN/A    bool executed;
1191060SN/A
1201060SN/A    /** Can this instruction commit. */
1211060SN/A    bool canCommit;
1221060SN/A
1231060SN/A    /** Is this instruction squashed. */
1241060SN/A    bool squashed;
1251060SN/A
1261060SN/A    /** Is this instruction squashed in the instruction queue. */
1271060SN/A    bool squashedInIQ;
1281060SN/A
1291060SN/A    /** Is this a recover instruction. */
1301060SN/A    bool recoverInst;
1311060SN/A
1321060SN/A    /** Is this a thread blocking instruction. */
1331060SN/A    bool blockingInst;	/* this inst has called thread_block() */
1341060SN/A
1351060SN/A    /** Is this a thread syncrhonization instruction. */
1361060SN/A    bool threadsyncWait;
1371060SN/A
1381060SN/A    /** The thread this instruction is from. */
1391060SN/A    short threadNumber;
1401060SN/A
1411060SN/A    /** data address space ID, for loads & stores. */
1421060SN/A    short asid;
1431060SN/A
1441060SN/A    /** Pointer to the FullCPU object. */
1451060SN/A    FullCPU *cpu;
1461060SN/A
1471060SN/A    /** Pointer to the exec context.  Will not exist in the final version. */
1482190SN/A    CPUExecContext *cpuXC;
1491060SN/A
1501060SN/A    /** The kind of fault this instruction has generated. */
1512132SN/A    Fault fault;
1521060SN/A
1531060SN/A    /** The effective virtual address (lds & stores only). */
1541060SN/A    Addr effAddr;
1551060SN/A
1561060SN/A    /** The effective physical address. */
1571060SN/A    Addr physEffAddr;
1581060SN/A
1591060SN/A    /** Effective virtual address for a copy source. */
1601060SN/A    Addr copySrcEffAddr;
1611060SN/A
1621060SN/A    /** Effective physical address for a copy source. */
1631060SN/A    Addr copySrcPhysEffAddr;
1641060SN/A
1651060SN/A    /** The memory request flags (from translation). */
1661060SN/A    unsigned memReqFlags;
1671060SN/A
1681060SN/A    /** The size of the data to be stored. */
1691060SN/A    int storeSize;
1701060SN/A
1711060SN/A    /** The data to be stored. */
1721060SN/A    IntReg storeData;
1731060SN/A
1741464SN/A    union Result {
1751464SN/A        uint64_t integer;
1761464SN/A        float fp;
1771464SN/A        double dbl;
1781464SN/A    };
1791060SN/A
1801464SN/A    /** The result of the instruction; assumes for now that there's only one
1811464SN/A     *  destination register.
1821464SN/A     */
1831464SN/A    Result instResult;
1841060SN/A
1851060SN/A    /** PC of this instruction. */
1861060SN/A    Addr PC;
1871060SN/A
1881060SN/A    /** Next non-speculative PC.  It is not filled in at fetch, but rather
1891060SN/A     *  once the target of the branch is truly known (either decode or
1901060SN/A     *  execute).
1911060SN/A     */
1921060SN/A    Addr nextPC;
1931060SN/A
1941060SN/A    /** Predicted next PC. */
1951060SN/A    Addr predPC;
1961060SN/A
1971060SN/A    /** Count of total number of dynamic instructions. */
1981060SN/A    static int instcount;
1991060SN/A
2001464SN/A    /** Whether or not the source register is ready.  Not sure this should be
2011464SN/A     *  here vs. the derived class.
2021060SN/A     */
2031060SN/A    bool _readySrcRegIdx[MaxInstSrcRegs];
2041060SN/A
2051060SN/A  public:
2061060SN/A    /** BaseDynInst constructor given a binary instruction. */
2071060SN/A    BaseDynInst(MachInst inst, Addr PC, Addr Pred_PC, InstSeqNum seq_num,
2081060SN/A                FullCPU *cpu);
2091060SN/A
2101060SN/A    /** BaseDynInst constructor given a static inst pointer. */
2112107SN/A    BaseDynInst(StaticInstPtr &_staticInst);
2121060SN/A
2131060SN/A    /** BaseDynInst destructor. */
2141060SN/A    ~BaseDynInst();
2151060SN/A
2161464SN/A  private:
2171684SN/A    /** Function to initialize variables in the constructors. */
2181464SN/A    void initVars();
2191060SN/A
2201464SN/A  public:
2211060SN/A    void
2222132SN/A    trace_mem(Fault fault,      // last fault
2231060SN/A              MemCmd cmd,       // last command
2241060SN/A              Addr addr,        // virtual address of access
2251060SN/A              void *p,          // memory accessed
2261060SN/A              int nbytes);      // access size
2271060SN/A
2281060SN/A    /** Dumps out contents of this BaseDynInst. */
2291060SN/A    void dump();
2301060SN/A
2311060SN/A    /** Dumps out contents of this BaseDynInst into given string. */
2321060SN/A    void dump(std::string &outstring);
2331060SN/A
2341060SN/A    /** Returns the fault type. */
2352132SN/A    Fault getFault() { return fault; }
2361060SN/A
2371060SN/A    /** Checks whether or not this instruction has had its branch target
2381060SN/A     *  calculated yet.  For now it is not utilized and is hacked to be
2391060SN/A     *  always false.
2401060SN/A     */
2411060SN/A    bool doneTargCalc() { return false; }
2421060SN/A
2431684SN/A    /** Returns the next PC.  This could be the speculative next PC if it is
2441684SN/A     *  called prior to the actual branch target being calculated.
2451684SN/A     */
2461060SN/A    Addr readNextPC() { return nextPC; }
2471060SN/A
2481060SN/A    /** Set the predicted target of this current instruction. */
2491060SN/A    void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
2501060SN/A
2511060SN/A    /** Returns the predicted target of the branch. */
2521060SN/A    Addr readPredTarg() { return predPC; }
2531060SN/A
2541060SN/A    /** Returns whether the instruction was predicted taken or not. */
2551060SN/A    bool predTaken() {
2561060SN/A        return( predPC != (PC + sizeof(MachInst) ) );
2571060SN/A    }
2581060SN/A
2591060SN/A    /** Returns whether the instruction mispredicted. */
2601060SN/A    bool mispredicted() { return (predPC != nextPC); }
2611060SN/A
2621060SN/A    //
2631060SN/A    //  Instruction types.  Forward checks to StaticInst object.
2641060SN/A    //
2651060SN/A    bool isNop()	  const { return staticInst->isNop(); }
2661060SN/A    bool isMemRef()    	  const { return staticInst->isMemRef(); }
2671060SN/A    bool isLoad()	  const { return staticInst->isLoad(); }
2681060SN/A    bool isStore()	  const { return staticInst->isStore(); }
2691060SN/A    bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
2701060SN/A    bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
2711060SN/A    bool isCopy()         const { return staticInst->isCopy(); }
2721060SN/A    bool isInteger()	  const { return staticInst->isInteger(); }
2731060SN/A    bool isFloating()	  const { return staticInst->isFloating(); }
2741060SN/A    bool isControl()	  const { return staticInst->isControl(); }
2751060SN/A    bool isCall()	  const { return staticInst->isCall(); }
2761060SN/A    bool isReturn()	  const { return staticInst->isReturn(); }
2771060SN/A    bool isDirectCtrl()	  const { return staticInst->isDirectCtrl(); }
2781060SN/A    bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
2791060SN/A    bool isCondCtrl()	  const { return staticInst->isCondCtrl(); }
2801060SN/A    bool isUncondCtrl()	  const { return staticInst->isUncondCtrl(); }
2811060SN/A    bool isThreadSync()   const { return staticInst->isThreadSync(); }
2821060SN/A    bool isSerializing()  const { return staticInst->isSerializing(); }
2831060SN/A    bool isMemBarrier()   const { return staticInst->isMemBarrier(); }
2841060SN/A    bool isWriteBarrier() const { return staticInst->isWriteBarrier(); }
2851060SN/A    bool isNonSpeculative() const { return staticInst->isNonSpeculative(); }
2861060SN/A
2871464SN/A    /** Returns the opclass of this instruction. */
2881464SN/A    OpClass opClass() const { return staticInst->opClass(); }
2891464SN/A
2901464SN/A    /** Returns the branch target address. */
2911464SN/A    Addr branchTarget() const { return staticInst->branchTarget(PC); }
2921464SN/A
2931684SN/A    /** Number of source registers. */
2941060SN/A    int8_t numSrcRegs()	 const { return staticInst->numSrcRegs(); }
2951684SN/A
2961684SN/A    /** Number of destination registers. */
2971060SN/A    int8_t numDestRegs() const { return staticInst->numDestRegs(); }
2981060SN/A
2991060SN/A    // the following are used to track physical register usage
3001060SN/A    // for machines with separate int & FP reg files
3011060SN/A    int8_t numFPDestRegs()  const { return staticInst->numFPDestRegs(); }
3021060SN/A    int8_t numIntDestRegs() const { return staticInst->numIntDestRegs(); }
3031060SN/A
3041060SN/A    /** Returns the logical register index of the i'th destination register. */
3051060SN/A    RegIndex destRegIdx(int i) const
3061060SN/A    {
3071060SN/A        return staticInst->destRegIdx(i);
3081060SN/A    }
3091060SN/A
3101060SN/A    /** Returns the logical register index of the i'th source register. */
3111060SN/A    RegIndex srcRegIdx(int i) const
3121060SN/A    {
3131060SN/A        return staticInst->srcRegIdx(i);
3141060SN/A    }
3151060SN/A
3161684SN/A    /** Returns the result of an integer instruction. */
3171464SN/A    uint64_t readIntResult() { return instResult.integer; }
3181684SN/A
3191684SN/A    /** Returns the result of a floating point instruction. */
3201464SN/A    float readFloatResult() { return instResult.fp; }
3211684SN/A
3221684SN/A    /** Returns the result of a floating point (double) instruction. */
3231464SN/A    double readDoubleResult() { return instResult.dbl; }
3241060SN/A
3251060SN/A    //Push to .cc file.
3261060SN/A    /** Records that one of the source registers is ready. */
3271060SN/A    void markSrcRegReady()
3281060SN/A    {
3291060SN/A        ++readyRegs;
3301060SN/A        if(readyRegs == numSrcRegs()) {
3311060SN/A            canIssue = true;
3321060SN/A        }
3331060SN/A    }
3341060SN/A
3351684SN/A    /** Marks a specific register as ready.
3361684SN/A     *  @todo: Move this to .cc file.
3371684SN/A     */
3381060SN/A    void markSrcRegReady(RegIndex src_idx)
3391060SN/A    {
3401060SN/A        ++readyRegs;
3411060SN/A
3421060SN/A        _readySrcRegIdx[src_idx] = 1;
3431060SN/A
3441060SN/A        if(readyRegs == numSrcRegs()) {
3451060SN/A            canIssue = true;
3461060SN/A        }
3471060SN/A    }
3481060SN/A
3491684SN/A    /** Returns if a source register is ready. */
3501464SN/A    bool isReadySrcRegIdx(int idx) const
3511464SN/A    {
3521464SN/A        return this->_readySrcRegIdx[idx];
3531464SN/A    }
3541464SN/A
3551684SN/A    /** Sets this instruction as completed. */
3561464SN/A    void setCompleted() { completed = true; }
3571464SN/A
3581684SN/A    /** Returns whethe or not this instruction is completed. */
3591464SN/A    bool isCompleted() const { return completed; }
3601464SN/A
3611060SN/A    /** Sets this instruction as ready to issue. */
3621060SN/A    void setCanIssue() { canIssue = true; }
3631060SN/A
3641060SN/A    /** Returns whether or not this instruction is ready to issue. */
3651060SN/A    bool readyToIssue() const { return canIssue; }
3661060SN/A
3671060SN/A    /** Sets this instruction as issued from the IQ. */
3681060SN/A    void setIssued() { issued = true; }
3691060SN/A
3701060SN/A    /** Returns whether or not this instruction has issued. */
3711464SN/A    bool isIssued() const { return issued; }
3721060SN/A
3731060SN/A    /** Sets this instruction as executed. */
3741060SN/A    void setExecuted() { executed = true; }
3751060SN/A
3761060SN/A    /** Returns whether or not this instruction has executed. */
3771464SN/A    bool isExecuted() const { return executed; }
3781060SN/A
3791060SN/A    /** Sets this instruction as ready to commit. */
3801060SN/A    void setCanCommit() { canCommit = true; }
3811060SN/A
3821061SN/A    /** Clears this instruction as being ready to commit. */
3831061SN/A    void clearCanCommit() { canCommit = false; }
3841061SN/A
3851060SN/A    /** Returns whether or not this instruction is ready to commit. */
3861060SN/A    bool readyToCommit() const { return canCommit; }
3871060SN/A
3881060SN/A    /** Sets this instruction as squashed. */
3891060SN/A    void setSquashed() { squashed = true; }
3901060SN/A
3911060SN/A    /** Returns whether or not this instruction is squashed. */
3921060SN/A    bool isSquashed() const { return squashed; }
3931060SN/A
3941060SN/A    /** Sets this instruction as squashed in the IQ. */
3951060SN/A    void setSquashedInIQ() { squashedInIQ = true; }
3961060SN/A
3971060SN/A    /** Returns whether or not this instruction is squashed in the IQ. */
3981464SN/A    bool isSquashedInIQ() const { return squashedInIQ; }
3991060SN/A
4001060SN/A    /** Read the PC of this instruction. */
4011464SN/A    const Addr readPC() const { return PC; }
4021060SN/A
4031060SN/A    /** Set the next PC of this instruction (its actual target). */
4041060SN/A    void setNextPC(uint64_t val) { nextPC = val; }
4051060SN/A
4061684SN/A    /** Returns the exec context.
4071684SN/A     *  @todo: Remove this once the ExecContext is no longer used.
4081684SN/A     */
4092190SN/A    ExecContext *xcBase() { return cpuXC->getProxy(); }
4101464SN/A
4111464SN/A  private:
4121684SN/A    /** Instruction effective address.
4131684SN/A     *  @todo: Consider if this is necessary or not.
4141684SN/A     */
4151464SN/A    Addr instEffAddr;
4161684SN/A    /** Whether or not the effective address calculation is completed.
4171684SN/A     *  @todo: Consider if this is necessary or not.
4181684SN/A     */
4191464SN/A    bool eaCalcDone;
4201464SN/A
4211464SN/A  public:
4221684SN/A    /** Sets the effective address. */
4231464SN/A    void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
4241684SN/A
4251684SN/A    /** Returns the effective address. */
4261464SN/A    const Addr &getEA() const { return instEffAddr; }
4271684SN/A
4281684SN/A    /** Returns whether or not the eff. addr. calculation has been completed. */
4291464SN/A    bool doneEACalc() { return eaCalcDone; }
4301684SN/A
4311684SN/A    /** Returns whether or not the eff. addr. source registers are ready. */
4321464SN/A    bool eaSrcsReady();
4331681SN/A
4341681SN/A  public:
4351684SN/A    /** Load queue index. */
4361681SN/A    int16_t lqIdx;
4371684SN/A
4381684SN/A    /** Store queue index. */
4391681SN/A    int16_t sqIdx;
4401060SN/A};
4411060SN/A
4421060SN/Atemplate<class Impl>
4431060SN/Atemplate<class T>
4442132SN/Ainline Fault
4451060SN/ABaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
4461060SN/A{
4472190SN/A    MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
4481060SN/A    req->asid = asid;
4491060SN/A
4501060SN/A    fault = cpu->translateDataReadReq(req);
4511060SN/A
4521060SN/A    // Record key MemReq parameters so we can generate another one
4531060SN/A    // just like it for the timing access without calling translate()
4541060SN/A    // again (which might mess up the TLB).
4551681SN/A    // Do I ever really need this? -KTL 3/05
4561060SN/A    effAddr = req->vaddr;
4571060SN/A    physEffAddr = req->paddr;
4581060SN/A    memReqFlags = req->flags;
4591060SN/A
4601060SN/A    /**
4611060SN/A     * @todo
4621060SN/A     * Replace the disjoint functional memory with a unified one and remove
4631060SN/A     * this hack.
4641060SN/A     */
4651858SN/A#if !FULL_SYSTEM
4661060SN/A    req->paddr = req->vaddr;
4671060SN/A#endif
4681060SN/A
4692090SN/A    if (fault == NoFault) {
4701681SN/A        fault = cpu->read(req, data, lqIdx);
4711684SN/A    } else {
4721060SN/A        // Return a fixed value to keep simulation deterministic even
4731060SN/A        // along misspeculated paths.
4741060SN/A        data = (T)-1;
4751060SN/A    }
4761060SN/A
4771060SN/A    if (traceData) {
4781060SN/A        traceData->setAddr(addr);
4791060SN/A        traceData->setData(data);
4801060SN/A    }
4811060SN/A
4821060SN/A    return fault;
4831060SN/A}
4841060SN/A
4851060SN/Atemplate<class Impl>
4861060SN/Atemplate<class T>
4872132SN/Ainline Fault
4881060SN/ABaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
4891060SN/A{
4901060SN/A    if (traceData) {
4911060SN/A        traceData->setAddr(addr);
4921060SN/A        traceData->setData(data);
4931060SN/A    }
4941060SN/A
4952190SN/A    MemReqPtr req = new MemReq(addr, cpuXC->getProxy(), sizeof(T), flags);
4961060SN/A
4971060SN/A    req->asid = asid;
4981060SN/A
4991060SN/A    fault = cpu->translateDataWriteReq(req);
5001060SN/A
5011060SN/A    // Record key MemReq parameters so we can generate another one
5021060SN/A    // just like it for the timing access without calling translate()
5031060SN/A    // again (which might mess up the TLB).
5041060SN/A    effAddr = req->vaddr;
5051060SN/A    physEffAddr = req->paddr;
5061060SN/A    memReqFlags = req->flags;
5071060SN/A
5081060SN/A    /**
5091060SN/A     * @todo
5101060SN/A     * Replace the disjoint functional memory with a unified one and remove
5111060SN/A     * this hack.
5121060SN/A     */
5131858SN/A#if !FULL_SYSTEM
5141060SN/A    req->paddr = req->vaddr;
5151060SN/A#endif
5161060SN/A
5172090SN/A    if (fault == NoFault) {
5181681SN/A        fault = cpu->write(req, data, sqIdx);
5191060SN/A    }
5201060SN/A
5211060SN/A    if (res) {
5221060SN/A        // always return some result to keep misspeculated paths
5231060SN/A        // (which will ignore faults) deterministic
5242090SN/A        *res = (fault == NoFault) ? req->result : 0;
5251060SN/A    }
5261060SN/A
5271060SN/A    return fault;
5281060SN/A}
5291060SN/A
5301464SN/A#endif // __CPU_BASE_DYN_INST_HH__
531