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; }