/*
* Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * Copyright (c) 2009 The University of Edinburgh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Kevin Lim
+ * Timothy M. Jones
*/
#ifndef __CPU_BASE_DYN_INST_HH__
#include "base/fast_alloc.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
+#include "config/the_isa.hh"
+#include "cpu/o3/comm.hh"
#include "cpu/exetrace.hh"
#include "cpu/inst_seq.hh"
#include "cpu/op_class.hh"
#include "cpu/static_inst.hh"
+#include "cpu/translation.hh"
#include "mem/packet.hh"
#include "sim/system.hh"
+#include "sim/tlb.hh"
/**
* @file
typedef typename Impl::CPUType ImplCPU;
typedef typename ImplCPU::ImplState ImplState;
- // Binary machine instruction type.
- typedef TheISA::MachInst MachInst;
- // Extended machine instruction type
- typedef TheISA::ExtMachInst ExtMachInst;
// Logical register index type.
typedef TheISA::RegIndex RegIndex;
// Integer register type.
typedef typename std::list<DynInstPtr>::iterator ListIt;
enum {
- MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs
- MaxInstDestRegs = TheISA::MaxInstDestRegs, /// Max dest regs
+ MaxInstSrcRegs = TheISA::MaxInstSrcRegs, /// Max source regs
+ MaxInstDestRegs = TheISA::MaxInstDestRegs, /// Max dest regs
};
/** The StaticInst used by this BaseDynInst. */
/** InstRecord that tracks this instructions. */
Trace::InstRecord *traceData;
+ void demapPage(Addr vaddr, uint64_t asn)
+ {
+ cpu->demapPage(vaddr, asn);
+ }
+ void demapInstPage(Addr vaddr, uint64_t asn)
+ {
+ cpu->demapPage(vaddr, asn);
+ }
+ void demapDataPage(Addr vaddr, uint64_t asn)
+ {
+ cpu->demapPage(vaddr, asn);
+ }
+
/**
* Does a read to a given address.
* @param addr The address to read.
template <class T>
Fault read(Addr addr, T &data, unsigned flags);
+ Fault readBytes(Addr addr, uint8_t *data, unsigned size, unsigned flags);
+
/**
* Does a write to a given address.
* @param data The data to be written.
* @return Returns any fault due to the write.
*/
template <class T>
- Fault write(T data, Addr addr, unsigned flags,
- uint64_t *res);
+ Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
+
+ Fault writeBytes(uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *res);
+
+ /** Splits a request in two if it crosses a dcache block. */
+ void splitRequest(RequestPtr req, RequestPtr &sreqLow,
+ RequestPtr &sreqHigh);
+
+ /** Initiate a DTB address translation. */
+ void initiateTranslation(RequestPtr req, RequestPtr sreqLow,
+ RequestPtr sreqHigh, uint64_t *res,
+ BaseTLB::Mode mode);
+
+ /** Finish a DTB address translation. */
+ void finishTranslation(WholeTranslationState *state);
void prefetch(Addr addr, unsigned flags);
void writeHint(Addr addr, int size, unsigned flags);
std::bitset<NumStatus> status;
/** The thread this instruction is from. */
- short threadNumber;
+ ThreadID threadNumber;
/** data address space ID, for loads & stores. */
short asid;
/** The kind of fault this instruction has generated. */
Fault fault;
- /** The memory request. */
- Request *req;
-
/** Pointer to the data for the memory access. */
uint8_t *memData;
/** The effective virtual address (lds & stores only). */
Addr effAddr;
+ /** Is the effective virtual address valid. */
+ bool effAddrValid;
+
/** The effective physical address. */
Addr physEffAddr;
/** PC of this instruction. */
Addr PC;
+ /** Micro PC of this instruction. */
+ Addr microPC;
+
+ protected:
/** Next non-speculative PC. It is not filled in at fetch, but rather
* once the target of the branch is truly known (either decode or
* execute).
/** Next non-speculative NPC. Target PC for Mips or Sparc. */
Addr nextNPC;
+ /** Next non-speculative micro PC. */
+ Addr nextMicroPC;
+
/** Predicted next PC. */
Addr predPC;
- /** Count of total number of dynamic instructions. */
- static int instcount;
+ /** Predicted next NPC. */
+ Addr predNPC;
+
+ /** Predicted next microPC */
+ Addr predMicroPC;
+
+ /** If this is a branch that was predicted taken */
+ bool predTaken;
+
+ public:
#ifdef DEBUG
void dumpSNList();
*/
bool _readySrcRegIdx[MaxInstSrcRegs];
+ protected:
+ /** Flattened register index of the destination registers of this
+ * instruction.
+ */
+ TheISA::RegIndex _flatDestRegIdx[TheISA::MaxInstDestRegs];
+
+ /** Flattened register index of the source registers of this
+ * instruction.
+ */
+ TheISA::RegIndex _flatSrcRegIdx[TheISA::MaxInstSrcRegs];
+
+ /** Physical register index of the destination registers of this
+ * instruction.
+ */
+ PhysRegIndex _destRegIdx[TheISA::MaxInstDestRegs];
+
+ /** Physical register index of the source registers of this
+ * instruction.
+ */
+ PhysRegIndex _srcRegIdx[TheISA::MaxInstSrcRegs];
+
+ /** Physical register index of the previous producers of the
+ * architected destinations.
+ */
+ PhysRegIndex _prevDestRegIdx[TheISA::MaxInstDestRegs];
+
public:
+
+ /** Returns the physical register index of the i'th destination
+ * register.
+ */
+ PhysRegIndex renamedDestRegIdx(int idx) const
+ {
+ return _destRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the i'th source register. */
+ PhysRegIndex renamedSrcRegIdx(int idx) const
+ {
+ return _srcRegIdx[idx];
+ }
+
+ /** Returns the flattened register index of the i'th destination
+ * register.
+ */
+ TheISA::RegIndex flattenedDestRegIdx(int idx) const
+ {
+ return _flatDestRegIdx[idx];
+ }
+
+ /** Returns the flattened register index of the i'th source register */
+ TheISA::RegIndex flattenedSrcRegIdx(int idx) const
+ {
+ return _flatSrcRegIdx[idx];
+ }
+
+ /** Returns the physical register index of the previous physical register
+ * that remapped to the same logical register index.
+ */
+ PhysRegIndex prevDestRegIdx(int idx) const
+ {
+ return _prevDestRegIdx[idx];
+ }
+
+ /** Renames a destination register to a physical register. Also records
+ * the previous physical register that the logical register mapped to.
+ */
+ void renameDestReg(int idx,
+ PhysRegIndex renamed_dest,
+ PhysRegIndex previous_rename)
+ {
+ _destRegIdx[idx] = renamed_dest;
+ _prevDestRegIdx[idx] = previous_rename;
+ }
+
+ /** Renames a source logical register to the physical register which
+ * has/will produce that logical register's result.
+ * @todo: add in whether or not the source register is ready.
+ */
+ void renameSrcReg(int idx, PhysRegIndex renamed_src)
+ {
+ _srcRegIdx[idx] = renamed_src;
+ }
+
+ /** Flattens a source architectural register index into a logical index.
+ */
+ void flattenSrcReg(int idx, TheISA::RegIndex flattened_src)
+ {
+ _flatSrcRegIdx[idx] = flattened_src;
+ }
+
+ /** Flattens a destination architectural register index into a logical
+ * index.
+ */
+ void flattenDestReg(int idx, TheISA::RegIndex flattened_dest)
+ {
+ _flatDestRegIdx[idx] = flattened_dest;
+ }
+ /** BaseDynInst constructor given a binary instruction.
+ * @param staticInst A StaticInstPtr to the underlying instruction.
+ * @param PC The PC of the instruction.
+ * @param pred_PC The predicted next PC.
+ * @param pred_NPC The predicted next NPC.
+ * @param seq_num The sequence number of the instruction.
+ * @param cpu Pointer to the instruction's CPU.
+ */
+ BaseDynInst(StaticInstPtr staticInst, Addr PC, Addr NPC, Addr microPC,
+ Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC,
+ InstSeqNum seq_num, ImplCPU *cpu);
+
/** BaseDynInst constructor given a binary instruction.
* @param inst The binary instruction.
* @param PC The PC of the instruction.
* @param pred_PC The predicted next PC.
+ * @param pred_NPC The predicted next NPC.
* @param seq_num The sequence number of the instruction.
* @param cpu Pointer to the instruction's CPU.
*/
- BaseDynInst(ExtMachInst inst, Addr PC, Addr pred_PC, InstSeqNum seq_num,
- ImplCPU *cpu);
+ BaseDynInst(TheISA::ExtMachInst inst, Addr PC, Addr NPC, Addr microPC,
+ Addr pred_PC, Addr pred_NPC, Addr pred_MicroPC,
+ InstSeqNum seq_num, ImplCPU *cpu);
/** BaseDynInst constructor given a StaticInst pointer.
* @param _staticInst The StaticInst for this BaseDynInst.
void dump(std::string &outstring);
/** Read this CPU's ID. */
- int readCpuId() { return cpu->readCpuId(); }
+ int cpuId() { return cpu->cpuId(); }
+
+ /** Read this context's system-wide ID **/
+ int contextId() { return thread->contextId(); }
/** Returns the fault type. */
Fault getFault() { return fault; }
/** Returns the next NPC. This could be the speculative next NPC if it is
* called prior to the actual branch target being calculated.
*/
- Addr readNextNPC() { return nextNPC; }
+ Addr readNextNPC()
+ {
+#if ISA_HAS_DELAY_SLOT
+ return nextNPC;
+#else
+ return nextPC + sizeof(TheISA::MachInst);
+#endif
+ }
+
+ Addr readNextMicroPC()
+ {
+ return nextMicroPC;
+ }
/** Set the predicted target of this current instruction. */
- void setPredTarg(Addr predicted_PC) { predPC = predicted_PC; }
+ void setPredTarg(Addr predicted_PC, Addr predicted_NPC,
+ Addr predicted_MicroPC)
+ {
+ predPC = predicted_PC;
+ predNPC = predicted_NPC;
+ predMicroPC = predicted_MicroPC;
+ }
- /** Returns the predicted target of the branch. */
- Addr readPredTarg() { return predPC; }
+ /** Returns the predicted PC immediately after the branch. */
+ Addr readPredPC() { return predPC; }
+
+ /** Returns the predicted PC two instructions after the branch */
+ Addr readPredNPC() { return predNPC; }
+
+ /** Returns the predicted micro PC after the branch */
+ Addr readPredMicroPC() { return predMicroPC; }
/** Returns whether the instruction was predicted taken or not. */
- bool predTaken()
-#if ISA_HAS_DELAY_SLOT
- { return predPC != (nextPC + sizeof(MachInst)); }
-#else
- { return predPC != (PC + sizeof(MachInst)); }
-#endif
+ bool readPredTaken()
+ {
+ return predTaken;
+ }
+
+ void setPredTaken(bool predicted_taken)
+ {
+ predTaken = predicted_taken;
+ }
/** Returns whether the instruction mispredicted. */
bool mispredicted()
-#if ISA_HAS_DELAY_SLOT
- { return predPC != nextNPC; }
-#else
- { return predPC != nextPC; }
-#endif
+ {
+ return readPredPC() != readNextPC() ||
+ readPredNPC() != readNextNPC() ||
+ readPredMicroPC() != readNextMicroPC();
+ }
+
//
// Instruction types. Forward checks to StaticInst object.
//
- bool isNop() const { return staticInst->isNop(); }
- bool isMemRef() const { return staticInst->isMemRef(); }
- bool isLoad() const { return staticInst->isLoad(); }
- bool isStore() const { return staticInst->isStore(); }
+ bool isNop() const { return staticInst->isNop(); }
+ bool isMemRef() const { return staticInst->isMemRef(); }
+ bool isLoad() const { return staticInst->isLoad(); }
+ bool isStore() const { return staticInst->isStore(); }
bool isStoreConditional() const
{ return staticInst->isStoreConditional(); }
bool isInstPrefetch() const { return staticInst->isInstPrefetch(); }
bool isDataPrefetch() const { return staticInst->isDataPrefetch(); }
bool isCopy() const { return staticInst->isCopy(); }
- bool isInteger() const { return staticInst->isInteger(); }
- bool isFloating() const { return staticInst->isFloating(); }
- bool isControl() const { return staticInst->isControl(); }
- bool isCall() const { return staticInst->isCall(); }
- bool isReturn() const { return staticInst->isReturn(); }
- bool isDirectCtrl() const { return staticInst->isDirectCtrl(); }
+ bool isInteger() const { return staticInst->isInteger(); }
+ bool isFloating() const { return staticInst->isFloating(); }
+ bool isControl() const { return staticInst->isControl(); }
+ bool isCall() const { return staticInst->isCall(); }
+ bool isReturn() const { return staticInst->isReturn(); }
+ bool isDirectCtrl() const { return staticInst->isDirectCtrl(); }
bool isIndirectCtrl() const { return staticInst->isIndirectCtrl(); }
- bool isCondCtrl() const { return staticInst->isCondCtrl(); }
- bool isUncondCtrl() const { return staticInst->isUncondCtrl(); }
+ bool isCondCtrl() const { return staticInst->isCondCtrl(); }
+ bool isUncondCtrl() const { return staticInst->isUncondCtrl(); }
bool isCondDelaySlot() const { return staticInst->isCondDelaySlot(); }
bool isThreadSync() const { return staticInst->isThreadSync(); }
bool isSerializing() const { return staticInst->isSerializing(); }
bool isQuiesce() const { return staticInst->isQuiesce(); }
bool isIprAccess() const { return staticInst->isIprAccess(); }
bool isUnverifiable() const { return staticInst->isUnverifiable(); }
+ bool isSyscall() const { return staticInst->isSyscall(); }
+ bool isMacroop() const { return staticInst->isMacroop(); }
+ bool isMicroop() const { return staticInst->isMicroop(); }
+ bool isDelayedCommit() const { return staticInst->isDelayedCommit(); }
+ bool isLastMicroop() const { return staticInst->isLastMicroop(); }
+ bool isFirstMicroop() const { return staticInst->isFirstMicroop(); }
+ bool isMicroBranch() const { return staticInst->isMicroBranch(); }
/** Temporarily sets this instruction as a serialize before instruction. */
void setSerializeBefore() { status.set(SerializeBefore); }
Addr branchTarget() const { return staticInst->branchTarget(PC); }
/** Returns the number of source registers. */
- int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
+ int8_t numSrcRegs() const { return staticInst->numSrcRegs(); }
/** Returns the number of destination registers. */
int8_t numDestRegs() const { return staticInst->numDestRegs(); }
/** Returns whether or not this instruction is ready to issue. */
bool readyToIssue() const { return status[CanIssue]; }
+ /** Clears this instruction being able to issue. */
+ void clearCanIssue() { status.reset(CanIssue); }
+
/** Sets this instruction as issued from the IQ. */
void setIssued() { status.set(Issued); }
/** Returns whether or not this instruction has issued. */
bool isIssued() const { return status[Issued]; }
+ /** Clears this instruction as being issued. */
+ void clearIssued() { status.reset(Issued); }
+
/** Sets this instruction as executed. */
void setExecuted() { status.set(Executed); }
/** Read the PC of this instruction. */
const Addr readPC() const { return PC; }
+ /**Read the micro PC of this instruction. */
+ const Addr readMicroPC() const { return microPC; }
+
/** Set the next PC of this instruction (its actual target). */
- void setNextPC(uint64_t val)
+ void setNextPC(Addr val)
{
nextPC = val;
}
/** Set the next NPC of this instruction (the target in Mips or Sparc).*/
- void setNextNPC(uint64_t val)
+ void setNextNPC(Addr val)
{
+#if ISA_HAS_DELAY_SLOT
nextNPC = val;
+#endif
+ }
+
+ void setNextMicroPC(Addr val)
+ {
+ nextMicroPC = val;
}
/** Sets the ASID. */
void setASID(short addr_space_id) { asid = addr_space_id; }
/** Sets the thread id. */
- void setTid(unsigned tid) { threadNumber = tid; }
+ void setTid(ThreadID tid) { threadNumber = tid; }
/** Sets the pointer to the thread state. */
void setThreadState(ImplState *state) { thread = state; }
*/
bool eaCalcDone;
+ /** Is this instruction's memory access uncacheable. */
+ bool isUncacheable;
+
+ /** Has this instruction generated a memory request. */
+ bool reqMade;
+
public:
/** Sets the effective address. */
void setEA(Addr &ea) { instEffAddr = ea; eaCalcDone = true; }
/** Whether or not the memory operation is done. */
bool memOpDone;
+ /** Is this instruction's memory access uncacheable. */
+ bool uncacheable() { return isUncacheable; }
+
+ /** Has this instruction generated a memory request. */
+ bool hasRequest() { return reqMade; }
+
public:
/** Load queue index. */
int16_t lqIdx;
};
template<class Impl>
-template<class T>
-inline Fault
-BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
+Fault
+BaseDynInst<Impl>::readBytes(Addr addr, uint8_t *data,
+ unsigned size, unsigned flags)
{
- // Sometimes reads will get retried, so they may come through here
- // twice.
- if (!req) {
- req = new Request();
- req->setVirt(asid, addr, sizeof(T), flags, this->PC);
- req->setThreadContext(thread->readCpuId(), threadNumber);
- } else {
- assert(addr == req->getVaddr());
- }
+ reqMade = true;
+ Request *req = new Request(asid, addr, size, flags, this->PC,
+ thread->contextId(), threadNumber);
- if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
- TheISA::VMPageSize) {
- return TheISA::genAlignmentFault();
- }
+ Request *sreqLow = NULL;
+ Request *sreqHigh = NULL;
- fault = cpu->translateDataReadReq(req, thread);
+ // Only split the request if the ISA supports unaligned accesses.
+ if (TheISA::HasUnalignedMemAcc) {
+ splitRequest(req, sreqLow, sreqHigh);
+ }
+ initiateTranslation(req, sreqLow, sreqHigh, NULL, BaseTLB::Read);
if (fault == NoFault) {
effAddr = req->getVaddr();
- physEffAddr = req->getPaddr();
- memReqFlags = req->getFlags();
-
-#if 0
- if (cpu->system->memctrl->badaddr(physEffAddr)) {
- fault = TheISA::genMachineCheckFault();
- data = (T)-1;
- this->setExecuted();
- } else {
- fault = cpu->read(req, data, lqIdx);
- }
-#else
- fault = cpu->read(req, data, lqIdx);
-#endif
+ effAddrValid = true;
+ fault = cpu->read(req, sreqLow, sreqHigh, data, lqIdx);
} else {
- // Return a fixed value to keep simulation deterministic even
- // along misspeculated paths.
- data = (T)-1;
-
// Commit will have to clean up whatever happened. Set this
// instruction as executed.
this->setExecuted();
if (traceData) {
traceData->setAddr(addr);
+ }
+
+ return fault;
+}
+
+template<class Impl>
+template<class T>
+inline Fault
+BaseDynInst<Impl>::read(Addr addr, T &data, unsigned flags)
+{
+ Fault fault = readBytes(addr, (uint8_t *)&data, sizeof(T), flags);
+
+ if (fault != NoFault) {
+ // Return a fixed value to keep simulation deterministic even
+ // along misspeculated paths.
+ data = (T)-1;
+ }
+ data = TheISA::gtoh(data);
+
+ if (traceData) {
traceData->setData(data);
}
return fault;
}
+template<class Impl>
+Fault
+BaseDynInst<Impl>::writeBytes(uint8_t *data, unsigned size,
+ Addr addr, unsigned flags, uint64_t *res)
+{
+ if (traceData) {
+ traceData->setAddr(addr);
+ }
+
+ reqMade = true;
+ Request *req = new Request(asid, addr, size, flags, this->PC,
+ thread->contextId(), threadNumber);
+
+ Request *sreqLow = NULL;
+ Request *sreqHigh = NULL;
+
+ // Only split the request if the ISA supports unaligned accesses.
+ if (TheISA::HasUnalignedMemAcc) {
+ splitRequest(req, sreqLow, sreqHigh);
+ }
+ initiateTranslation(req, sreqLow, sreqHigh, res, BaseTLB::Write);
+
+ if (fault == NoFault) {
+ effAddr = req->getVaddr();
+ effAddrValid = true;
+ fault = cpu->write(req, sreqLow, sreqHigh, data, sqIdx);
+ }
+
+ return fault;
+}
+
template<class Impl>
template<class T>
inline Fault
BaseDynInst<Impl>::write(T data, Addr addr, unsigned flags, uint64_t *res)
{
if (traceData) {
- traceData->setAddr(addr);
traceData->setData(data);
}
+ data = TheISA::htog(data);
+ return writeBytes((uint8_t *)&data, sizeof(T), addr, flags, res);
+}
- assert(req == NULL);
+template<class Impl>
+inline void
+BaseDynInst<Impl>::splitRequest(RequestPtr req, RequestPtr &sreqLow,
+ RequestPtr &sreqHigh)
+{
+ // Check to see if the request crosses the next level block boundary.
+ unsigned block_size = cpu->getDcachePort()->peerBlockSize();
+ Addr addr = req->getVaddr();
+ Addr split_addr = roundDown(addr + req->getSize() - 1, block_size);
+ assert(split_addr <= addr || split_addr - addr < block_size);
+
+ // Spans two blocks.
+ if (split_addr > addr) {
+ req->splitOnVaddr(split_addr, sreqLow, sreqHigh);
+ }
+}
- req = new Request();
- req->setVirt(asid, addr, sizeof(T), flags, this->PC);
- req->setThreadContext(thread->readCpuId(), threadNumber);
+template<class Impl>
+inline void
+BaseDynInst<Impl>::initiateTranslation(RequestPtr req, RequestPtr sreqLow,
+ RequestPtr sreqHigh, uint64_t *res,
+ BaseTLB::Mode mode)
+{
+ if (!TheISA::HasUnalignedMemAcc || sreqLow == NULL) {
+ WholeTranslationState *state =
+ new WholeTranslationState(req, NULL, res, mode);
+
+ // One translation if the request isn't split.
+ DataTranslation<BaseDynInst<Impl> > *trans =
+ new DataTranslation<BaseDynInst<Impl> >(this, state);
+ cpu->dtb->translateTiming(req, thread->getTC(), trans, mode);
+ } else {
+ WholeTranslationState *state =
+ new WholeTranslationState(req, sreqLow, sreqHigh, NULL, res, mode);
- if ((req->getVaddr() & (TheISA::VMPageSize - 1)) + req->getSize() >
- TheISA::VMPageSize) {
- return TheISA::genAlignmentFault();
+ // Two translations when the request is split.
+ DataTranslation<BaseDynInst<Impl> > *stransLow =
+ new DataTranslation<BaseDynInst<Impl> >(this, state, 0);
+ DataTranslation<BaseDynInst<Impl> > *stransHigh =
+ new DataTranslation<BaseDynInst<Impl> >(this, state, 1);
+
+ cpu->dtb->translateTiming(sreqLow, thread->getTC(), stransLow, mode);
+ cpu->dtb->translateTiming(sreqHigh, thread->getTC(), stransHigh, mode);
}
+}
- fault = cpu->translateDataWriteReq(req, thread);
+template<class Impl>
+inline void
+BaseDynInst<Impl>::finishTranslation(WholeTranslationState *state)
+{
+ fault = state->getFault();
+
+ if (state->isUncacheable())
+ isUncacheable = true;
if (fault == NoFault) {
- effAddr = req->getVaddr();
- physEffAddr = req->getPaddr();
- memReqFlags = req->getFlags();
-#if 0
- if (cpu->system->memctrl->badaddr(physEffAddr)) {
- fault = TheISA::genMachineCheckFault();
- } else {
- fault = cpu->write(req, data, sqIdx);
+ physEffAddr = state->getPaddr();
+ memReqFlags = state->getFlags();
+
+ if (state->mainReq->isCondSwap()) {
+ assert(state->res);
+ state->mainReq->setExtraData(*state->res);
}
-#else
- fault = cpu->write(req, data, sqIdx);
-#endif
- }
- if (res) {
- // always return some result to keep misspeculated paths
- // (which will ignore faults) deterministic
- *res = (fault == NoFault) ? req->getScResult() : 0;
+ } else {
+ state->deleteReqs();
}
-
- return fault;
+ delete state;
}
#endif // __CPU_BASE_DYN_INST_HH__