cpu-minor: Disentangle the PC and fetch address.

The minor CPU was using a PCState object both to track redirects when
taking a branch, etc, and to track where to fetch a line of memory from.
It would need to create a new PCState object, or at least update the
existing one, whenever it needed to advance to the next line.

This is problematic since it means the minor CPU needs to know how to
create or set a PCState object, and since it by necessity only
understands the most basic aspect of a PCState, what the address is, it
can only set that, with all the other potential attributes staying at
their old values or getting set to some default.

Instead, this change separates the two. There is now a PC which is used
for redirects which the later stages will only pick up if there is a
change in "sequence", the same behavior as before. This PC will only
ever be set when changing sequence, and will otherwise not be
meaningful/useful.

There is also now a separate fetch address which is what the fetch stage
uses to get new lines. This was all the PC value that was artificially
updated was used for anyway.

Change-Id: Ia64bbe21e980566ae77786999689c9c8a94e9378
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52048
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/fetch1.cc b/src/cpu/minor/fetch1.cc
index 198ed52..193ebaa 100644
--- a/src/cpu/minor/fetch1.cc
+++ b/src/cpu/minor/fetch1.cc
@@ -157,7 +157,7 @@
     /* If line_offset != 0, a request is pushed for the remainder of the
      * line. */
     /* Use a lower, sizeof(MachInst) aligned address for the fetch */
-    Addr aligned_pc = thread.pc.instAddr() & ~((Addr) lineSnap - 1);
+    Addr aligned_pc = thread.fetchAddr & ~((Addr) lineSnap - 1);
     unsigned int line_offset = aligned_pc % lineSnap;
     unsigned int request_size = maxLineWidth - line_offset;
 
@@ -166,17 +166,18 @@
         thread.streamSeqNum, thread.predictionSeqNum,
         lineSeqNum);
 
-    FetchRequestPtr request = new FetchRequest(*this, request_id, thread.pc);
+    FetchRequestPtr request = new FetchRequest(*this, request_id,
+            thread.fetchAddr);
 
     DPRINTF(Fetch, "Inserting fetch into the fetch queue "
         "%s addr: 0x%x pc: %s line_offset: %d request_size: %d\n",
-        request_id, aligned_pc, thread.pc, line_offset, request_size);
+        request_id, aligned_pc, thread.fetchAddr, line_offset, request_size);
 
     request->request->setContext(cpu.threads[tid]->getTC()->contextId());
     request->request->setVirt(
         aligned_pc, request_size, Request::INST_FETCH, cpu.instRequestorId(),
         /* I've no idea why we need the PC, but give it */
-        thread.pc.instAddr());
+        thread.fetchAddr);
 
     DPRINTF(Fetch, "Submitting ITLB request\n");
     numFetchesInITLB++;
@@ -200,7 +201,7 @@
     /* Step the PC for the next line onto the line aligned next address.
      * Note that as instructions can span lines, this PC is only a
      * reliable 'new' PC if the next line has a new stream sequence number. */
-    thread.pc.set(aligned_pc + request_size);
+    thread.fetchAddr = aligned_pc + request_size;
 }
 
 std::ostream &
@@ -511,6 +512,7 @@
         break;
     }
     thread.pc = branch.target;
+    thread.fetchAddr = thread.pc.instAddr();
 }
 
 void
@@ -543,8 +545,10 @@
     line.setFault(response->fault);
     /* Make sequence numbers valid in return */
     line.id = response->id;
-    /* Set PC to virtual address */
-    line.pc = response->pc;
+    /* Set the PC in case there was a sequence change */
+    line.pc = thread.pc;
+    /* Set fetch address to virtual address */
+    line.fetchAddr = response->pc;
     /* Set the lineBase, which is a sizeof(MachInst) aligned address <=
      *  pc.instAddr() */
     line.lineBaseAddr = response->request->getVaddr();
@@ -712,6 +716,7 @@
     ThreadContext *thread_ctx = cpu.getContext(tid);
     Fetch1ThreadInfo &thread = fetchInfo[tid];
     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",
diff --git a/src/cpu/minor/fetch1.hh b/src/cpu/minor/fetch1.hh
index dcdf35e..434fbba 100644
--- a/src/cpu/minor/fetch1.hh
+++ b/src/cpu/minor/fetch1.hh
@@ -139,7 +139,7 @@
         RequestPtr request;
 
         /** PC to fixup with line address */
-        TheISA::PCState pc;
+        Addr pc;
 
         /** Fill in a fault if one happens during fetch, check this by
          *  picking apart the response packet */
@@ -173,7 +173,7 @@
                     ThreadContext *tc, BaseMMU::Mode mode);
 
       public:
-        FetchRequest(Fetch1 &fetch_, InstId id_, TheISA::PCState pc_) :
+        FetchRequest(Fetch1 &fetch_, InstId id_, Addr pc_) :
             SenderState(),
             fetch(fetch_),
             state(NotIssued),
@@ -248,6 +248,7 @@
         Fetch1ThreadInfo() :
             state(FetchWaitingForPC),
             pc(TheISA::PCState(0)),
+            fetchAddr(0),
             streamSeqNum(InstId::firstStreamSeqNum),
             predictionSeqNum(InstId::firstPredictionSeqNum),
             blocked(false),
@@ -265,10 +266,13 @@
         FetchState state;
 
         /** Fetch PC value. This is updated by branches from Execute, branch
-         *  prediction targets from Fetch2 and by incrementing it as we fetch
-         *  lines subsequent to those two sources. */
+         *  prediction targets from Fetch2. This is only valid immediately
+         *  following a redirect from one of those two sources. */
         TheISA::PCState pc;
 
+        /** The address we're currently fetching lines from. */
+        Addr fetchAddr;
+
         /** 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. */
diff --git a/src/cpu/minor/pipe_data.hh b/src/cpu/minor/pipe_data.hh
index f16af27..e9bad03 100644
--- a/src/cpu/minor/pipe_data.hh
+++ b/src/cpu/minor/pipe_data.hh
@@ -184,9 +184,12 @@
      *  <= pc.instAddr() */
     Addr lineBaseAddr;
 
-    /** PC of the first requested inst within this line */
+    /** PC of the first inst within this sequence */
     TheISA::PCState pc;
 
+    /** Address of this line of data */
+    Addr fetchAddr;
+
     /** Explicit line width, don't rely on data.size */
     unsigned int lineWidth;