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