cpu: Refactor memory system checks
authorAndreas Sandberg <Andreas.Sandberg@ARM.com>
Fri, 15 Feb 2013 22:40:08 +0000 (17:40 -0500)
committerAndreas Sandberg <Andreas.Sandberg@ARM.com>
Fri, 15 Feb 2013 22:40:08 +0000 (17:40 -0500)
CPUs need to test that the memory system is in the right mode in two
places, when the CPU is initialized (unless it's switched out) and on
a drainResume(). This led to some code duplication in the CPU
models. This changeset introduces the verifyMemoryMode() method which
is called by BaseCPU::init() if the CPU isn't switched out. The
individual CPU models are responsible for calling this method when
resuming from a drain as this code is CPU model specific.

src/cpu/base.cc
src/cpu/base.hh
src/cpu/inorder/cpu.cc
src/cpu/inorder/cpu.hh
src/cpu/o3/cpu.cc
src/cpu/o3/cpu.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/timing.cc
src/cpu/simple/timing.hh

index 3e7a6d4b66469fb23b25bea812b0c79e7b9b5e26..36caea79aa163b30e31d24b373f0e1255d50f5a1 100644 (file)
@@ -254,8 +254,11 @@ BaseCPU::~BaseCPU()
 void
 BaseCPU::init()
 {
-    if (!params()->switched_out)
+    if (!params()->switched_out) {
         registerThreadContexts();
+
+        verifyMemoryMode();
+    }
 }
 
 void
index 34b23cea07a7ed8eaa6ff7305ba842f8399fdd61..073050816b39e3e5af8976420a16f568328dc474 100644 (file)
@@ -341,6 +341,17 @@ class BaseCPU : public MemObject
      */
     bool switchedOut() const { return _switchedOut; }
 
+    /**
+     * Verify that the system is in a memory mode supported by the
+     * CPU.
+     *
+     * Implementations are expected to query the system for the
+     * current memory mode and ensure that it is what the CPU model
+     * expects. If the check fails, the implementation should
+     * terminate the simulation using fatal().
+     */
+    virtual void verifyMemoryMode() const { };
+
     /**
      *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
      * This is a constant for the duration of the simulation.
index 87272da7f5e5a718975a6991e0bb45b80dc13a13..5490cb3f283e60e6effb2e56dce7e3d77e616887 100644 (file)
@@ -786,12 +786,6 @@ InOrderCPU::init()
 {
     BaseCPU::init();
 
-    if (!params()->switched_out &&
-        system->getMemoryMode() != Enums::timing) {
-        fatal("The in-order CPU requires the memory system to be in "
-              "'timing' mode.\n");
-    }
-
     for (ThreadID tid = 0; tid < numThreads; ++tid) {
         // Set noSquashFromTC so that the CPU doesn't squash when initially
         // setting up registers.
@@ -815,6 +809,15 @@ InOrderCPU::init()
     resPool->init();
 }
 
+void
+InOrderCPU::verifyMemoryMode() const
+{
+    if (system->getMemoryMode() != Enums::timing) {
+        fatal("The in-order CPU requires the memory system to be in "
+              "'timing' mode.\n");
+    }
+}
+
 Fault
 InOrderCPU::hwrei(ThreadID tid)
 {
index 1037ea2e654a87664914475354676c7ec48fd8a1..7ca4355de9e56291e88e0aad65369725785aaffb 100644 (file)
@@ -109,6 +109,8 @@ class InOrderCPU : public BaseCPU
     /* Destructor */
     ~InOrderCPU();
     
+    void verifyMemoryMode() const;
+
     /** Return a reference to the data port. */
     virtual CpuPort &getDataPort() { return dataPort; }
 
index 393b9a189d1245654ff6caadde652b6922fa0480..53250d49575f7437ac416b5406a090196bd09429 100644 (file)
@@ -646,12 +646,6 @@ FullO3CPU<Impl>::init()
 {
     BaseCPU::init();
 
-    if (!params()->switched_out &&
-        system->getMemoryMode() != Enums::timing) {
-        fatal("The O3 CPU requires the memory system to be in "
-              "'timing' mode.\n");
-    }
-
     for (ThreadID tid = 0; tid < numThreads; ++tid) {
         // Set noSquashFromTC so that the CPU doesn't squash when initially
         // setting up registers.
@@ -1262,11 +1256,7 @@ FullO3CPU<Impl>::drainResume()
         return;
 
     DPRINTF(Drain, "Resuming...\n");
-
-    if (system->getMemoryMode() != Enums::timing) {
-        fatal("The O3 CPU requires the memory system to be in "
-              "'timing' mode.\n");
-    }
+    verifyMemoryMode();
 
     fetch.drainResume();
     commit.drainResume();
@@ -1322,6 +1312,16 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
     _status = Idle;
 }
 
+template <class Impl>
+void
+FullO3CPU<Impl>::verifyMemoryMode() const
+{
+    if (system->getMemoryMode() != Enums::timing) {
+        fatal("The O3 CPU requires the memory system to be in "
+              "'timing' mode.\n");
+    }
+}
+
 template <class Impl>
 TheISA::MiscReg
 FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, ThreadID tid)
index 5dd0e222d1b1de190929614806764ab8ca689999..719d38ef03eb20537f3bebc1986cd92ed837c7df 100644 (file)
@@ -479,6 +479,8 @@ class FullO3CPU : public BaseO3CPU
     /** Takes over from another CPU. */
     virtual void takeOverFrom(BaseCPU *oldCPU);
 
+    void verifyMemoryMode() const;
+
     /** Get the current instruction sequence number, and increment it. */
     InstSeqNum getAndIncrementInstSeq()
     { return globalSeqNum++; }
index 7255469a0479efc1170699717a5395ae8aab89a8..7a07789618fc5bfb52ea6b9e0b6f019ffc6cfa88 100644 (file)
@@ -84,12 +84,6 @@ AtomicSimpleCPU::init()
 {
     BaseCPU::init();
 
-    if (!params()->switched_out &&
-        system->getMemoryMode() != Enums::atomic) {
-        fatal("The atomic CPU requires the memory system to be in "
-              "'atomic' mode.\n");
-    }
-
     // Initialise the ThreadContext's memory proxies
     tcBase()->initMemProxies(tcBase());
 
@@ -157,10 +151,7 @@ AtomicSimpleCPU::drainResume()
         return;
 
     DPRINTF(SimpleCPU, "Resume\n");
-    if (system->getMemoryMode() != Enums::atomic) {
-        fatal("The atomic CPU requires the memory system to be in "
-              "'atomic' mode.\n");
-    }
+    verifyMemoryMode();
 
     assert(!threadContexts.empty());
     if (threadContexts.size() > 1)
@@ -218,6 +209,14 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
     data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too
 }
 
+void
+AtomicSimpleCPU::verifyMemoryMode() const
+{
+    if (system->getMemoryMode() != Enums::atomic) {
+        fatal("The atomic CPU requires the memory system to be in "
+              "'atomic' mode.\n");
+    }
+}
 
 void
 AtomicSimpleCPU::activateContext(ThreadID thread_num, Cycles delay)
index 68412510660c6939ff59c883e71f0c1e4f7c08a1..e3eafe8e094c90bbd03ef65b804bc7fc008dd1ee 100644 (file)
@@ -164,6 +164,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     void switchOut();
     void takeOverFrom(BaseCPU *oldCPU);
 
+    void verifyMemoryMode() const;
+
     virtual void activateContext(ThreadID thread_num, Cycles delay);
     virtual void suspendContext(ThreadID thread_num);
 
index f6dc1fbf63889c708a45bd43b3879ae552801fbc..7423d082cc20cd399286ac79cac94647ff2ec018 100644 (file)
@@ -66,12 +66,6 @@ TimingSimpleCPU::init()
 {
     BaseCPU::init();
 
-    if (!params()->switched_out &&
-        system->getMemoryMode() != Enums::timing) {
-        fatal("The timing CPU requires the memory system to be in "
-              "'timing' mode.\n");
-    }
-
     // Initialise the ThreadContext's memory proxies
     tcBase()->initMemProxies(tcBase());
 
@@ -141,10 +135,7 @@ TimingSimpleCPU::drainResume()
         return;
 
     DPRINTF(SimpleCPU, "Resume\n");
-    if (system->getMemoryMode() != Enums::timing) {
-        fatal("The timing CPU requires the memory system to be in "
-              "'timing' mode.\n");
-    }
+    verifyMemoryMode();
 
     assert(!threadContexts.empty());
     if (threadContexts.size() > 1)
@@ -197,6 +188,14 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
     previousCycle = curCycle();
 }
 
+void
+TimingSimpleCPU::verifyMemoryMode() const
+{
+    if (system->getMemoryMode() != Enums::timing) {
+        fatal("The timing CPU requires the memory system to be in "
+              "'timing' mode.\n");
+    }
+}
 
 void
 TimingSimpleCPU::activateContext(ThreadID thread_num, Cycles delay)
index af780265f48d7c7336365fbc9c200cb4b8bfb311..348129150bbf0fd988b9718cb50d0610094df43f 100644 (file)
@@ -261,6 +261,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
     void switchOut();
     void takeOverFrom(BaseCPU *oldCPU);
 
+    void verifyMemoryMode() const;
+
     virtual void activateContext(ThreadID thread_num, Cycles delay);
     virtual void suspendContext(ThreadID thread_num);