Two fixes:
authorKevin Lim <ktlim@umich.edu>
Fri, 9 Mar 2007 15:06:09 +0000 (10:06 -0500)
committerKevin Lim <ktlim@umich.edu>
Fri, 9 Mar 2007 15:06:09 +0000 (10:06 -0500)
1. Make sure connectMemPorts() only gets called when the CPU's peer gets changed.  This is done by making setPeer() virtual, and overriding it in the CPU's ports.  When it gets called on a CPU's port (dcache specifically), it calls the normal setPeer() function, and also connectMemPorts().
2. Consolidate redundant code that handles switching in a CPU.

src/cpu/base.cc:
    Move common code of switching over peers to base CPU.
src/cpu/base.hh:
    Move common code of switching over peers to BaseCPU.
src/cpu/o3/cpu.cc:
    Add in function that updates thread context's ports.
    Also use updated function to takeOverFrom() in BaseCPU.  This gets rid of some repeated code.
src/cpu/o3/cpu.hh:
    Include function to update thread context's memory ports.
src/cpu/o3/lsq.hh:
    Add function to dcache port that will update the memory ports upon getting a new peer.
    Also include a function that will tell the CPU to update those memory ports.
src/cpu/o3/lsq_impl.hh:
    Add function that will update the memory ports upon getting a new peer.
src/cpu/simple/atomic.cc:
src/cpu/simple/timing.cc:
    Add function that will update thread context's memory ports upon getting a new peer.
    Also use the new BaseCPU's take over from function.
src/cpu/simple/atomic.hh:
    Add in function (and dcache port) that will allow the dcache to update memory ports when it gets assigned a new peer.
src/cpu/simple/timing.hh:
    Add function that will update thread context's memory ports upon getting a new peer.
src/mem/port.hh:
    Make setPeer virtual so that other classes can override it.

--HG--
extra : convert_revision : 2050f1241dd2e83875d281cfc5ad5c6c8705fdaf

src/cpu/base.cc
src/cpu/base.hh
src/cpu/o3/cpu.cc
src/cpu/o3/cpu.hh
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_impl.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/timing.cc
src/cpu/simple/timing.hh
src/mem/port.hh

index 104b3b6bb5baf5c8be3339dcfa6d4067a673d5eb..3e0be6ad82ea871856e2d5fe57d60040eac0e290 100644 (file)
@@ -319,7 +319,7 @@ BaseCPU::switchOut()
 }
 
 void
-BaseCPU::takeOverFrom(BaseCPU *oldCPU)
+BaseCPU::takeOverFrom(BaseCPU *oldCPU, Port *ic, Port *dc)
 {
     assert(threadContexts.size() == oldCPU->threadContexts.size());
 
@@ -352,6 +352,26 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
 //    if (profileEvent)
 //        profileEvent->schedule(curTick);
 #endif
+
+    // Connect new CPU to old CPU's memory only if new CPU isn't
+    // connected to anything.  Also connect old CPU's memory to new
+    // CPU.
+    Port *peer;
+    if (ic->getPeer() == NULL) {
+        peer = oldCPU->getPort("icache_port")->getPeer();
+        ic->setPeer(peer);
+    } else {
+        peer = ic->getPeer();
+    }
+    peer->setPeer(ic);
+
+    if (dc->getPeer() == NULL) {
+        peer = oldCPU->getPort("dcache_port")->getPeer();
+        dc->setPeer(peer);
+    } else {
+        peer = dc->getPeer();
+    }
+    peer->setPeer(dc);
 }
 
 
index d4213887dd50a626987e898a62f3147b75f56ac4..7167bfde01ffe53092e044d2e5df1df3adb7943f 100644 (file)
@@ -196,7 +196,7 @@ class BaseCPU : public MemObject
 
     /// Take over execution from the given CPU.  Used for warm-up and
     /// sampling.
-    virtual void takeOverFrom(BaseCPU *);
+    virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);
 
     /**
      *  Number of threads we're actually simulating (<= SMT_MAX_THREADS).
index 785165636ea3211cfa73c483e9118dbb9f91216b..38e6a0b5beb25ea48cf2ad615cfbb1b834b02ff4 100644 (file)
@@ -557,12 +557,6 @@ template <class Impl>
 void
 FullO3CPU<Impl>::activateContext(int tid, int delay)
 {
-#if FULL_SYSTEM
-    // Connect the ThreadContext's memory ports (Functional/Virtual
-    // Ports)
-    threadContexts[tid]->connectMemPorts();
-#endif
-
     // Needs to set each stage to running as well.
     if (delay){
         DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
@@ -781,6 +775,18 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
     }
 }
 
+#if FULL_SYSTEM
+template <class Impl>
+void
+FullO3CPU<Impl>::updateMemPorts()
+{
+    // Update all ThreadContext's memory ports (Functional/Virtual
+    // Ports)
+    for (int i = 0; i < thread.size(); ++i)
+        thread[i]->connectMemPorts();
+}
+#endif
+
 template <class Impl>
 void
 FullO3CPU<Impl>::serialize(std::ostream &os)
@@ -941,7 +947,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
 
     activityRec.reset();
 
-    BaseCPU::takeOverFrom(oldCPU);
+    BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort());
 
     fetch.takeOverFrom();
     decode.takeOverFrom();
@@ -978,25 +984,6 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
     }
     if (!tickEvent.scheduled())
         tickEvent.schedule(curTick);
-
-    Port *peer;
-    Port *icachePort = fetch.getIcachePort();
-    if (icachePort->getPeer() == NULL) {
-        peer = oldCPU->getPort("icache_port")->getPeer();
-        icachePort->setPeer(peer);
-    } else {
-        peer = icachePort->getPeer();
-    }
-    peer->setPeer(icachePort);
-
-    Port *dcachePort = iew.getDcachePort();
-    if (dcachePort->getPeer() == NULL) {
-        peer = oldCPU->getPort("dcache_port")->getPeer();
-        dcachePort->setPeer(peer);
-    } else {
-        peer = dcachePort->getPeer();
-    }
-    peer->setPeer(dcachePort);
 }
 
 template <class Impl>
index d217a3e85c1a99ef67c1b3c6c3a85a179b4080be..ea374dd574d0ad3217978f240d8bbeb565a9dd1e 100644 (file)
@@ -357,6 +357,10 @@ class FullO3CPU : public BaseO3CPU
     { return globalSeqNum++; }
 
 #if FULL_SYSTEM
+    /** Update the Virt and Phys ports of all ThreadContexts to
+     * reflect change in memory connections. */
+    void updateMemPorts();
+
     /** Check if this address is a valid instruction address. */
     bool validInstAddr(Addr addr) { return true; }
 
index e68085cfd8756d1667cbe075399c55d79a671152..80f53a7260c85fc8d0975e27e161c4e2ff178058 100644 (file)
@@ -300,6 +300,8 @@ class LSQ {
 
         bool snoopRangeSent;
 
+        virtual void setPeer(Port *port);
+
       protected:
         /** Atomic version of receive.  Panics. */
         virtual Tick recvAtomic(PacketPtr pkt);
@@ -327,6 +329,11 @@ class LSQ {
     /** D-cache port. */
     DcachePort dcachePort;
 
+#if FULL_SYSTEM
+    /** Tell the CPU to update the Phys and Virt ports. */
+    void updateMemPorts() { cpu->updateMemPorts(); }
+#endif
+
   protected:
     /** The LSQ policy for SMT mode. */
     LSQPolicy lsqPolicy;
index fb738f7c9f64a8d6d93ba5fdba4ab9f8d9c7a205..d4994fcb7387ccefa65f1ebaa3b3237652363d7e 100644 (file)
 
 #include "cpu/o3/lsq.hh"
 
+template<class Impl>
+void
+LSQ<Impl>::DcachePort::setPeer(Port *port)
+{
+    Port::setPeer(port);
+
+#if FULL_SYSTEM
+    // Update the ThreadContext's memory ports (Functional/Virtual
+    // Ports)
+    lsq->updateMemPorts();
+#endif
+}
+
 template <class Impl>
 Tick
 LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
index df7e780e639588275a9f0294337bfaa72148d926..ca4627bbff9239ca0bfc17f8abd9c9becf0fef75 100644 (file)
@@ -126,6 +126,17 @@ AtomicSimpleCPU::CpuPort::recvRetry()
     panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
 }
 
+void
+AtomicSimpleCPU::DcachePort::setPeer(Port *port)
+{
+    Port::setPeer(port);
+
+#if FULL_SYSTEM
+    // Update the ThreadContext's memory ports (Functional/Virtual
+    // Ports)
+    cpu->tcBase()->connectMemPorts();
+#endif
+}
 
 AtomicSimpleCPU::AtomicSimpleCPU(Params *p)
     : BaseSimpleCPU(p), tickEvent(this),
@@ -211,7 +222,7 @@ AtomicSimpleCPU::switchOut()
 void
 AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
 {
-    BaseCPU::takeOverFrom(oldCPU);
+    BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
 
     assert(!tickEvent.scheduled());
 
@@ -242,12 +253,6 @@ AtomicSimpleCPU::activateContext(int thread_num, int delay)
 
     notIdleFraction++;
 
-#if FULL_SYSTEM
-    // Connect the ThreadContext's memory ports (Functional/Virtual
-    // Ports)
-    tc->connectMemPorts();
-#endif
-
     //Make sure ticks are still on multiples of cycles
     tickEvent.schedule(nextCycle(curTick + cycles(delay)));
     _status = Running;
index 5bffb76667c4e378cde600199e979bc313b9df11..ad4aa47088b9046fd4ca9b2c9c696918b1d9ad9b 100644 (file)
@@ -81,9 +81,6 @@ class AtomicSimpleCPU : public BaseSimpleCPU
 
     class CpuPort : public Port
     {
-
-        AtomicSimpleCPU *cpu;
-
       public:
 
         CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu)
@@ -94,6 +91,8 @@ class AtomicSimpleCPU : public BaseSimpleCPU
 
       protected:
 
+        AtomicSimpleCPU *cpu;
+
         virtual bool recvTiming(PacketPtr pkt);
 
         virtual Tick recvAtomic(PacketPtr pkt);
@@ -110,7 +109,17 @@ class AtomicSimpleCPU : public BaseSimpleCPU
 
     };
     CpuPort icachePort;
-    CpuPort dcachePort;
+
+    class DcachePort : public CpuPort
+    {
+      public:
+        DcachePort(const std::string &_name, AtomicSimpleCPU *_cpu)
+            : CpuPort(_name, _cpu)
+        { }
+
+        virtual void setPeer(Port *port);
+    };
+    DcachePort dcachePort;
 
     Request  *ifetch_req;
     PacketPtr ifetch_pkt;
index 7f857c68d88e98ba1a1da6c293fbe335bee7e115..6f3604678e070f32741e50e4657b618d30d15cf2 100644 (file)
@@ -194,7 +194,7 @@ TimingSimpleCPU::switchOut()
 void
 TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
 {
-    BaseCPU::takeOverFrom(oldCPU);
+    BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
 
     // if any of this CPU's ThreadContexts are active, mark the CPU as
     // running and schedule its tick event.
@@ -209,23 +209,6 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU)
     if (_status != Running) {
         _status = Idle;
     }
-
-    Port *peer;
-    if (icachePort.getPeer() == NULL) {
-        peer = oldCPU->getPort("icache_port")->getPeer();
-        icachePort.setPeer(peer);
-    } else {
-        peer = icachePort.getPeer();
-    }
-    peer->setPeer(&icachePort);
-
-    if (dcachePort.getPeer() == NULL) {
-        peer = oldCPU->getPort("dcache_port")->getPeer();
-        dcachePort.setPeer(peer);
-    } else {
-        peer = dcachePort.getPeer();
-    }
-    peer->setPeer(&dcachePort);
 }
 
 
@@ -240,12 +223,6 @@ TimingSimpleCPU::activateContext(int thread_num, int delay)
     notIdleFraction++;
     _status = Running;
 
-#if FULL_SYSTEM
-    // Connect the ThreadContext's memory ports (Functional/Virtual
-    // Ports)
-    tc->connectMemPorts();
-#endif
-
     // kick things off by initiating the fetch of the next instruction
     fetchEvent =
         new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
@@ -649,6 +626,18 @@ TimingSimpleCPU::completeDrain()
     drainEvent->process();
 }
 
+void
+TimingSimpleCPU::DcachePort::setPeer(Port *port)
+{
+    Port::setPeer(port);
+
+#if FULL_SYSTEM
+    // Update the ThreadContext's memory ports (Functional/Virtual
+    // Ports)
+    cpu->tcBase()->connectMemPorts();
+#endif
+}
+
 bool
 TimingSimpleCPU::DcachePort::recvTiming(PacketPtr pkt)
 {
index abcb224bfce72fffb692d8b66b0a1d2594242171..ef062d24a88147dc4b47fbd0a72d985b4cdf5676 100644 (file)
@@ -144,6 +144,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
             : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu)
         { }
 
+        virtual void setPeer(Port *port);
+
       protected:
 
         virtual bool recvTiming(PacketPtr pkt);
index 52162bf7640db6a63972f9010619be460e394838..6296b42ca96b979a4877750800a791577a12992b 100644 (file)
@@ -120,7 +120,7 @@ class Port
     { portName = name; }
 
     /** Function to set the pointer for the peer port. */
-    void setPeer(Port *port);
+    virtual void setPeer(Port *port);
 
     /** Function to get the pointer to the peer port. */
     Port *getPeer() { return peer; }