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:
committed by
Giacomo Gabrielli
parent
338a173e82
commit
0c50a0b4fe
@@ -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; }
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -292,7 +292,7 @@ class ExecContext : public ::ExecContext
|
||||
}
|
||||
|
||||
bool
|
||||
readPredicate() override
|
||||
readPredicate() const override
|
||||
{
|
||||
return thread.readPredicate();
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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*
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -482,7 +482,7 @@ class SimpleExecContext : public ExecContext {
|
||||
return thread->simPalCheck(palFunc);
|
||||
}
|
||||
|
||||
bool readPredicate() override
|
||||
bool readPredicate() const override
|
||||
{
|
||||
return thread->readPredicate();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user