cpu: Fix the usage of const DynInstPtr

Summary: Usage of const DynInstPtr& when possible and introduction of
move operators to RefCountingPtr.

In many places, scoped references to dynamic instructions do a copy of
the DynInstPtr when a reference would do. This is detrimental to
performance. On top of that, in case there is a need for reference
tracking for debugging, the redundant copies make the process much more
painful than it already is.

Also, from the theoretical point of view, a function/method that
defines a convenience name to access an instruction should not be
considered an owner of the data, i.e., doing a copy and not a reference
is not justified.

On a related topic, C++11 introduces move semantics, and those are
useful when, for example, there is a class modelling a HW structure that
contains a list, and has a getHeadOfList function, to prevent doing a
copy to an internal variable -> update pointer, remove from the list ->
update pointer, return value making a copy to the assined variable ->
update pointer, destroy the returned value -> update pointer.

Change-Id: I3bb46c20ef23b6873b469fd22befb251ac44d2f6
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/13105
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
Rekai Gonzalez-Alberquilla
2017-02-06 11:10:06 +00:00
committed by Giacomo Gabrielli
parent 338a173e82
commit 0c50a0b4fe
36 changed files with 274 additions and 210 deletions

View File

@@ -1,4 +1,16 @@
/*
* Copyright (c) 2017 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
* not be construed as granting a license to any other intellectual
* property including but not limited to intellectual property relating
* to a hardware implementation of the functionality of the software
* licensed hereunder. You may use the software subject to the license
* terms below provided that you ensure that this notice is replicated
* unmodified and in its entirety in all distributions of the software,
* modified or unmodified, in source code or in binary form.
*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* All rights reserved.
*
@@ -31,6 +43,8 @@
#ifndef __BASE_REFCNT_HH__
#define __BASE_REFCNT_HH__
#include <type_traits>
/**
* @file base/refcnt.hh
*
@@ -80,11 +94,11 @@ class RefCounted
virtual ~RefCounted() {}
/// Increment the reference count
void incref() { ++count; }
void incref() const { ++count; }
/// Decrement the reference count and destroy the object if all
/// references are gone.
void decref() { if (--count <= 0) delete this; }
void decref() const { if (--count <= 0) delete this; }
};
/**
@@ -106,6 +120,18 @@ template <class T>
class RefCountingPtr
{
protected:
/** Convenience aliases for const/non-const versions of T w/ friendship. */
/** @{ */
static constexpr auto TisConst = std::is_const<T>::value;
using ConstT = typename std::conditional<TisConst,
RefCountingPtr<T>,
RefCountingPtr<typename std::add_const<T>::type>>::type;
friend ConstT;
using NonConstT = typename std::conditional<TisConst,
RefCountingPtr<typename std::remove_const<T>::type>,
RefCountingPtr<T>>::type;
friend NonConstT;
/** @} */
/// The stored pointer.
/// Arguably this should be private.
T *data;
@@ -163,6 +189,18 @@ class RefCountingPtr
/// one. Adds a reference.
RefCountingPtr(const RefCountingPtr &r) { copy(r.data); }
/** Move-constructor.
* Does not add a reference.
*/
RefCountingPtr(RefCountingPtr&& r)
{
data = r.data;
r.data = nullptr;
}
template <bool B = TisConst>
RefCountingPtr(const NonConstT &r) { copy(r.data); }
/// Destroy the pointer and any reference it may hold.
~RefCountingPtr() { del(); }
@@ -179,6 +217,12 @@ class RefCountingPtr
/// Directly access the pointer itself without taking a reference.
T *get() const { return data; }
template <bool B = TisConst>
operator RefCountingPtr<typename std::enable_if<!B, ConstT>::type>()
{
return RefCountingPtr<const T>(*this);
}
/// Assign a new value to the pointer
const RefCountingPtr &operator=(T *p) { set(p); return *this; }
@@ -186,6 +230,18 @@ class RefCountingPtr
const RefCountingPtr &operator=(const RefCountingPtr &r)
{ return operator=(r.data); }
/// Move-assign the pointer from another RefCountingPtr
const RefCountingPtr &operator=(RefCountingPtr&& r)
{
/* This happens regardless of whether the pointer is the same or not,
* because of the move semantics, the rvalue needs to be 'destroyed'.
*/
del();
data = r.data;
r.data = nullptr;
return *this;
}
/// Check if the pointer is empty
bool operator!() const { return data == 0; }

View File

@@ -827,7 +827,7 @@ class BaseDynInst : public ExecContext, public RefCounted
/**Read the micro PC of this instruction. */
Addr microPC() const { return pc.microPC(); }
bool readPredicate()
bool readPredicate() const
{
return instFlags[Predicate];
}
@@ -855,13 +855,13 @@ class BaseDynInst : public ExecContext, public RefCounted
public:
/** Returns whether or not the eff. addr. source registers are ready. */
bool eaSrcsReady();
bool eaSrcsReady() const;
/** Is this instruction's memory access strictly ordered? */
bool strictlyOrdered() const { return instFlags[IsStrictlyOrdered]; }
/** Has this instruction generated a memory request. */
bool hasRequest() { return instFlags[ReqMade]; }
bool hasRequest() const { return instFlags[ReqMade]; }
/** Returns iterator to this instruction in the list of all insts. */
ListIt &getInstListIt() { return instListIt; }

View File

@@ -217,7 +217,7 @@ BaseDynInst<Impl>::markSrcRegReady(RegIndex src_idx)
template <class Impl>
bool
BaseDynInst<Impl>::eaSrcsReady()
BaseDynInst<Impl>::eaSrcsReady() const
{
// For now I am assuming that src registers 1..n-1 are the ones that the
// EA calc depends on. (i.e. src reg 0 is the source of the data to be

View File

@@ -397,7 +397,8 @@ class CheckerCPU : public BaseCPU, public ExecContext
setVecElemResult(val);
}
bool readPredicate() override { return thread->readPredicate(); }
bool readPredicate() const override { return thread->readPredicate(); }
void setPredicate(bool val) override
{
thread->setPredicate(val);
@@ -572,18 +573,18 @@ class Checker : public CheckerCPU
void advancePC(const Fault &fault);
void verify(DynInstPtr &inst);
void verify(const DynInstPtr &inst);
void validateInst(DynInstPtr &inst);
void validateExecution(DynInstPtr &inst);
void validateInst(const DynInstPtr &inst);
void validateExecution(const DynInstPtr &inst);
void validateState();
void copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
void copyResult(const DynInstPtr &inst, const InstResult& mismatch_val,
int start_idx);
void handlePendingInt();
private:
void handleError(DynInstPtr &inst)
void handleError(const DynInstPtr &inst)
{
if (exitOnError) {
dumpAndExit(inst);
@@ -592,7 +593,7 @@ class Checker : public CheckerCPU
}
}
void dumpAndExit(DynInstPtr &inst);
void dumpAndExit(const DynInstPtr &inst);
bool updateThisCycle;

View File

@@ -124,7 +124,7 @@ Checker<Impl>::handlePendingInt()
template <class Impl>
void
Checker<Impl>::verify(DynInstPtr &completed_inst)
Checker<Impl>::verify(const DynInstPtr &completed_inst)
{
DynInstPtr inst;
@@ -456,7 +456,7 @@ Checker<Impl>::takeOverFrom(BaseCPU *oldCPU)
template <class Impl>
void
Checker<Impl>::validateInst(DynInstPtr &inst)
Checker<Impl>::validateInst(const DynInstPtr &inst)
{
if (inst->instAddr() != thread->instAddr()) {
warn("%lli: PCs do not match! Inst: %s, checker: %s",
@@ -477,7 +477,7 @@ Checker<Impl>::validateInst(DynInstPtr &inst)
template <class Impl>
void
Checker<Impl>::validateExecution(DynInstPtr &inst)
Checker<Impl>::validateExecution(const DynInstPtr &inst)
{
InstResult checker_val;
InstResult inst_val;
@@ -595,8 +595,8 @@ Checker<Impl>::validateState()
template <class Impl>
void
Checker<Impl>::copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
int start_idx)
Checker<Impl>::copyResult(const DynInstPtr &inst,
const InstResult& mismatch_val, int start_idx)
{
// We've already popped one dest off the queue,
// so do the fix-up then start with the next dest reg;
@@ -672,7 +672,7 @@ Checker<Impl>::copyResult(DynInstPtr &inst, const InstResult& mismatch_val,
template <class Impl>
void
Checker<Impl>::dumpAndExit(DynInstPtr &inst)
Checker<Impl>::dumpAndExit(const DynInstPtr &inst)
{
cprintf("Error detected, instruction information:\n");
cprintf("PC:%s, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"

View File

@@ -306,7 +306,7 @@ class ExecContext {
* @name ARM-Specific Interfaces
*/
virtual bool readPredicate() = 0;
virtual bool readPredicate() const = 0;
virtual void setPredicate(bool val) = 0;
/** @} */

View File

@@ -292,7 +292,7 @@ class ExecContext : public ::ExecContext
}
bool
readPredicate() override
readPredicate() const override
{
return thread.readPredicate();
}

View File

@@ -282,7 +282,7 @@ class DefaultCommit
* @param tid ID of the thread to squash.
* @param head_inst Instruction that requested the squash.
*/
void squashAfter(ThreadID tid, DynInstPtr &head_inst);
void squashAfter(ThreadID tid, const DynInstPtr &head_inst);
/** Handles processing an interrupt. */
void handleInterrupt();
@@ -296,7 +296,7 @@ class DefaultCommit
/** Tries to commit the head ROB instruction passed in.
* @param head_inst The instruction to be committed.
*/
bool commitHead(DynInstPtr &head_inst, unsigned inst_num);
bool commitHead(const DynInstPtr &head_inst, unsigned inst_num);
/** Gets instructions from rename and inserts them into the ROB. */
void getInsts();
@@ -477,7 +477,7 @@ class DefaultCommit
bool avoidQuiesceLiveLock;
/** Updates commit stats based on this instruction. */
void updateComInstStats(DynInstPtr &inst);
void updateComInstStats(const DynInstPtr &inst);
/** Stat for the total number of squashed instructions discarded by commit.
*/

View File

@@ -636,7 +636,7 @@ DefaultCommit<Impl>::squashFromSquashAfter(ThreadID tid)
template <class Impl>
void
DefaultCommit<Impl>::squashAfter(ThreadID tid, DynInstPtr &head_inst)
DefaultCommit<Impl>::squashAfter(ThreadID tid, const DynInstPtr &head_inst)
{
DPRINTF(Commit, "Executing squash after for [tid:%i] inst [sn:%lli]\n",
tid, head_inst->seqNum);
@@ -696,14 +696,14 @@ DefaultCommit<Impl>::tick()
// will be active.
_nextStatus = Active;
DynInstPtr inst = rob->readHeadInst(tid);
const DynInstPtr &inst M5_VAR_USED = rob->readHeadInst(tid);
DPRINTF(Commit,"[tid:%i]: Instruction [sn:%lli] PC %s is head of"
" ROB and ready to commit\n",
tid, inst->seqNum, inst->pcState());
} else if (!rob->isEmpty(tid)) {
DynInstPtr inst = rob->readHeadInst(tid);
const DynInstPtr &inst = rob->readHeadInst(tid);
ppCommitStall->notify(inst);
@@ -1136,7 +1136,7 @@ DefaultCommit<Impl>::commitInsts()
template <class Impl>
bool
DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
DefaultCommit<Impl>::commitHead(const DynInstPtr &head_inst, unsigned inst_num)
{
assert(head_inst);
@@ -1317,9 +1317,7 @@ DefaultCommit<Impl>::getInsts()
int insts_to_process = std::min((int)renameWidth, fromRename->size);
for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {
DynInstPtr inst;
inst = fromRename->insts[inst_num];
const DynInstPtr &inst = fromRename->insts[inst_num];
ThreadID tid = inst->threadNumber;
if (!inst->isSquashed() &&
@@ -1366,7 +1364,7 @@ DefaultCommit<Impl>::markCompletedInsts()
template <class Impl>
void
DefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst)
DefaultCommit<Impl>::updateComInstStats(const DynInstPtr &inst)
{
ThreadID tid = inst->threadNumber;
@@ -1507,7 +1505,7 @@ DefaultCommit<Impl>::oldestReady()
if (rob->isHeadReady(tid)) {
DynInstPtr head_inst = rob->readHeadInst(tid);
const DynInstPtr &head_inst = rob->readHeadInst(tid);
if (first) {
oldest = tid;

View File

@@ -1564,7 +1564,7 @@ FullO3CPU<Impl>::squashFromTC(ThreadID tid)
template <class Impl>
typename FullO3CPU<Impl>::ListIt
FullO3CPU<Impl>::addInst(DynInstPtr &inst)
FullO3CPU<Impl>::addInst(const DynInstPtr &inst)
{
instList.push_back(inst);
@@ -1573,7 +1573,7 @@ FullO3CPU<Impl>::addInst(DynInstPtr &inst)
template <class Impl>
void
FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst)
FullO3CPU<Impl>::instDone(ThreadID tid, const DynInstPtr &inst)
{
// Keep an instruction count.
if (!inst->isMicroop() || inst->isLastMicroop()) {
@@ -1595,7 +1595,7 @@ FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst)
template <class Impl>
void
FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
FullO3CPU<Impl>::removeFrontInst(const DynInstPtr &inst)
{
DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %s "
"[sn:%lli]\n",
@@ -1751,7 +1751,7 @@ FullO3CPU<Impl>::dumpInsts()
/*
template <class Impl>
void
FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
FullO3CPU<Impl>::wakeDependents(const DynInstPtr &inst)
{
iew.wakeDependents(inst);
}

View File

@@ -537,15 +537,15 @@ class FullO3CPU : public BaseO3CPU
/** Function to add instruction onto the head of the list of the
* instructions. Used when new instructions are fetched.
*/
ListIt addInst(DynInstPtr &inst);
ListIt addInst(const DynInstPtr &inst);
/** Function to tell the CPU that an instruction has completed. */
void instDone(ThreadID tid, DynInstPtr &inst);
void instDone(ThreadID tid, const DynInstPtr &inst);
/** Remove an instruction from the front end of the list. There's
* no restriction on location of the instruction.
*/
void removeFrontInst(DynInstPtr &inst);
void removeFrontInst(const DynInstPtr &inst);
/** Remove all instructions that are not currently in the ROB.
* There's also an option to not squash delay slot instructions.*/

View File

@@ -194,7 +194,7 @@ class DefaultDecode
/** Squashes if there is a PC-relative branch that was predicted
* incorrectly. Sends squash information back to fetch.
*/
void squash(DynInstPtr &inst, ThreadID tid);
void squash(const DynInstPtr &inst, ThreadID tid);
public:
/** Squashes due to commit signalling a squash. Changes status to

View File

@@ -288,7 +288,7 @@ DefaultDecode<Impl>::unblock(ThreadID tid)
template<class Impl>
void
DefaultDecode<Impl>::squash(DynInstPtr &inst, ThreadID tid)
DefaultDecode<Impl>::squash(const DynInstPtr &inst, ThreadID tid)
{
DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch "
"prediction detected at decode.\n", tid, inst->seqNum);
@@ -650,8 +650,6 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
++decodeRunCycles;
}
DynInstPtr inst;
std::queue<DynInstPtr>
&insts_to_decode = decodeStatus[tid] == Unblocking ?
skidBuffer[tid] : insts[tid];
@@ -661,7 +659,7 @@ DefaultDecode<Impl>::decodeInsts(ThreadID tid)
while (insts_available > 0 && toRenameIndex < decodeWidth) {
assert(!insts_to_decode.empty());
inst = insts_to_decode.front();
DynInstPtr inst = std::move(insts_to_decode.front());
insts_to_decode.pop();

View File

@@ -89,10 +89,10 @@ class DependencyGraph
void reset();
/** Inserts an instruction to be dependent on the given index. */
void insert(PhysRegIndex idx, DynInstPtr &new_inst);
void insert(PhysRegIndex idx, const DynInstPtr &new_inst);
/** Sets the producing instruction of a given register. */
void setInst(PhysRegIndex idx, DynInstPtr &new_inst)
void setInst(PhysRegIndex idx, const DynInstPtr &new_inst)
{ dependGraph[idx].inst = new_inst; }
/** Clears the producing instruction. */
@@ -100,7 +100,7 @@ class DependencyGraph
{ dependGraph[idx].inst = NULL; }
/** Removes an instruction from a single linked list. */
void remove(PhysRegIndex idx, DynInstPtr &inst_to_remove);
void remove(PhysRegIndex idx, const DynInstPtr &inst_to_remove);
/** Removes and returns the newest dependent of a specific register. */
DynInstPtr pop(PhysRegIndex idx);
@@ -182,7 +182,8 @@ DependencyGraph<DynInstPtr>::reset()
template <class DynInstPtr>
void
DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst)
DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx,
const DynInstPtr &new_inst)
{
//Add this new, dependent instruction at the head of the dependency
//chain.
@@ -203,7 +204,7 @@ DependencyGraph<DynInstPtr>::insert(PhysRegIndex idx, DynInstPtr &new_inst)
template <class DynInstPtr>
void
DependencyGraph<DynInstPtr>::remove(PhysRegIndex idx,
DynInstPtr &inst_to_remove)
const DynInstPtr &inst_to_remove)
{
DepEntry *prev = &dependGraph[idx];
DepEntry *curr = dependGraph[idx].next;

View File

@@ -281,7 +281,7 @@ class DefaultFetch
* @param next_NPC Used for ISAs which use delay slots.
* @return Whether or not a branch was predicted as taken.
*/
bool lookupAndUpdateNextPC(DynInstPtr &inst, TheISA::PCState &pc);
bool lookupAndUpdateNextPC(const DynInstPtr &inst, TheISA::PCState &pc);
/**
* Fetches the cache line that contains the fetch PC. Returns any

View File

@@ -546,7 +546,7 @@ DefaultFetch<Impl>::deactivateThread(ThreadID tid)
template <class Impl>
bool
DefaultFetch<Impl>::lookupAndUpdateNextPC(
DynInstPtr &inst, TheISA::PCState &nextPC)
const DynInstPtr &inst, TheISA::PCState &nextPC)
{
// Do branch prediction check here.
// A bit of a misnomer...next_PC is actually the current PC until
@@ -953,7 +953,7 @@ DefaultFetch<Impl>::tick()
while (available_insts != 0 && insts_to_decode < decodeWidth) {
ThreadID tid = *tid_itr;
if (!stalls[tid].decode && !fetchQueue[tid].empty()) {
auto inst = fetchQueue[tid].front();
const auto& inst = fetchQueue[tid].front();
toDecode->insts[toDecode->size++] = inst;
DPRINTF(Fetch, "[tid:%i][sn:%i]: Sending instruction to decode from "
"fetch queue. Fetch queue size: %i.\n",

View File

@@ -175,24 +175,24 @@ class DefaultIEW
void squash(ThreadID tid);
/** Wakes all dependents of a completed instruction. */
void wakeDependents(DynInstPtr &inst);
void wakeDependents(const DynInstPtr &inst);
/** Tells memory dependence unit that a memory instruction needs to be
* rescheduled. It will re-execute once replayMemInst() is called.
*/
void rescheduleMemInst(DynInstPtr &inst);
void rescheduleMemInst(const DynInstPtr &inst);
/** Re-executes all rescheduled memory instructions. */
void replayMemInst(DynInstPtr &inst);
void replayMemInst(const DynInstPtr &inst);
/** Moves memory instruction onto the list of cache blocked instructions */
void blockMemInst(DynInstPtr &inst);
void blockMemInst(const DynInstPtr &inst);
/** Notifies that the cache has become unblocked */
void cacheUnblocked();
/** Sends an instruction to commit through the time buffer. */
void instToCommit(DynInstPtr &inst);
void instToCommit(const DynInstPtr &inst);
/** Inserts unused instructions of a thread into the skid buffer. */
void skidInsert(ThreadID tid);
@@ -230,18 +230,18 @@ class DefaultIEW
bool hasStoresToWB(ThreadID tid) { return ldstQueue.hasStoresToWB(tid); }
/** Check misprediction */
void checkMisprediction(DynInstPtr &inst);
void checkMisprediction(const DynInstPtr &inst);
private:
/** Sends commit proper information for a squash due to a branch
* mispredict.
*/
void squashDueToBranch(DynInstPtr &inst, ThreadID tid);
void squashDueToBranch(const DynInstPtr &inst, ThreadID tid);
/** Sends commit proper information for a squash due to a memory order
* violation.
*/
void squashDueToMemOrder(DynInstPtr &inst, ThreadID tid);
void squashDueToMemOrder(const DynInstPtr &inst, ThreadID tid);
/** Sets Dispatch to blocked, and signals back to other stages to block. */
void block(ThreadID tid);
@@ -295,7 +295,7 @@ class DefaultIEW
private:
/** Updates execution stats based on the instruction. */
void updateExeInstStats(DynInstPtr &inst);
void updateExeInstStats(const DynInstPtr &inst);
/** Pointer to main time buffer used for backwards communication. */
TimeBuffer<TimeStruct> *timeBuffer;

View File

@@ -478,7 +478,7 @@ DefaultIEW<Impl>::squash(ThreadID tid)
template<class Impl>
void
DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
DefaultIEW<Impl>::squashDueToBranch(const DynInstPtr& inst, ThreadID tid)
{
DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s "
"[sn:%i].\n", tid, inst->pcState(), inst->seqNum);
@@ -503,7 +503,7 @@ DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid)
template<class Impl>
void
DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid)
DefaultIEW<Impl>::squashDueToMemOrder(const DynInstPtr& inst, ThreadID tid)
{
DPRINTF(IEW, "[tid:%i]: Memory violation, squashing violator and younger "
"insts, PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum);
@@ -566,28 +566,28 @@ DefaultIEW<Impl>::unblock(ThreadID tid)
template<class Impl>
void
DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst)
DefaultIEW<Impl>::wakeDependents(const DynInstPtr& inst)
{
instQueue.wakeDependents(inst);
}
template<class Impl>
void
DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst)
DefaultIEW<Impl>::rescheduleMemInst(const DynInstPtr& inst)
{
instQueue.rescheduleMemInst(inst);
}
template<class Impl>
void
DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst)
DefaultIEW<Impl>::replayMemInst(const DynInstPtr& inst)
{
instQueue.replayMemInst(inst);
}
template<class Impl>
void
DefaultIEW<Impl>::blockMemInst(DynInstPtr& inst)
DefaultIEW<Impl>::blockMemInst(const DynInstPtr& inst)
{
instQueue.blockMemInst(inst);
}
@@ -601,7 +601,7 @@ DefaultIEW<Impl>::cacheUnblocked()
template<class Impl>
void
DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
DefaultIEW<Impl>::instToCommit(const DynInstPtr& inst)
{
// This function should not be called after writebackInsts in a
// single cycle. That will cause problems with an instruction
@@ -1578,7 +1578,7 @@ DefaultIEW<Impl>::tick()
template <class Impl>
void
DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
DefaultIEW<Impl>::updateExeInstStats(const DynInstPtr& inst)
{
ThreadID tid = inst->threadNumber;
@@ -1610,7 +1610,7 @@ DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
template <class Impl>
void
DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst)
DefaultIEW<Impl>::checkMisprediction(const DynInstPtr& inst)
{
ThreadID tid = inst->threadNumber;

View File

@@ -65,6 +65,7 @@ struct O3CPUImpl
* what should be used, and not DynInst *.
*/
typedef RefCountingPtr<DynInst> DynInstPtr;
typedef RefCountingPtr<const DynInst> DynInstConstPtr;
/** The O3CPU type to be used. */
typedef FullO3CPU<O3CPUImpl> O3CPU;

View File

@@ -113,7 +113,7 @@ class InstructionQueue
public:
/** Construct a FU completion event. */
FUCompletion(DynInstPtr &_inst, int fu_idx,
FUCompletion(const DynInstPtr &_inst, int fu_idx,
InstructionQueue<Impl> *iq_ptr);
virtual void process();
@@ -176,15 +176,15 @@ class InstructionQueue
bool hasReadyInsts();
/** Inserts a new instruction into the IQ. */
void insert(DynInstPtr &new_inst);
void insert(const DynInstPtr &new_inst);
/** Inserts a new, non-speculative instruction into the IQ. */
void insertNonSpec(DynInstPtr &new_inst);
void insertNonSpec(const DynInstPtr &new_inst);
/** Inserts a memory or write barrier into the IQ to make sure
* loads and stores are ordered properly.
*/
void insertBarrier(DynInstPtr &barr_inst);
void insertBarrier(const DynInstPtr &barr_inst);
/** Returns the oldest scheduled instruction, and removes it from
* the list of instructions waiting to execute.
@@ -205,11 +205,11 @@ class InstructionQueue
* Records the instruction as the producer of a register without
* adding it to the rest of the IQ.
*/
void recordProducer(DynInstPtr &inst)
void recordProducer(const DynInstPtr &inst)
{ addToProducers(inst); }
/** Process FU completion event. */
void processFUCompletion(DynInstPtr &inst, int fu_idx);
void processFUCompletion(const DynInstPtr &inst, int fu_idx);
/**
* Schedules ready instructions, adding the ready ones (oldest first) to
@@ -227,37 +227,37 @@ class InstructionQueue
void commit(const InstSeqNum &inst, ThreadID tid = 0);
/** Wakes all dependents of a completed instruction. */
int wakeDependents(DynInstPtr &completed_inst);
int wakeDependents(const DynInstPtr &completed_inst);
/** Adds a ready memory instruction to the ready list. */
void addReadyMemInst(DynInstPtr &ready_inst);
void addReadyMemInst(const DynInstPtr &ready_inst);
/**
* Reschedules a memory instruction. It will be ready to issue once
* replayMemInst() is called.
*/
void rescheduleMemInst(DynInstPtr &resched_inst);
void rescheduleMemInst(const DynInstPtr &resched_inst);
/** Replays a memory instruction. It must be rescheduled first. */
void replayMemInst(DynInstPtr &replay_inst);
void replayMemInst(const DynInstPtr &replay_inst);
/** Completes a memory operation. */
void completeMemInst(DynInstPtr &completed_inst);
void completeMemInst(const DynInstPtr &completed_inst);
/**
* Defers a memory instruction when its DTB translation incurs a hw
* page table walk.
*/
void deferMemInst(DynInstPtr &deferred_inst);
void deferMemInst(const DynInstPtr &deferred_inst);
/** Defers a memory instruction when it is cache blocked. */
void blockMemInst(DynInstPtr &blocked_inst);
void blockMemInst(const DynInstPtr &blocked_inst);
/** Notify instruction queue that a previous blockage has resolved */
void cacheUnblocked();
/** Indicates an ordering violation between a store and a load. */
void violation(DynInstPtr &store, DynInstPtr &faulting_load);
void violation(const DynInstPtr &store, const DynInstPtr &faulting_load);
/**
* Squashes instructions for a thread. Squashing information is obtained
@@ -457,13 +457,13 @@ class InstructionQueue
std::vector<bool> regScoreboard;
/** Adds an instruction to the dependency graph, as a consumer. */
bool addToDependents(DynInstPtr &new_inst);
bool addToDependents(const DynInstPtr &new_inst);
/** Adds an instruction to the dependency graph, as a producer. */
void addToProducers(DynInstPtr &new_inst);
void addToProducers(const DynInstPtr &new_inst);
/** Moves an instruction to the ready queue if it is ready. */
void addIfReady(DynInstPtr &inst);
void addIfReady(const DynInstPtr &inst);
/** Debugging function to count how many entries are in the IQ. It does
* a linear walk through the instructions, so do not call this function

View File

@@ -60,7 +60,7 @@
using std::list;
template <class Impl>
InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
InstructionQueue<Impl>::FUCompletion::FUCompletion(const DynInstPtr &_inst,
int fu_idx, InstructionQueue<Impl> *iq_ptr)
: Event(Stat_Event_Pri, AutoDelete),
inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
@@ -585,7 +585,7 @@ InstructionQueue<Impl>::hasReadyInsts()
template <class Impl>
void
InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
InstructionQueue<Impl>::insert(const DynInstPtr &new_inst)
{
if (new_inst->isFloating()) {
fpInstQueueWrites++;
@@ -631,7 +631,7 @@ InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
template <class Impl>
void
InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
InstructionQueue<Impl>::insertNonSpec(const DynInstPtr &new_inst)
{
// @todo: Clean up this code; can do it by setting inst as unable
// to issue, then calling normal insert on the inst.
@@ -678,7 +678,7 @@ InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
template <class Impl>
void
InstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst)
InstructionQueue<Impl>::insertBarrier(const DynInstPtr &barr_inst)
{
memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
@@ -690,7 +690,7 @@ typename Impl::DynInstPtr
InstructionQueue<Impl>::getInstToExecute()
{
assert(!instsToExecute.empty());
DynInstPtr inst = instsToExecute.front();
DynInstPtr inst = std::move(instsToExecute.front());
instsToExecute.pop_front();
if (inst->isFloating()) {
fpInstQueueReads++;
@@ -757,7 +757,7 @@ InstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
template <class Impl>
void
InstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
InstructionQueue<Impl>::processFUCompletion(const DynInstPtr &inst, int fu_idx)
{
DPRINTF(IQ, "Processing FU completion [sn:%lli]\n", inst->seqNum);
assert(!cpu->switchedOut());
@@ -789,12 +789,12 @@ InstructionQueue<Impl>::scheduleReadyInsts()
IssueStruct *i2e_info = issueToExecuteQueue->access(0);
DynInstPtr mem_inst;
while (mem_inst = getDeferredMemInstToExecute()) {
while (mem_inst = std::move(getDeferredMemInstToExecute())) {
addReadyMemInst(mem_inst);
}
// See if any cache blocked instructions are able to be executed
while (mem_inst = getBlockedMemInstToExecute()) {
while (mem_inst = std::move(getBlockedMemInstToExecute())) {
addReadyMemInst(mem_inst);
}
@@ -995,7 +995,7 @@ InstructionQueue<Impl>::commit(const InstSeqNum &inst, ThreadID tid)
template <class Impl>
int
InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
InstructionQueue<Impl>::wakeDependents(const DynInstPtr &completed_inst)
{
int dependents = 0;
@@ -1079,7 +1079,7 @@ InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
template <class Impl>
void
InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
InstructionQueue<Impl>::addReadyMemInst(const DynInstPtr &ready_inst)
{
OpClass op_class = ready_inst->opClass();
@@ -1102,7 +1102,7 @@ InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
template <class Impl>
void
InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
InstructionQueue<Impl>::rescheduleMemInst(const DynInstPtr &resched_inst)
{
DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);
@@ -1116,14 +1116,14 @@ InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
template <class Impl>
void
InstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst)
InstructionQueue<Impl>::replayMemInst(const DynInstPtr &replay_inst)
{
memDepUnit[replay_inst->threadNumber].replay();
}
template <class Impl>
void
InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
InstructionQueue<Impl>::completeMemInst(const DynInstPtr &completed_inst)
{
ThreadID tid = completed_inst->threadNumber;
@@ -1140,14 +1140,14 @@ InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
template <class Impl>
void
InstructionQueue<Impl>::deferMemInst(DynInstPtr &deferred_inst)
InstructionQueue<Impl>::deferMemInst(const DynInstPtr &deferred_inst)
{
deferredMemInsts.push_back(deferred_inst);
}
template <class Impl>
void
InstructionQueue<Impl>::blockMemInst(DynInstPtr &blocked_inst)
InstructionQueue<Impl>::blockMemInst(const DynInstPtr &blocked_inst)
{
blocked_inst->translationStarted(false);
blocked_inst->translationCompleted(false);
@@ -1173,7 +1173,7 @@ InstructionQueue<Impl>::getDeferredMemInstToExecute()
for (ListIt it = deferredMemInsts.begin(); it != deferredMemInsts.end();
++it) {
if ((*it)->translationCompleted() || (*it)->isSquashed()) {
DynInstPtr mem_inst = *it;
DynInstPtr mem_inst = std::move(*it);
deferredMemInsts.erase(it);
return mem_inst;
}
@@ -1188,7 +1188,7 @@ InstructionQueue<Impl>::getBlockedMemInstToExecute()
if (retryMemInsts.empty()) {
return nullptr;
} else {
DynInstPtr mem_inst = retryMemInsts.front();
DynInstPtr mem_inst = std::move(retryMemInsts.front());
retryMemInsts.pop_front();
return mem_inst;
}
@@ -1196,8 +1196,8 @@ InstructionQueue<Impl>::getBlockedMemInstToExecute()
template <class Impl>
void
InstructionQueue<Impl>::violation(DynInstPtr &store,
DynInstPtr &faulting_load)
InstructionQueue<Impl>::violation(const DynInstPtr &store,
const DynInstPtr &faulting_load)
{
intInstQueueWrites++;
memDepUnit[store->threadNumber].violation(store, faulting_load);
@@ -1364,7 +1364,7 @@ InstructionQueue<Impl>::doSquash(ThreadID tid)
template <class Impl>
bool
InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
InstructionQueue<Impl>::addToDependents(const DynInstPtr &new_inst)
{
// Loop through the instruction's source registers, adding
// them to the dependency list if they are not ready.
@@ -1412,7 +1412,7 @@ InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
template <class Impl>
void
InstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst)
InstructionQueue<Impl>::addToProducers(const DynInstPtr &new_inst)
{
// Nothing really needs to be marked when an instruction becomes
// the producer of a register's value, but for convenience a ptr
@@ -1448,7 +1448,7 @@ InstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst)
template <class Impl>
void
InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
InstructionQueue<Impl>::addIfReady(const DynInstPtr &inst)
{
// If the instruction now has all of its source registers
// available, then add it to the list of ready instructions.

View File

@@ -106,15 +106,15 @@ class LSQ {
{ thread[tid].tick(); }
/** Inserts a load into the LSQ. */
void insertLoad(DynInstPtr &load_inst);
void insertLoad(const DynInstPtr &load_inst);
/** Inserts a store into the LSQ. */
void insertStore(DynInstPtr &store_inst);
void insertStore(const DynInstPtr &store_inst);
/** Executes a load. */
Fault executeLoad(DynInstPtr &inst);
Fault executeLoad(const DynInstPtr &inst);
/** Executes a store. */
Fault executeStore(DynInstPtr &inst);
Fault executeStore(const DynInstPtr &inst);
/**
* Commits loads up until the given sequence number for a specific thread.

View File

@@ -257,7 +257,7 @@ LSQ<Impl>::tick()
template<class Impl>
void
LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
LSQ<Impl>::insertLoad(const DynInstPtr &load_inst)
{
ThreadID tid = load_inst->threadNumber;
@@ -266,7 +266,7 @@ LSQ<Impl>::insertLoad(DynInstPtr &load_inst)
template<class Impl>
void
LSQ<Impl>::insertStore(DynInstPtr &store_inst)
LSQ<Impl>::insertStore(const DynInstPtr &store_inst)
{
ThreadID tid = store_inst->threadNumber;
@@ -275,7 +275,7 @@ LSQ<Impl>::insertStore(DynInstPtr &store_inst)
template<class Impl>
Fault
LSQ<Impl>::executeLoad(DynInstPtr &inst)
LSQ<Impl>::executeLoad(const DynInstPtr &inst)
{
ThreadID tid = inst->threadNumber;
@@ -284,7 +284,7 @@ LSQ<Impl>::executeLoad(DynInstPtr &inst)
template<class Impl>
Fault
LSQ<Impl>::executeStore(DynInstPtr &inst)
LSQ<Impl>::executeStore(const DynInstPtr &inst)
{
ThreadID tid = inst->threadNumber;

View File

@@ -116,11 +116,11 @@ class LSQUnit {
void tick() { usedStorePorts = 0; }
/** Inserts an instruction. */
void insert(DynInstPtr &inst);
void insert(const DynInstPtr &inst);
/** Inserts a load instruction. */
void insertLoad(DynInstPtr &load_inst);
void insertLoad(const DynInstPtr &load_inst);
/** Inserts a store instruction. */
void insertStore(DynInstPtr &store_inst);
void insertStore(const DynInstPtr &store_inst);
/** Check for ordering violations in the LSQ. For a store squash if we
* ever find a conflicting load. For a load, only squash if we
@@ -128,7 +128,7 @@ class LSQUnit {
* @param load_idx index to start checking at
* @param inst the instruction to check
*/
Fault checkViolations(int load_idx, DynInstPtr &inst);
Fault checkViolations(int load_idx, const DynInstPtr &inst);
/** Check if an incoming invalidate hits in the lsq on a load
* that might have issued out of order wrt another load beacuse
@@ -137,11 +137,11 @@ class LSQUnit {
void checkSnoop(PacketPtr pkt);
/** Executes a load instruction. */
Fault executeLoad(DynInstPtr &inst);
Fault executeLoad(const DynInstPtr &inst);
Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; }
/** Executes a store instruction. */
Fault executeStore(DynInstPtr &inst);
Fault executeStore(const DynInstPtr &inst);
/** Commits the head load. */
void commitLoad();
@@ -233,7 +233,7 @@ class LSQUnit {
void resetState();
/** Writes back the instruction, sending it to IEW. */
void writeback(DynInstPtr &inst, PacketPtr pkt);
void writeback(const DynInstPtr &inst, PacketPtr pkt);
/** Writes back a store that couldn't be completed the previous cycle. */
void writebackPendingStore();
@@ -313,7 +313,8 @@ class LSQUnit {
class WritebackEvent : public Event {
public:
/** Constructs a writeback event. */
WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr);
WritebackEvent(const DynInstPtr &_inst, PacketPtr pkt,
LSQUnit *lsq_ptr);
/** Processes the writeback event. */
void process();
@@ -348,7 +349,7 @@ class LSQUnit {
}
/** Constructs a store queue entry for a given instruction. */
SQEntry(DynInstPtr &_inst)
SQEntry(const DynInstPtr &_inst)
: inst(_inst), req(NULL), sreqLow(NULL), sreqHigh(NULL), size(0),
isSplit(0), canWB(0), committed(0), completed(0), isAllZeros(0)
{

View File

@@ -61,8 +61,8 @@
#include "mem/request.hh"
template<class Impl>
LSQUnit<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst, PacketPtr _pkt,
LSQUnit *lsq_ptr)
LSQUnit<Impl>::WritebackEvent::WritebackEvent(const DynInstPtr &_inst,
PacketPtr _pkt, LSQUnit *lsq_ptr)
: Event(Default_Pri, AutoDelete),
inst(_inst), pkt(_pkt), lsqPtr(lsq_ptr)
{
@@ -339,7 +339,7 @@ LSQUnit<Impl>::resizeSQ(unsigned size)
template <class Impl>
void
LSQUnit<Impl>::insert(DynInstPtr &inst)
LSQUnit<Impl>::insert(const DynInstPtr &inst)
{
assert(inst->isMemRef());
@@ -356,7 +356,7 @@ LSQUnit<Impl>::insert(DynInstPtr &inst)
template <class Impl>
void
LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
LSQUnit<Impl>::insertLoad(const DynInstPtr &load_inst)
{
assert((loadTail + 1) % LQEntries != loadHead);
assert(loads < LQEntries);
@@ -381,7 +381,7 @@ LSQUnit<Impl>::insertLoad(DynInstPtr &load_inst)
template <class Impl>
void
LSQUnit<Impl>::insertStore(DynInstPtr &store_inst)
LSQUnit<Impl>::insertStore(const DynInstPtr &store_inst)
{
// Make sure it is not full before inserting an instruction.
assert((storeTail + 1) % SQEntries != storeHead);
@@ -525,7 +525,7 @@ LSQUnit<Impl>::checkSnoop(PacketPtr pkt)
template <class Impl>
Fault
LSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst)
LSQUnit<Impl>::checkViolations(int load_idx, const DynInstPtr &inst)
{
Addr inst_eff_addr1 = inst->effAddr >> depCheckShift;
Addr inst_eff_addr2 = (inst->effAddr + inst->effSize - 1) >> depCheckShift;
@@ -605,7 +605,7 @@ LSQUnit<Impl>::checkViolations(int load_idx, DynInstPtr &inst)
template <class Impl>
Fault
LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
LSQUnit<Impl>::executeLoad(const DynInstPtr &inst)
{
using namespace TheISA;
// Execute a specific load.
@@ -654,7 +654,7 @@ LSQUnit<Impl>::executeLoad(DynInstPtr &inst)
template <class Impl>
Fault
LSQUnit<Impl>::executeStore(DynInstPtr &store_inst)
LSQUnit<Impl>::executeStore(const DynInstPtr &store_inst)
{
using namespace TheISA;
// Make sure that a store exists.
@@ -1105,7 +1105,7 @@ LSQUnit<Impl>::storePostSend(PacketPtr pkt)
template <class Impl>
void
LSQUnit<Impl>::writeback(DynInstPtr &inst, PacketPtr pkt)
LSQUnit<Impl>::writeback(const DynInstPtr &inst, PacketPtr pkt)
{
iewStage->wakeCPU();

View File

@@ -85,6 +85,7 @@ class MemDepUnit
public:
typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::DynInstConstPtr DynInstConstPtr;
/** Empty constructor. Must call init() prior to using in this case. */
MemDepUnit();
@@ -117,22 +118,22 @@ class MemDepUnit
void setIQ(InstructionQueue<Impl> *iq_ptr);
/** Inserts a memory instruction. */
void insert(DynInstPtr &inst);
void insert(const DynInstPtr &inst);
/** Inserts a non-speculative memory instruction. */
void insertNonSpec(DynInstPtr &inst);
void insertNonSpec(const DynInstPtr &inst);
/** Inserts a barrier instruction. */
void insertBarrier(DynInstPtr &barr_inst);
void insertBarrier(const DynInstPtr &barr_inst);
/** Indicate that an instruction has its registers ready. */
void regsReady(DynInstPtr &inst);
void regsReady(const DynInstPtr &inst);
/** Indicate that a non-speculative instruction is ready. */
void nonSpecInstReady(DynInstPtr &inst);
void nonSpecInstReady(const DynInstPtr &inst);
/** Reschedules an instruction to be re-executed. */
void reschedule(DynInstPtr &inst);
void reschedule(const DynInstPtr &inst);
/** Replays all instructions that have been rescheduled by moving them to
* the ready list.
@@ -140,13 +141,13 @@ class MemDepUnit
void replay();
/** Completes a memory instruction. */
void completed(DynInstPtr &inst);
void completed(const DynInstPtr &inst);
/** Completes a barrier instruction. */
void completeBarrier(DynInstPtr &inst);
void completeBarrier(const DynInstPtr &inst);
/** Wakes any dependents of a memory instruction. */
void wakeDependents(DynInstPtr &inst);
void wakeDependents(const DynInstPtr &inst);
/** Squashes all instructions up until a given sequence number for a
* specific thread.
@@ -154,10 +155,11 @@ class MemDepUnit
void squash(const InstSeqNum &squashed_num, ThreadID tid);
/** Indicates an ordering violation between a store and a younger load. */
void violation(DynInstPtr &store_inst, DynInstPtr &violating_load);
void violation(const DynInstPtr &store_inst,
const DynInstPtr &violating_load);
/** Issues the given instruction */
void issue(DynInstPtr &inst);
void issue(const DynInstPtr &inst);
/** Debugging function to dump the lists of instructions. */
void dumpLists();
@@ -176,7 +178,7 @@ class MemDepUnit
class MemDepEntry {
public:
/** Constructs a memory dependence entry. */
MemDepEntry(DynInstPtr &new_inst)
MemDepEntry(const DynInstPtr &new_inst)
: inst(new_inst), regsReady(false), memDepReady(false),
completed(false), squashed(false)
{
@@ -232,7 +234,7 @@ class MemDepUnit
};
/** Finds the memory dependence entry in the hash map. */
inline MemDepEntryPtr &findInHash(const DynInstPtr &inst);
inline MemDepEntryPtr &findInHash(const DynInstConstPtr& inst);
/** Moves an entry to the ready list. */
inline void moveToReady(MemDepEntryPtr &ready_inst_entry);

View File

@@ -171,7 +171,7 @@ MemDepUnit<MemDepPred, Impl>::setIQ(InstructionQueue<Impl> *iq_ptr)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::insert(const DynInstPtr &inst)
{
ThreadID tid = inst->threadNumber;
@@ -268,7 +268,7 @@ MemDepUnit<MemDepPred, Impl>::insert(DynInstPtr &inst)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::insertNonSpec(const DynInstPtr &inst)
{
ThreadID tid = inst->threadNumber;
@@ -304,7 +304,7 @@ MemDepUnit<MemDepPred, Impl>::insertNonSpec(DynInstPtr &inst)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst)
MemDepUnit<MemDepPred, Impl>::insertBarrier(const DynInstPtr &barr_inst)
{
InstSeqNum barr_sn = barr_inst->seqNum;
// Memory barriers block loads and stores, write barriers only stores.
@@ -340,7 +340,7 @@ MemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::regsReady(const DynInstPtr &inst)
{
DPRINTF(MemDepUnit, "Marking registers as ready for "
"instruction PC %s [sn:%lli].\n",
@@ -363,7 +363,7 @@ MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(const DynInstPtr &inst)
{
DPRINTF(MemDepUnit, "Marking non speculative "
"instruction PC %s as ready [sn:%lli].\n",
@@ -376,7 +376,7 @@ MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::reschedule(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::reschedule(const DynInstPtr &inst)
{
instsToReplay.push_back(inst);
}
@@ -404,7 +404,7 @@ MemDepUnit<MemDepPred, Impl>::replay()
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::completed(const DynInstPtr &inst)
{
DPRINTF(MemDepUnit, "Completed mem instruction PC %s [sn:%lli].\n",
inst->pcState(), inst->seqNum);
@@ -428,7 +428,7 @@ MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::completeBarrier(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::completeBarrier(const DynInstPtr &inst)
{
wakeDependents(inst);
completed(inst);
@@ -449,7 +449,7 @@ MemDepUnit<MemDepPred, Impl>::completeBarrier(DynInstPtr &inst)
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::wakeDependents(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::wakeDependents(const DynInstPtr &inst)
{
// Only stores and barriers have dependents.
if (!inst->isStore() && !inst->isMemBarrier() && !inst->isWriteBarrier()) {
@@ -536,8 +536,8 @@ MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num,
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
DynInstPtr &violating_load)
MemDepUnit<MemDepPred, Impl>::violation(const DynInstPtr &store_inst,
const DynInstPtr &violating_load)
{
DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
" load: %#x, store: %#x\n", violating_load->instAddr(),
@@ -548,7 +548,7 @@ MemDepUnit<MemDepPred, Impl>::violation(DynInstPtr &store_inst,
template <class MemDepPred, class Impl>
void
MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::issue(const DynInstPtr &inst)
{
DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n",
inst->instAddr(), inst->seqNum);
@@ -558,7 +558,7 @@ MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
template <class MemDepPred, class Impl>
inline typename MemDepUnit<MemDepPred,Impl>::MemDepEntryPtr &
MemDepUnit<MemDepPred, Impl>::findInHash(const DynInstPtr &inst)
MemDepUnit<MemDepPred, Impl>::findInHash(const DynInstConstPtr &inst)
{
MemDepHashIt hash_it = memDepHash.find(inst->seqNum);

View File

@@ -124,18 +124,23 @@ ElasticTrace::regEtraceListeners()
// each probe point.
listeners.push_back(new ProbeListenerArg<ElasticTrace, RequestPtr>(this,
"FetchRequest", &ElasticTrace::fetchReqTrace));
listeners.push_back(new ProbeListenerArg<ElasticTrace, DynInstPtr>(this,
"Execute", &ElasticTrace::recordExecTick));
listeners.push_back(new ProbeListenerArg<ElasticTrace, DynInstPtr>(this,
"ToCommit", &ElasticTrace::recordToCommTick));
listeners.push_back(new ProbeListenerArg<ElasticTrace, DynInstPtr>(this,
"Rename", &ElasticTrace::updateRegDep));
listeners.push_back(new ProbeListenerArg<ElasticTrace,
DynInstConstPtr>(this, "Execute",
&ElasticTrace::recordExecTick));
listeners.push_back(new ProbeListenerArg<ElasticTrace,
DynInstConstPtr>(this, "ToCommit",
&ElasticTrace::recordToCommTick));
listeners.push_back(new ProbeListenerArg<ElasticTrace,
DynInstConstPtr>(this, "Rename",
&ElasticTrace::updateRegDep));
listeners.push_back(new ProbeListenerArg<ElasticTrace, SeqNumRegPair>(this,
"SquashInRename", &ElasticTrace::removeRegDepMapEntry));
listeners.push_back(new ProbeListenerArg<ElasticTrace, DynInstPtr>(this,
"Squash", &ElasticTrace::addSquashedInst));
listeners.push_back(new ProbeListenerArg<ElasticTrace, DynInstPtr>(this,
"Commit", &ElasticTrace::addCommittedInst));
listeners.push_back(new ProbeListenerArg<ElasticTrace,
DynInstConstPtr>(this, "Squash",
&ElasticTrace::addSquashedInst));
listeners.push_back(new ProbeListenerArg<ElasticTrace,
DynInstConstPtr>(this, "Commit",
&ElasticTrace::addCommittedInst));
allProbesReg = true;
}
@@ -162,7 +167,7 @@ ElasticTrace::fetchReqTrace(const RequestPtr &req)
}
void
ElasticTrace::recordExecTick(const DynInstPtr &dyn_inst)
ElasticTrace::recordExecTick(const DynInstConstPtr& dyn_inst)
{
// In a corner case, a retired instruction is propagated backward to the
@@ -199,7 +204,7 @@ ElasticTrace::recordExecTick(const DynInstPtr &dyn_inst)
}
void
ElasticTrace::recordToCommTick(const DynInstPtr &dyn_inst)
ElasticTrace::recordToCommTick(const DynInstConstPtr& dyn_inst)
{
// If tracing has just been enabled then the instruction at this stage of
// execution is far enough that we cannot gather info about its past like
@@ -220,7 +225,7 @@ ElasticTrace::recordToCommTick(const DynInstPtr &dyn_inst)
}
void
ElasticTrace::updateRegDep(const DynInstPtr &dyn_inst)
ElasticTrace::updateRegDep(const DynInstConstPtr& dyn_inst)
{
// Get the sequence number of the instruction
InstSeqNum seq_num = dyn_inst->seqNum;
@@ -298,7 +303,7 @@ ElasticTrace::removeRegDepMapEntry(const SeqNumRegPair &inst_reg_pair)
}
void
ElasticTrace::addSquashedInst(const DynInstPtr &head_inst)
ElasticTrace::addSquashedInst(const DynInstConstPtr& head_inst)
{
// If the squashed instruction was squashed before being processed by
// execute stage then it will not be in the temporary store. In this case
@@ -326,7 +331,7 @@ ElasticTrace::addSquashedInst(const DynInstPtr &head_inst)
}
void
ElasticTrace::addCommittedInst(const DynInstPtr &head_inst)
ElasticTrace::addCommittedInst(const DynInstConstPtr& head_inst)
{
DPRINTFR(ElasticTrace, "Attempt to add committed inst [sn:%lli]\n",
head_inst->seqNum);
@@ -385,7 +390,7 @@ ElasticTrace::addCommittedInst(const DynInstPtr &head_inst)
}
void
ElasticTrace::addDepTraceRecord(const DynInstPtr &head_inst,
ElasticTrace::addDepTraceRecord(const DynInstConstPtr& head_inst,
InstExecInfo* exec_info_ptr, bool commit)
{
// Create a record to assign dynamic intruction related fields.
@@ -648,7 +653,7 @@ ElasticTrace::hasCompCompleted(TraceInfo* past_record,
}
void
ElasticTrace::clearTempStoreUntil(const DynInstPtr head_inst)
ElasticTrace::clearTempStoreUntil(const DynInstConstPtr& head_inst)
{
// Clear from temp store starting with the execution info object
// corresponding the head_inst and continue clearing by decrementing the

View File

@@ -90,6 +90,7 @@ class ElasticTrace : public ProbeListenerObject
public:
typedef typename O3CPUImpl::DynInstPtr DynInstPtr;
typedef typename O3CPUImpl::DynInstConstPtr DynInstConstPtr;
typedef typename std::pair<InstSeqNum, PhysRegIndex> SeqNumRegPair;
/** Trace record types corresponding to instruction node types */
@@ -132,7 +133,7 @@ class ElasticTrace : public ProbeListenerObject
*
* @param dyn_inst pointer to dynamic instruction in flight
*/
void recordExecTick(const DynInstPtr &dyn_inst);
void recordExecTick(const DynInstConstPtr& dyn_inst);
/**
* Populate the timestamp field in an InstExecInfo object for an
@@ -141,7 +142,7 @@ class ElasticTrace : public ProbeListenerObject
*
* @param dyn_inst pointer to dynamic instruction in flight
*/
void recordToCommTick(const DynInstPtr &dyn_inst);
void recordToCommTick(const DynInstConstPtr& dyn_inst);
/**
* Record a Read After Write physical register dependency if there has
@@ -152,7 +153,7 @@ class ElasticTrace : public ProbeListenerObject
*
* @param dyn_inst pointer to dynamic instruction in flight
*/
void updateRegDep(const DynInstPtr &dyn_inst);
void updateRegDep(const DynInstConstPtr& dyn_inst);
/**
* When an instruction gets squashed the destination register mapped to it
@@ -169,14 +170,14 @@ class ElasticTrace : public ProbeListenerObject
*
* @param head_inst pointer to dynamic instruction to be squashed
*/
void addSquashedInst(const DynInstPtr &head_inst);
void addSquashedInst(const DynInstConstPtr& head_inst);
/**
* Add an instruction that is at the head of the ROB and is committed.
*
* @param head_inst pointer to dynamic instruction to be committed
*/
void addCommittedInst(const DynInstPtr &head_inst);
void addCommittedInst(const DynInstConstPtr& head_inst);
/** Register statistics for the elastic trace. */
void regStats();
@@ -385,7 +386,7 @@ class ElasticTrace : public ProbeListenerObject
* @param exec_info_ptr Pointer to InstExecInfo for that instruction
* @param commit True if instruction is committed, false if squashed
*/
void addDepTraceRecord(const DynInstPtr &head_inst,
void addDepTraceRecord(const DynInstConstPtr& head_inst,
InstExecInfo* exec_info_ptr, bool commit);
/**
@@ -394,7 +395,7 @@ class ElasticTrace : public ProbeListenerObject
*
* @param head_inst pointer to dynamic instruction
*/
void clearTempStoreUntil(const DynInstPtr head_inst);
void clearTempStoreUntil(const DynInstConstPtr& head_inst);
/**
* Calculate the computational delay between an instruction and a

View File

@@ -42,14 +42,14 @@
#include "base/trace.hh"
#include "debug/SimpleTrace.hh"
void SimpleTrace::traceCommit(const O3CPUImpl::DynInstPtr &dynInst)
void SimpleTrace::traceCommit(const O3CPUImpl::DynInstConstPtr& dynInst)
{
DPRINTFR(SimpleTrace, "[%s]: Commit 0x%08x %s.\n", name(),
dynInst->instAddr(),
dynInst->staticInst->disassemble(dynInst->instAddr()));
}
void SimpleTrace::traceFetch(const O3CPUImpl::DynInstPtr &dynInst)
void SimpleTrace::traceFetch(const O3CPUImpl::DynInstConstPtr& dynInst)
{
DPRINTFR(SimpleTrace, "[%s]: Fetch 0x%08x %s.\n", name(),
dynInst->instAddr(),
@@ -58,9 +58,12 @@ void SimpleTrace::traceFetch(const O3CPUImpl::DynInstPtr &dynInst)
void SimpleTrace::regProbeListeners()
{
typedef ProbeListenerArg<SimpleTrace, O3CPUImpl::DynInstPtr> DynInstListener;
listeners.push_back(new DynInstListener(this, "Commit", &SimpleTrace::traceCommit));
listeners.push_back(new DynInstListener(this, "Fetch", &SimpleTrace::traceFetch));
typedef ProbeListenerArg<SimpleTrace,
O3CPUImpl::DynInstConstPtr> DynInstListener;
listeners.push_back(new DynInstListener(this, "Commit",
&SimpleTrace::traceCommit));
listeners.push_back(new DynInstListener(this, "Fetch",
&SimpleTrace::traceFetch));
}
SimpleTrace*

View File

@@ -66,8 +66,8 @@ class SimpleTrace : public ProbeListenerObject {
const std::string name() const { return ProbeListenerObject::name() + ".trace"; }
private:
void traceFetch(const O3CPUImpl::DynInstPtr &dynInst);
void traceCommit(const O3CPUImpl::DynInstPtr &dynInst);
void traceFetch(const O3CPUImpl::DynInstConstPtr& dynInst);
void traceCommit(const O3CPUImpl::DynInstConstPtr& dynInst);
};
#endif//__CPU_O3_PROBE_SIMPLE_TRACE_HH__

View File

@@ -252,10 +252,10 @@ class DefaultRename
void removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid);
/** Renames the source registers of an instruction. */
inline void renameSrcRegs(DynInstPtr &inst, ThreadID tid);
inline void renameSrcRegs(const DynInstPtr &inst, ThreadID tid);
/** Renames the destination registers of an instruction. */
inline void renameDestRegs(DynInstPtr &inst, ThreadID tid);
inline void renameDestRegs(const DynInstPtr &inst, ThreadID tid);
/** Calculates the number of free ROB entries for a specific thread. */
inline int calcFreeROBEntries(ThreadID tid);

View File

@@ -524,8 +524,6 @@ DefaultRename<Impl>::renameInsts(ThreadID tid)
++renameRunCycles;
}
DynInstPtr inst;
// Will have to do a different calculation for the number of free
// entries.
int free_rob_entries = calcFreeROBEntries(tid);
@@ -596,7 +594,7 @@ DefaultRename<Impl>::renameInsts(ThreadID tid)
assert(!insts_to_rename.empty());
inst = insts_to_rename.front();
DynInstPtr inst = insts_to_rename.front();
//For all kind of instructions, check ROB and IQ first
//For load instruction, check LQ size and take into account the inflight loads
@@ -787,7 +785,7 @@ DefaultRename<Impl>::sortInsts()
{
int insts_from_decode = fromDecode->size;
for (int i = 0; i < insts_from_decode; ++i) {
DynInstPtr inst = fromDecode->insts[i];
const DynInstPtr &inst = fromDecode->insts[i];
insts[inst->threadNumber].push_back(inst);
#if TRACING_ON
if (DTRACE(O3PipeView)) {
@@ -1008,7 +1006,7 @@ DefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, ThreadID tid)
template <class Impl>
inline void
DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
DefaultRename<Impl>::renameSrcRegs(const DynInstPtr &inst, ThreadID tid)
{
ThreadContext *tc = inst->tcBase();
RenameMap *map = renameMap[tid];
@@ -1068,7 +1066,7 @@ DefaultRename<Impl>::renameSrcRegs(DynInstPtr &inst, ThreadID tid)
template <class Impl>
inline void
DefaultRename<Impl>::renameDestRegs(DynInstPtr &inst, ThreadID tid)
DefaultRename<Impl>::renameDestRegs(const DynInstPtr &inst, ThreadID tid)
{
ThreadContext *tc = inst->tcBase();
RenameMap *map = renameMap[tid];

View File

@@ -114,7 +114,7 @@ class ROB
* ROB for the new instruction.
* @param inst The instruction being inserted into the ROB.
*/
void insertInst(DynInstPtr &inst);
void insertInst(const DynInstPtr &inst);
/** Returns pointer to the head instruction within the ROB. There is
* no guarantee as to the return value if the ROB is empty.
@@ -126,7 +126,7 @@ class ROB
* the ROB.
* @return Pointer to the DynInst that is at the head of the ROB.
*/
DynInstPtr readHeadInst(ThreadID tid);
const DynInstPtr &readHeadInst(ThreadID tid);
/** Returns a pointer to the instruction with the given sequence if it is
* in the ROB.

View File

@@ -209,7 +209,7 @@ ROB<Impl>::countInsts(ThreadID tid)
template <class Impl>
void
ROB<Impl>::insertInst(DynInstPtr &inst)
ROB<Impl>::insertInst(const DynInstPtr &inst)
{
assert(inst);
@@ -252,10 +252,11 @@ ROB<Impl>::retireHead(ThreadID tid)
assert(numInstsInROB > 0);
// Get the head ROB instruction.
// Get the head ROB instruction by copying it and remove it from the list
InstIt head_it = instList[tid].begin();
DynInstPtr head_inst = (*head_it);
DynInstPtr head_inst = std::move(*head_it);
instList[tid].erase(head_it);
assert(head_inst->readyToCommit());
@@ -269,8 +270,6 @@ ROB<Impl>::retireHead(ThreadID tid)
head_inst->clearInROB();
head_inst->setCommitted();
instList[tid].erase(head_it);
//Update "Global" Head of ROB
updateHead();
@@ -513,7 +512,7 @@ ROB<Impl>::squash(InstSeqNum squash_num, ThreadID tid)
}
template <class Impl>
typename Impl::DynInstPtr
const typename Impl::DynInstPtr&
ROB<Impl>::readHeadInst(ThreadID tid)
{
if (threadEntries[tid] != 0) {

View File

@@ -482,7 +482,7 @@ class SimpleExecContext : public ExecContext {
return thread->simPalCheck(palFunc);
}
bool readPredicate() override
bool readPredicate() const override
{
return thread->readPredicate();
}