diff --git a/src/cpu/minor/decode.cc b/src/cpu/minor/decode.cc index e82811f1c5..5adf2cacfc 100644 --- a/src/cpu/minor/decode.cc +++ b/src/cpu/minor/decode.cc @@ -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()) { diff --git a/src/cpu/minor/decode.hh b/src/cpu/minor/decode.hh index 8e20e8bec4..6e9cb62fbd 100644 --- a/src/cpu/minor/decode.hh +++ b/src/cpu/minor/decode.hh @@ -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 microopPC; /** Source of execSeqNums to number instructions. */ - InstSeqNum execSeqNum; + InstSeqNum execSeqNum = InstId::firstExecSeqNum; /** Blocked indication for report */ - bool blocked; + bool blocked = false; }; std::vector decodeInfo; diff --git a/src/cpu/minor/fetch1.cc b/src/cpu/minor/fetch1.cc index 193ebaa452..72e9957c62 100644 --- a/src/cpu/minor/fetch1.cc +++ b/src/cpu/minor/fetch1.cc @@ -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); } diff --git a/src/cpu/minor/fetch1.hh b/src/cpu/minor/fetch1.hh index 434fbba905..bd8ad7d224 100644 --- a/src/cpu/minor/fetch1.hh +++ b/src/cpu/minor/fetch1.hh @@ -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 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 fetchInfo; diff --git a/src/cpu/minor/fetch2.cc b/src/cpu/minor/fetch2.cc index 39881322ec..3c9659c6af 100644 --- a/src/cpu/minor/fetch2.cc +++ b/src/cpu/minor/fetch2.cc @@ -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(), 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() /* 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(), 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(), 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(), 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()); /* 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().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); } } diff --git a/src/cpu/minor/fetch2.hh b/src/cpu/minor/fetch2.hh index 41a7a7fde4..2eb8a772f1 100644 --- a/src/cpu/minor/fetch2.hh +++ b/src/cpu/minor/fetch2.hh @@ -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 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 fetchInfo; diff --git a/src/cpu/minor/pipe_data.cc b/src/cpu/minor/pipe_data.cc index 5a3ec8cadb..d7f113cfa3 100644 --- a/src/cpu/minor/pipe_data.cc +++ b/src/cpu/minor/pipe_data.cc @@ -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)"; diff --git a/src/cpu/minor/pipe_data.hh b/src/cpu/minor/pipe_data.hh index e9bad03781..b85f9bef70 100644 --- a/src/cpu/minor/pipe_data.hh +++ b/src/cpu/minor/pipe_data.hh @@ -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 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 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; }