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>
diff --git a/src/cpu/minor/decode.cc b/src/cpu/minor/decode.cc
index e82811f..5adf2ca 100644
--- a/src/cpu/minor/decode.cc
+++ b/src/cpu/minor/decode.cc
@@ -184,7 +184,7 @@
* 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 @@
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()) {
diff --git a/src/cpu/minor/decode.hh b/src/cpu/minor/decode.hh
index 8e20e8b..6e9cb62 100644
--- a/src/cpu/minor/decode.hh
+++ b/src/cpu/minor/decode.hh
@@ -94,40 +94,35 @@
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;
diff --git a/src/cpu/minor/fetch1.cc b/src/cpu/minor/fetch1.cc
index 193ebaa..72e9957 100644
--- a/src/cpu/minor/fetch1.cc
+++ b/src/cpu/minor/fetch1.cc
@@ -83,6 +83,9 @@
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 @@
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 @@
/* 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 @@
{
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);
}
diff --git a/src/cpu/minor/fetch1.hh b/src/cpu/minor/fetch1.hh
index 434fbba..bd8ad7d 100644
--- a/src/cpu/minor/fetch1.hh
+++ b/src/cpu/minor/fetch1.hh
@@ -243,52 +243,43 @@
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;
diff --git a/src/cpu/minor/fetch2.cc b/src/cpu/minor/fetch2.cc
index 3988132..3c9659c 100644
--- a/src/cpu/minor/fetch2.cc
+++ b/src/cpu/minor/fetch2.cc
@@ -156,7 +156,7 @@
/* 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 @@
/* 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 @@
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 @@
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 @@
/* 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 @@
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 @@
* 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 @@
" 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 @@
* 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 @@
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);
}
}
diff --git a/src/cpu/minor/fetch2.hh b/src/cpu/minor/fetch2.hh
index 41a7a7f..2eb8a77 100644
--- a/src/cpu/minor/fetch2.hh
+++ b/src/cpu/minor/fetch2.hh
@@ -104,32 +104,22 @@
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 @@
* 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;
diff --git a/src/cpu/minor/pipe_data.cc b/src/cpu/minor/pipe_data.cc
index 5a3ec8c..d7f113c 100644
--- a/src/cpu/minor/pipe_data.cc
+++ b/src/cpu/minor/pipe_data.cc
@@ -145,7 +145,7 @@
} 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 @@
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)";
diff --git a/src/cpu/minor/pipe_data.hh b/src/cpu/minor/pipe_data.hh
index e9bad03..b85f9be 100644
--- a/src/cpu/minor/pipe_data.hh
+++ b/src/cpu/minor/pipe_data.hh
@@ -110,42 +110,51 @@
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 @@
{
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; }