cpu: Move the instruction port into o3's fetch stage.

That's where it's used, and that avoids having to pass it around using
the top level getInstPort accessor.

Change-Id: I489a3f3239b3116292f3dcd78a3945fb468c6311
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20239
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Gabe Black <gabeblack@google.com>
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc
index c9e01a5..1353c1e 100644
--- a/src/cpu/o3/cpu.cc
+++ b/src/cpu/o3/cpu.cc
@@ -90,26 +90,6 @@
     BaseCPU::regStats();
 }
 
-template<class Impl>
-bool
-FullO3CPU<Impl>::IcachePort::recvTimingResp(PacketPtr pkt)
-{
-    DPRINTF(O3CPU, "Fetch unit received timing\n");
-    // We shouldn't ever get a cacheable block in Modified state
-    assert(pkt->req->isUncacheable() ||
-           !(pkt->cacheResponding() && !pkt->hasSharers()));
-    fetch->processCacheCompletion(pkt);
-
-    return true;
-}
-
-template<class Impl>
-void
-FullO3CPU<Impl>::IcachePort::recvReqRetry()
-{
-    fetch->recvReqRetry();
-}
-
 template <class Impl>
 FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
     : BaseO3CPU(params),
@@ -148,8 +128,6 @@
 
       isa(numThreads, NULL),
 
-      icachePort(&fetch, this),
-
       timeBuffer(params->backComSize, params->forwardComSize),
       fetchQueue(params->backComSize, params->forwardComSize),
       decodeQueue(params->backComSize, params->forwardComSize),
@@ -172,7 +150,7 @@
     if (params->checker) {
         BaseCPU *temp_checker = params->checker;
         checker = dynamic_cast<Checker<Impl> *>(temp_checker);
-        checker->setIcachePort(&icachePort);
+        checker->setIcachePort(&this->fetch.getInstPort());
         checker->setSystem(params->system);
     } else {
         checker = NULL;
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 778c55b..58a2218 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -133,31 +133,6 @@
 
   private:
 
-    /**
-     * IcachePort class for instruction fetch.
-     */
-    class IcachePort : public MasterPort
-    {
-      protected:
-        /** Pointer to fetch. */
-        DefaultFetch<Impl> *fetch;
-
-      public:
-        /** Default constructor. */
-        IcachePort(DefaultFetch<Impl> *_fetch, FullO3CPU<Impl>* _cpu)
-            : MasterPort(_cpu->name() + ".icache_port", _cpu), fetch(_fetch)
-        { }
-
-      protected:
-
-        /** Timing version of receive.  Handles setting fetch to the
-         * proper status to start fetching. */
-        virtual bool recvTimingResp(PacketPtr pkt);
-
-        /** Handles doing a retry of a failed fetch. */
-        virtual void recvReqRetry();
-    };
-
     /** The tick event used for scheduling CPU ticks. */
     EventFunctionWrapper tickEvent;
 
@@ -629,9 +604,6 @@
 
     std::vector<TheISA::ISA *> isa;
 
-    /** Instruction port. Note that it has to appear after the fetch stage. */
-    IcachePort icachePort;
-
   public:
     /** Enum to give each stage a specific index, so when calling
      *  activateStage() or deactivateStage(), they can specify which stage
@@ -763,7 +735,11 @@
     }
 
     /** Used by the fetch unit to get a hold of the instruction port. */
-    MasterPort &getInstPort() override { return icachePort; }
+    MasterPort &
+    getInstPort() override
+    {
+        return this->fetch.getInstPort();
+    }
 
     /** Get the dcache port (used to find block size for translations). */
     MasterPort &
diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh
index 3cf0773..b8766ad 100644
--- a/src/cpu/o3/fetch.hh
+++ b/src/cpu/o3/fetch.hh
@@ -59,6 +59,8 @@
 #include "sim/probe/probe.hh"
 
 struct DerivO3CPUParams;
+template <class Impl>
+class FullO3CPU;
 
 /**
  * DefaultFetch class handles both single threaded and SMT fetch. Its
@@ -85,6 +87,31 @@
     /** Typedefs from ISA. */
     typedef TheISA::MachInst MachInst;
 
+    /**
+     * IcachePort class for instruction fetch.
+     */
+    class IcachePort : public MasterPort
+    {
+      protected:
+        /** Pointer to fetch. */
+        DefaultFetch<Impl> *fetch;
+
+      public:
+        /** Default constructor. */
+        IcachePort(DefaultFetch<Impl> *_fetch, FullO3CPU<Impl>* _cpu)
+            : MasterPort(_cpu->name() + ".icache_port", _cpu), fetch(_fetch)
+        { }
+
+      protected:
+
+        /** Timing version of receive.  Handles setting fetch to the
+         * proper status to start fetching. */
+        virtual bool recvTimingResp(PacketPtr pkt);
+
+        /** Handles doing a retry of a failed fetch. */
+        virtual void recvReqRetry();
+    };
+
     class FetchTranslation : public BaseTLB::Translation
     {
       protected:
@@ -353,6 +380,8 @@
     /** The decoder. */
     TheISA::Decoder *decoder[Impl::MaxThreads];
 
+    MasterPort &getInstPort() { return icachePort; }
+
   private:
     DynInstPtr buildInst(ThreadID tid, StaticInstPtr staticInst,
                          StaticInstPtr curMacroop, TheISA::PCState thisPC,
@@ -511,6 +540,9 @@
      */
     bool interruptPending;
 
+    /** Instruction port. Note that it has to appear after the fetch stage. */
+    IcachePort icachePort;
+
     /** Set to true if a pipelined I-cache request should be issued. */
     bool issuePipelinedIfetch[Impl::MaxThreads];
 
diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh
index f0a97e4..60542b8 100644
--- a/src/cpu/o3/fetch_impl.hh
+++ b/src/cpu/o3/fetch_impl.hh
@@ -60,11 +60,13 @@
 #include "config/the_isa.hh"
 #include "cpu/base.hh"
 //#include "cpu/checker/cpu.hh"
+#include "cpu/o3/cpu.hh"
 #include "cpu/o3/fetch.hh"
 #include "cpu/exetrace.hh"
 #include "debug/Activity.hh"
 #include "debug/Drain.hh"
 #include "debug/Fetch.hh"
+#include "debug/O3CPU.hh"
 #include "debug/O3PipeView.hh"
 #include "mem/packet.hh"
 #include "params/DerivO3CPU.hh"
@@ -96,6 +98,7 @@
       fetchQueueSize(params->fetchQueueSize),
       numThreads(params->numThreads),
       numFetchingThreads(params->smtNumFetchingThreads),
+      icachePort(this, _cpu),
       finishTranslationEvent(this)
 {
     if (numThreads > Impl::MaxThreads)
@@ -692,7 +695,7 @@
         fetchedCacheLines++;
 
         // Access the cache.
-        if (!cpu->getInstPort().sendTimingReq(data_pkt)) {
+        if (!icachePort.sendTimingReq(data_pkt)) {
             assert(retryPkt == NULL);
             assert(retryTid == InvalidThreadID);
             DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
@@ -1422,7 +1425,7 @@
         assert(retryTid != InvalidThreadID);
         assert(fetchStatus[retryTid] == IcacheWaitRetry);
 
-        if (cpu->getInstPort().sendTimingReq(retryPkt)) {
+        if (icachePort.sendTimingReq(retryPkt)) {
             fetchStatus[retryTid] = IcacheWaitResponse;
             // Notify Fetch Request probe when a retryPkt is successfully sent.
             // Note that notify must be called before retryPkt is set to NULL.
@@ -1670,4 +1673,24 @@
     }
 }
 
+template<class Impl>
+bool
+DefaultFetch<Impl>::IcachePort::recvTimingResp(PacketPtr pkt)
+{
+    DPRINTF(O3CPU, "Fetch unit received timing\n");
+    // We shouldn't ever get a cacheable block in Modified state
+    assert(pkt->req->isUncacheable() ||
+           !(pkt->cacheResponding() && !pkt->hasSharers()));
+    fetch->processCacheCompletion(pkt);
+
+    return true;
+}
+
+template<class Impl>
+void
+DefaultFetch<Impl>::IcachePort::recvReqRetry()
+{
+    fetch->recvReqRetry();
+}
+
 #endif//__CPU_O3_FETCH_IMPL_HH__