cpu-minor: Convert the rest of the CPU to use PCStateBase *|&.

Change-Id: I528622cd5ad82dbcefe1462401841c6e28359ed3
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52049
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: ZHENGRONG WANG <seanyukigeek@gmail.com>
Maintainer: ZHENGRONG WANG <seanyukigeek@gmail.com>
This commit is contained in:
Gabe Black
2021-10-11 13:47:59 -07:00
parent f9cbef9bf7
commit 7497caefa5
8 changed files with 121 additions and 122 deletions

View File

@@ -184,7 +184,7 @@ Decode::evaluate()
* static_inst. */
static_micro_inst =
static_inst->fetchMicroop(
decode_info.microopPC.microPC());
decode_info.microopPC->microPC());
output_inst =
new MinorDynInst(static_micro_inst, inst->id);
@@ -201,19 +201,18 @@ Decode::evaluate()
DPRINTF(Decode, "Microop decomposition inputIndex:"
" %d output_index: %d lastMicroop: %s microopPC:"
" %d.%d inst: %d\n",
" %s inst: %d\n",
decode_info.inputIndex, output_index,
(static_micro_inst->isLastMicroop() ?
"true" : "false"),
decode_info.microopPC.instAddr(),
decode_info.microopPC.microPC(),
*decode_info.microopPC,
*output_inst);
/* Acknowledge that the static_inst isn't mine, it's my
* parent macro-op's */
parent_static_inst = static_inst;
static_micro_inst->advancePC(decode_info.microopPC);
static_micro_inst->advancePC(*decode_info.microopPC);
/* Step input if this is the last micro-op */
if (static_micro_inst->isLastMicroop()) {

View File

@@ -94,40 +94,35 @@ class Decode : public Named
struct DecodeThreadInfo
{
/** Default Constructor */
DecodeThreadInfo() :
inputIndex(0),
inMacroop(false),
execSeqNum(InstId::firstExecSeqNum),
blocked(false)
{ }
DecodeThreadInfo() {}
DecodeThreadInfo(const DecodeThreadInfo& other) :
inputIndex(other.inputIndex),
inMacroop(other.inMacroop),
execSeqNum(other.execSeqNum),
blocked(other.blocked)
{ }
{
set(microopPC, other.microopPC);
}
/** Index into the inputBuffer's head marking the start of unhandled
* instructions */
unsigned int inputIndex;
unsigned int inputIndex = 0;
/** True when we're in the process of decomposing a micro-op and
* microopPC will be valid. This is only the case when there isn't
* sufficient space in Executes input buffer to take the whole of a
* decomposed instruction and some of that instructions micro-ops must
* be generated in a later cycle */
bool inMacroop;
TheISA::PCState microopPC;
bool inMacroop = false;
std::unique_ptr<PCStateBase> microopPC;
/** Source of execSeqNums to number instructions. */
InstSeqNum execSeqNum;
InstSeqNum execSeqNum = InstId::firstExecSeqNum;
/** Blocked indication for report */
bool blocked;
bool blocked = false;
};
std::vector<DecodeThreadInfo> decodeInfo;

View File

@@ -83,6 +83,9 @@ Fetch1::Fetch1(const std::string &name_,
numFetchesInMemorySystem(0),
numFetchesInITLB(0)
{
for (auto &info: fetchInfo)
info.pc.reset(params.isa[0]->newPCState());
if (lineSnap == 0) {
lineSnap = cpu.cacheLineSize();
DPRINTF(Fetch, "lineSnap set to cache line size of: %d\n",
@@ -511,8 +514,8 @@ Fetch1::changeStream(const BranchData &branch)
thread.state = FetchRunning;
break;
}
thread.pc = branch.target;
thread.fetchAddr = thread.pc.instAddr();
set(thread.pc, branch.target);
thread.fetchAddr = thread.pc->instAddr();
}
void
@@ -546,7 +549,7 @@ Fetch1::processResponse(Fetch1::FetchRequestPtr response,
/* Make sequence numbers valid in return */
line.id = response->id;
/* Set the PC in case there was a sequence change */
line.pc = thread.pc;
set(line.pc, thread.pc);
/* Set fetch address to virtual address */
line.fetchAddr = response->pc;
/* Set the lineBase, which is a sizeof(MachInst) aligned address <=
@@ -715,12 +718,11 @@ Fetch1::wakeupFetch(ThreadID tid)
{
ThreadContext *thread_ctx = cpu.getContext(tid);
Fetch1ThreadInfo &thread = fetchInfo[tid];
thread.pc = thread_ctx->pcState();
thread.fetchAddr = thread.pc.instAddr();
set(thread.pc, thread_ctx->pcState());
thread.fetchAddr = thread.pc->instAddr();
thread.state = FetchRunning;
thread.wakeupGuard = true;
DPRINTF(Fetch, "[tid:%d]: Changing stream wakeup %s\n",
tid, thread_ctx->pcState());
DPRINTF(Fetch, "[tid:%d]: Changing stream wakeup %s\n", tid, *thread.pc);
cpu.wakeupOnEvent(Pipeline::Fetch1StageId);
}

View File

@@ -243,52 +243,43 @@ class Fetch1 : public Named
struct Fetch1ThreadInfo
{
/** Consturctor to initialize all fields. */
Fetch1ThreadInfo() :
state(FetchWaitingForPC),
pc(TheISA::PCState(0)),
fetchAddr(0),
streamSeqNum(InstId::firstStreamSeqNum),
predictionSeqNum(InstId::firstPredictionSeqNum),
blocked(false),
wakeupGuard(false)
{ }
// All fields have default initializers.
Fetch1ThreadInfo() {}
Fetch1ThreadInfo(const Fetch1ThreadInfo& other) :
state(other.state),
pc(other.pc),
pc(other.pc->clone()),
streamSeqNum(other.streamSeqNum),
predictionSeqNum(other.predictionSeqNum),
blocked(other.blocked)
{ }
FetchState state;
FetchState state = FetchWaitingForPC;
/** Fetch PC value. This is updated by branches from Execute, branch
* prediction targets from Fetch2. This is only valid immediately
* following a redirect from one of those two sources. */
TheISA::PCState pc;
std::unique_ptr<PCStateBase> pc;
/** The address we're currently fetching lines from. */
Addr fetchAddr;
Addr fetchAddr = 0;
/** Stream sequence number. This changes on request from Execute and is
* used to tag instructions by the fetch stream to which they belong.
* Execute originates new prediction sequence numbers. */
InstSeqNum streamSeqNum;
InstSeqNum streamSeqNum = InstId::firstStreamSeqNum;
/** Prediction sequence number. This changes when requests from Execute
* or Fetch2 ask for a change of fetch address and is used to tag lines
* by the prediction to which they belong. Fetch2 originates
* prediction sequence numbers. */
InstSeqNum predictionSeqNum;
InstSeqNum predictionSeqNum = InstId::firstPredictionSeqNum;
/** Blocked indication for report */
bool blocked;
bool blocked = false;
/** Signal to guard against sleeping first cycle of wakeup */
bool wakeupGuard;
bool wakeupGuard = false;
};
std::vector<Fetch1ThreadInfo> fetchInfo;

View File

@@ -156,7 +156,7 @@ Fetch2::updateBranchPrediction(const BranchData &branch)
/* Unpredicted branch or barrier */
DPRINTF(Branch, "Unpredicted branch seen inst: %s\n", *inst);
branchPredictor.squash(inst->id.fetchSeqNum,
branch.target, true, inst->id.threadId);
branch.target->as<TheISA::PCState>(), true, inst->id.threadId);
// Update after squashing to accomodate O3CPU
// using the branch prediction code.
branchPredictor.update(inst->id.fetchSeqNum,
@@ -172,7 +172,8 @@ Fetch2::updateBranchPrediction(const BranchData &branch)
/* Predicted taken, not taken */
DPRINTF(Branch, "Branch mis-predicted inst: %s\n", *inst);
branchPredictor.squash(inst->id.fetchSeqNum,
branch.target /* Not used */, false, inst->id.threadId);
branch.target->as<TheISA::PCState>() /* Not used */,
false, inst->id.threadId);
// Update after squashing to accomodate O3CPU
// using the branch prediction code.
branchPredictor.update(inst->id.fetchSeqNum,
@@ -181,9 +182,9 @@ Fetch2::updateBranchPrediction(const BranchData &branch)
case BranchData::BadlyPredictedBranchTarget:
/* Predicted taken, was taken but to a different target */
DPRINTF(Branch, "Branch mis-predicted target inst: %s target: %s\n",
*inst, branch.target);
*inst, *branch.target);
branchPredictor.squash(inst->id.fetchSeqNum,
branch.target, true, inst->id.threadId);
branch.target->as<TheISA::PCState>(), true, inst->id.threadId);
break;
}
}
@@ -224,7 +225,7 @@ Fetch2::predictBranch(MinorDynInstPtr inst, BranchData &branch)
BranchData new_branch = BranchData(BranchData::BranchPrediction,
inst->id.threadId,
inst->id.streamSeqNum, thread.predictionSeqNum + 1,
inst->predictedTarget->as<TheISA::PCState>(), inst);
*inst->predictedTarget, inst);
/* Mark with a new prediction number by the stream number of the
* instruction causing the prediction */
@@ -331,13 +332,13 @@ Fetch2::evaluate()
/* Set the inputIndex to be the MachInst-aligned offset
* from lineBaseAddr of the new PC value */
fetch_info.inputIndex =
(line_in->pc.instAddr() & decoder->pcMask()) -
(line_in->pc->instAddr() & decoder->pcMask()) -
line_in->lineBaseAddr;
DPRINTF(Fetch, "Setting new PC value: %s inputIndex: 0x%x"
" lineBaseAddr: 0x%x lineWidth: 0x%x\n",
line_in->pc, fetch_info.inputIndex, line_in->lineBaseAddr,
*line_in->pc, fetch_info.inputIndex, line_in->lineBaseAddr,
line_in->lineWidth);
fetch_info.pc = line_in->pc;
set(fetch_info.pc, line_in->pc);
fetch_info.havePC = true;
decoder->reset();
}
@@ -383,7 +384,7 @@ Fetch2::evaluate()
decoder->moreBytesSize());
if (!decoder->instReady()) {
decoder->moreBytes(fetch_info.pc,
decoder->moreBytes(fetch_info.pc->as<TheISA::PCState>(),
line_in->lineBaseAddr + fetch_info.inputIndex);
DPRINTF(Fetch, "Offering MachInst to decoder addr: 0x%x\n",
line_in->lineBaseAddr + fetch_info.inputIndex);
@@ -397,7 +398,7 @@ Fetch2::evaluate()
* Remember not to assign it until *after* calling
* decode */
StaticInstPtr decoded_inst =
decoder->decode(fetch_info.pc);
decoder->decode(fetch_info.pc->as<TheISA::PCState>());
/* Make a new instruction and pick up the line, stream,
* prediction, thread ids from the incoming line */
@@ -432,7 +433,7 @@ Fetch2::evaluate()
" pc: %s inst: %s\n",
line_in->id,
line_in->lineWidth, output_index, fetch_info.inputIndex,
fetch_info.pc, *dyn_inst);
*fetch_info.pc, *dyn_inst);
/*
* In SE mode, it's possible to branch to a microop when
@@ -448,10 +449,10 @@ Fetch2::evaluate()
* may be pointing to a microop other than 0. Once
* advanced, however, the microop number *must* be 0
*/
fetch_info.pc.uReset();
fetch_info.pc->as<TheISA::PCState>().uReset();
/* Advance PC for the next instruction */
decoded_inst->advancePC(fetch_info.pc);
decoded_inst->advancePC(*fetch_info.pc);
/* Predict any branches and issue a branch if
* necessary */
@@ -467,7 +468,7 @@ Fetch2::evaluate()
DPRINTF(Fetch, "Updated inputIndex value PC: %s"
" inputIndex: 0x%x lineBaseAddr: 0x%x lineWidth: 0x%x\n",
line_in->pc, fetch_info.inputIndex, line_in->lineBaseAddr,
*line_in->pc, fetch_info.inputIndex, line_in->lineBaseAddr,
line_in->lineWidth);
}
}

View File

@@ -104,32 +104,22 @@ class Fetch2 : public Named
struct Fetch2ThreadInfo
{
/** Default constructor */
Fetch2ThreadInfo() :
inputIndex(0),
pc(TheISA::PCState(0)),
havePC(false),
lastStreamSeqNum(InstId::firstStreamSeqNum),
fetchSeqNum(InstId::firstFetchSeqNum),
expectedStreamSeqNum(InstId::firstStreamSeqNum),
predictionSeqNum(InstId::firstPredictionSeqNum),
blocked(false)
{ }
Fetch2ThreadInfo() {}
Fetch2ThreadInfo(const Fetch2ThreadInfo& other) :
inputIndex(other.inputIndex),
pc(other.pc),
havePC(other.havePC),
lastStreamSeqNum(other.lastStreamSeqNum),
expectedStreamSeqNum(other.expectedStreamSeqNum),
predictionSeqNum(other.predictionSeqNum),
blocked(other.blocked)
{ }
{
set(pc, other.pc);
}
/** Index into an incompletely processed input line that instructions
* are to be extracted from */
unsigned int inputIndex;
unsigned int inputIndex = 0;
/** Remembered program counter value. Between contiguous lines, this
@@ -138,34 +128,34 @@ class Fetch2 : public Named
* havePC is needed to accomodate instructions which span across
* lines meaning that Fetch2 and the decoder need to remember a PC
* value and a partially-offered instruction from the previous line */
TheISA::PCState pc;
std::unique_ptr<PCStateBase> pc;
/** PC is currently valid. Initially false, gets set to true when a
* change-of-stream line is received and false again when lines are
* discarded for any reason */
bool havePC;
bool havePC = false;
/** Stream sequence number of the last seen line used to identify
* changes of instruction stream */
InstSeqNum lastStreamSeqNum;
InstSeqNum lastStreamSeqNum = InstId::firstStreamSeqNum;
/** Fetch2 is the source of fetch sequence numbers. These represent the
* sequence that instructions were extracted from fetched lines. */
InstSeqNum fetchSeqNum;
InstSeqNum fetchSeqNum = InstId::firstFetchSeqNum;
/** Stream sequence number remembered from last time the
* predictionSeqNum changed. Lines should only be discarded when their
* predictionSeqNums disagree with Fetch2::predictionSeqNum *and* they
* are from the same stream that bore that prediction number */
InstSeqNum expectedStreamSeqNum;
InstSeqNum expectedStreamSeqNum = InstId::firstStreamSeqNum;
/** Fetch2 is the source of prediction sequence numbers. These
* represent predicted changes of control flow sources from branch
* prediction in Fetch2. */
InstSeqNum predictionSeqNum;
InstSeqNum predictionSeqNum = InstId::firstPredictionSeqNum;
/** Blocked indication for report */
bool blocked;
bool blocked = false;
};
std::vector<Fetch2ThreadInfo> fetchInfo;

View File

@@ -145,7 +145,7 @@ BranchData::reportData(std::ostream &os) const
} else {
os << reason
<< ';' << newStreamSeqNum << '.' << newPredictionSeqNum
<< ";0x" << std::hex << target.instAddr() << std::dec
<< ";0x" << std::hex << target->instAddr() << std::dec
<< ';';
inst->reportData(os);
}
@@ -155,7 +155,7 @@ std::ostream &
operator <<(std::ostream &os, const BranchData &branch)
{
os << branch.reason << " target: 0x"
<< std::hex << branch.target.instAddr() << std::dec
<< std::hex << branch.target->instAddr() << std::dec
<< ' ' << *branch.inst
<< ' ' << branch.newStreamSeqNum << "(stream)."
<< branch.newPredictionSeqNum << "(pred)";

View File

@@ -110,42 +110,51 @@ class BranchData /* : public ReportIF, public BubbleIF */
public:
/** Explanation for this branch */
Reason reason;
Reason reason = NoBranch;
/** ThreadID associated with branch */
ThreadID threadId;
ThreadID threadId = InvalidThreadID;
/** Sequence number of new stream/prediction to be adopted */
InstSeqNum newStreamSeqNum;
InstSeqNum newPredictionSeqNum;
InstSeqNum newStreamSeqNum = 0;
InstSeqNum newPredictionSeqNum = 0;
/** Starting PC of that stream */
TheISA::PCState target;
std::unique_ptr<PCStateBase> target;
/** Instruction which caused this branch */
MinorDynInstPtr inst;
MinorDynInstPtr inst = MinorDynInst::bubble();
public:
BranchData() :
reason(NoBranch), threadId(InvalidThreadID), newStreamSeqNum(0),
newPredictionSeqNum(0), target(TheISA::PCState(0)),
inst(MinorDynInst::bubble())
{ }
BranchData() {}
BranchData(
Reason reason_,
ThreadID thread_id,
InstSeqNum new_stream_seq_num,
InstSeqNum new_prediction_seq_num,
TheISA::PCState target,
MinorDynInstPtr inst_) :
reason(reason_),
threadId(thread_id),
BranchData(Reason reason_, ThreadID thread_id,
InstSeqNum new_stream_seq_num, InstSeqNum new_prediction_seq_num,
const PCStateBase &target, MinorDynInstPtr inst_) :
reason(reason_), threadId(thread_id),
newStreamSeqNum(new_stream_seq_num),
newPredictionSeqNum(new_prediction_seq_num),
target(target),
inst(inst_)
{ }
target(target.clone()), inst(inst_)
{}
BranchData(const BranchData &other) :
reason(other.reason), threadId(other.threadId),
newStreamSeqNum(other.newStreamSeqNum),
newPredictionSeqNum(other.newPredictionSeqNum),
target(other.target->clone()),
inst(other.inst)
{}
BranchData &
operator=(const BranchData &other)
{
reason = other.reason;
threadId = other.threadId;
newStreamSeqNum = other.newStreamSeqNum;
newPredictionSeqNum = other.newPredictionSeqNum;
set(target, other.target);
inst = other.inst;
return *this;
}
/** BubbleIF interface */
static BranchData bubble() { return BranchData(); }
@@ -176,48 +185,60 @@ class ForwardLineData /* : public ReportIF, public BubbleIF */
{
private:
/** This line is a bubble. No other data member is required to be valid
* if this is true */
bool bubbleFlag;
* if this is true
* Make lines bubbles by default */
bool bubbleFlag = true;
public:
/** First byte address in the line. This is allowed to be
* <= pc.instAddr() */
Addr lineBaseAddr;
Addr lineBaseAddr = 0;
/** PC of the first inst within this sequence */
TheISA::PCState pc;
std::unique_ptr<PCStateBase> pc;
/** Address of this line of data */
Addr fetchAddr;
/** Explicit line width, don't rely on data.size */
unsigned int lineWidth;
unsigned int lineWidth = 0;
public:
/** This line has a fault. The bubble flag will be false and seqNums
* will be valid but no data will */
Fault fault;
Fault fault = NoFault;
/** Thread, stream, prediction ... id of this line */
InstId id;
/** Line data. line[0] is the byte at address pc.instAddr(). Data is
* only valid upto lineWidth - 1. */
uint8_t *line;
uint8_t *line = nullptr;
/** Packet from which the line is taken */
Packet *packet;
Packet *packet = nullptr;
public:
ForwardLineData() :
bubbleFlag(true),
lineBaseAddr(0),
lineWidth(0),
fault(NoFault),
line(NULL),
packet(NULL)
ForwardLineData() {}
ForwardLineData(const ForwardLineData &other) :
bubbleFlag(other.bubbleFlag), lineBaseAddr(other.lineBaseAddr),
pc(other.pc->clone()), fetchAddr(other.fetchAddr),
lineWidth(other.lineWidth), fault(other.fault), id(other.id),
line(other.line), packet(other.packet)
{}
ForwardLineData &
operator=(const ForwardLineData &other)
{
/* Make lines bubbles by default */
bubbleFlag = other.bubbleFlag;
lineBaseAddr = other.lineBaseAddr;
set(pc, other.pc);
fetchAddr = other.fetchAddr;
lineWidth = other.lineWidth;
fault = other.fault;
id = other.id;
line = other.line;
packet = other.packet;
return *this;
}
~ForwardLineData() { line = NULL; }