CPU: Moving towards a more general port across CPU models
authorAndreas Hansson <andreas.hansson@arm.com>
Tue, 17 Jan 2012 18:55:08 +0000 (12:55 -0600)
committerAndreas Hansson <andreas.hansson@arm.com>
Tue, 17 Jan 2012 18:55:08 +0000 (12:55 -0600)
This patch performs minimal changes to move the instruction and data
ports from specialised subclasses to the base CPU (to the largest
degree possible). Ultimately it servers to make the CPU(s) have a
well-defined interface to the memory sub-system.

18 files changed:
src/cpu/BaseCPU.py
src/cpu/base.cc
src/cpu/base.hh
src/cpu/inorder/InOrderCPU.py
src/cpu/o3/O3CPU.py
src/cpu/o3/cpu.cc
src/cpu/o3/cpu.hh
src/cpu/o3/fetch.hh
src/cpu/o3/fetch_impl.hh
src/cpu/o3/iew.hh
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_impl.hh
src/cpu/simple/AtomicSimpleCPU.py
src/cpu/simple/TimingSimpleCPU.py
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/simple/timing.cc
src/cpu/simple/timing.hh

index 665d42af07ff4eb3b5dac2310b70bf6a29cccdf3..6800b4c9199def74ef8d67562b62cb6e1c7e62a1 100644 (file)
@@ -152,9 +152,12 @@ class BaseCPU(MemObject):
 
     tracer = Param.InstTracer(default_tracer, "Instruction tracer")
 
-    _cached_ports = []
+    icache_port = Port("Instruction Port")
+    dcache_port = Port("Data Port")
+    _cached_ports = ['icache_port', 'dcache_port']
+
     if buildEnv['TARGET_ISA'] in ['x86', 'arm'] and buildEnv['FULL_SYSTEM']:
-        _cached_ports = ["itb.walker.port", "dtb.walker.port"]
+        _cached_ports += ["itb.walker.port", "dtb.walker.port"]
 
     _uncached_ports = []
     if buildEnv['TARGET_ISA'] == 'x86' and buildEnv['FULL_SYSTEM']:
index c37f4585607c019cd58f8060d1cd839521322e06..2fe41cd4de5ce5625ca3d5524651f0dfd3e55e7b 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
  * Copyright (c) 2011 Regents of the University of California
  * All rights reserved.
@@ -485,3 +497,53 @@ BaseCPU::traceFunctionsInternal(Addr pc)
         functionEntryTick = curTick();
     }
 }
+
+bool
+BaseCPU::CpuPort::recvTiming(PacketPtr pkt)
+{
+    panic("BaseCPU doesn't expect recvTiming callback!");
+    return true;
+}
+
+void
+BaseCPU::CpuPort::recvRetry()
+{
+    panic("BaseCPU doesn't expect recvRetry callback!");
+}
+
+Tick
+BaseCPU::CpuPort::recvAtomic(PacketPtr pkt)
+{
+    panic("BaseCPU doesn't expect recvAtomic callback!");
+    return curTick();
+}
+
+void
+BaseCPU::CpuPort::recvFunctional(PacketPtr pkt)
+{
+    // No internal storage to update (in the general case). In the
+    // long term this should never be called, but that assumed a split
+    // into master/slave and request/response.
+}
+
+void
+BaseCPU::CpuPort::recvStatusChange(Status status)
+{
+    if (status == RangeChange) {
+        if (!snoopRangeSent) {
+            snoopRangeSent = true;
+            sendStatusChange(Port::RangeChange);
+        }
+        return;
+    }
+
+    panic("BaseCPU doesn't expect recvStatusChange callback!");
+}
+
+void
+BaseCPU::CpuPort::getDeviceAddressRanges(AddrRangeList& resp,
+                                         bool& snoop)
+{
+    resp.clear();
+    snoop = false;
+}
index 638556deb96e3794320f1bcfcee992ebeee0092d..5622031f857ccf74e9553ca28492cf75d51f79d1 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
  * Copyright (c) 2011 Regents of the University of California
  * All rights reserved.
@@ -95,6 +107,57 @@ class BaseCPU : public MemObject
     // therefore no setCpuId() method is provided
     int _cpuId;
 
+    /**
+     * Define a base class for the CPU ports (instruction and data)
+     * that is refined in the subclasses. This class handles the
+     * common cases, i.e. the functional accesses and the status
+     * changes and address range queries. The default behaviour for
+     * both atomic and timing access is to panic and the corresponding
+     * subclasses have to override these methods.
+     */
+    class CpuPort : public Port
+    {
+      public:
+
+        /**
+         * Create a CPU port with a name and a structural owner.
+         *
+         * @param _name port name including the owner
+         * @param _name structural owner of this port
+         */
+        CpuPort(const std::string& _name, MemObject* _owner) :
+            Port(_name, _owner), snoopRangeSent(false)
+        { }
+
+      protected:
+
+        virtual bool recvTiming(PacketPtr pkt);
+
+        virtual Tick recvAtomic(PacketPtr pkt);
+
+        virtual void recvRetry();
+
+        void recvFunctional(PacketPtr pkt);
+
+        void recvStatusChange(Status status);
+
+        /**
+         * Add CPU ports are master ports and do not respond to any
+         * address ranges. Note that the LSQ snoops for specific ISAs
+         * and thus has to override this method.
+         *
+         * @param resp list of ranges this port responds to
+         * @param snoop indicating if the port snoops or not
+         */
+        virtual void getDeviceAddressRanges(AddrRangeList& resp,
+                                            bool& snoop);
+
+      private:
+
+        bool snoopRangeSent;
+
+    };
+
   public:
     /** Reads this CPU's ID. */
     int cpuId() { return _cpuId; }
index 4766a1ac10dfb5902a416ebb1239fa3178178928..40af48b1922ff303ad08bf2a43160500db0274ea 100644 (file)
@@ -44,9 +44,6 @@ class InOrderCPU(BaseCPU):
 
     fetchMemPort = Param.String("icache_port" , "Name of Memory Port to get instructions from")
     dataMemPort = Param.String("dcache_port" , "Name of Memory Port to get data from")
-    icache_port = Port("Instruction Port")
-    dcache_port = Port("Data Port")
-    _cached_ports = ['icache_port', 'dcache_port']
 
     fetchBuffSize = Param.Unsigned(4, "Fetch Buffer Size (Number of Cache Blocks Stored)")
     memBlockSize = Param.Unsigned(64, "Memory Block Size")
index 2a5b6782fdc21d2a9739cbefd6e82a121f784f4b..9dfcc8b9eb09f6efa04e4ff9f89402a9d6ed6636 100644 (file)
@@ -53,9 +53,6 @@ class DerivO3CPU(BaseCPU):
         checker.dtb = Parent.dtb
 
     cachePorts = Param.Unsigned(200, "Cache Ports")
-    icache_port = Port("Instruction Port")
-    dcache_port = Port("Data Port")
-    _cached_ports = BaseCPU._cached_ports + ['icache_port', 'dcache_port']
 
     decodeToFetchDelay = Param.Unsigned(1, "Decode to fetch delay")
     renameToFetchDelay = Param.Unsigned(1 ,"Rename to fetch delay")
index ee0c3a88a829ba0f2446792c656796cece51a15c..7e0b4cee7bd8c779ccc8ddc45dd9fb9d90b4a77e 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2006 The Regents of The University of Michigan
  * Copyright (c) 2011 Regents of the University of California
  * All rights reserved.
@@ -79,6 +91,42 @@ BaseO3CPU::regStats()
     BaseCPU::regStats();
 }
 
+template<class Impl>
+bool
+FullO3CPU<Impl>::IcachePort::recvTiming(PacketPtr pkt)
+{
+    DPRINTF(O3CPU, "Fetch unit received timing\n");
+    if (pkt->isResponse()) {
+        // We shouldn't ever get a block in ownership state
+        assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
+
+        fetch->processCacheCompletion(pkt);
+    }
+    //else Snooped a coherence request, just return
+    return true;
+}
+
+template<class Impl>
+void
+FullO3CPU<Impl>::IcachePort::recvRetry()
+{
+    fetch->recvRetry();
+}
+
+template <class Impl>
+bool
+FullO3CPU<Impl>::DcachePort::recvTiming(PacketPtr pkt)
+{
+    return lsq->recvTiming(pkt);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::DcachePort::recvRetry()
+{
+    lsq->recvRetry();
+}
+
 template <class Impl>
 FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
     : Event(CPU_Tick_Pri), cpu(c)
@@ -194,6 +242,9 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
                  TheISA::NumMiscRegs * numThreads,
                  TheISA::ZeroReg),
 
+      icachePort(&fetch, this),
+      dcachePort(&iew.ldstQueue, this),
+
       timeBuffer(params->backComSize, params->forwardComSize),
       fetchQueue(params->backComSize, params->forwardComSize),
       decodeQueue(params->backComSize, params->forwardComSize),
@@ -218,6 +269,7 @@ FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
     if (params->checker) {
         BaseCPU *temp_checker = params->checker;
         checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
+        checker->setIcachePort(&icachePort);
 #if FULL_SYSTEM
         checker->setSystem(params->system);
 #endif
@@ -528,9 +580,9 @@ Port *
 FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
 {
     if (if_name == "dcache_port")
-        return iew.getDcachePort();
+        return &dcachePort;
     else if (if_name == "icache_port")
-        return fetch.getIcachePort();
+        return &icachePort;
     else
         panic("No Such Port\n");
 }
@@ -606,6 +658,13 @@ FullO3CPU<Impl>::init()
     for (ThreadID tid = 0; tid < numThreads; ++tid)
         thread[tid]->inSyscall = true;
 
+    // this CPU could still be unconnected if we are restoring from a
+    // checkpoint and this CPU is to be switched in, thus we can only
+    // do this here if the instruction port is actually connected, if
+    // not we have to do it as part of takeOverFrom
+    if (icachePort.isConnected())
+        fetch.setIcache();
+
 #if FULL_SYSTEM
     for (ThreadID tid = 0; tid < numThreads; tid++) {
         ThreadContext *src_tc = threadContexts[tid];
@@ -1170,7 +1229,7 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
 
     activityRec.reset();
 
-    BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort());
+    BaseCPU::takeOverFrom(oldCPU, &icachePort, &dcachePort);
 
     fetch.takeOverFrom();
     decode.takeOverFrom();
index 652e6d99a32d86691127df985235d2f0e3b81926..1dd49a4f3ab2e46d757456cfb138a72fc95ca178 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2005 The Regents of The University of Michigan
  * Copyright (c) 2011 Regents of the University of California
  * All rights reserved.
@@ -118,6 +130,70 @@ class FullO3CPU : public BaseO3CPU
     Status _threadStatus[Impl::MaxThreads];
 
   private:
+
+    /**
+     * IcachePort class for instruction fetch.
+     */
+    class IcachePort : public CpuPort
+    {
+      protected:
+        /** Pointer to fetch. */
+        DefaultFetch<Impl> *fetch;
+
+      public:
+        /** Default constructor. */
+        IcachePort(DefaultFetch<Impl> *_fetch, FullO3CPU<Impl>* _cpu)
+            : CpuPort(_fetch->name() + "-iport", _cpu), fetch(_fetch)
+        { }
+
+      protected:
+
+        /** Timing version of receive.  Handles setting fetch to the
+         * proper status to start fetching. */
+        virtual bool recvTiming(PacketPtr pkt);
+
+        /** Handles doing a retry of a failed fetch. */
+        virtual void recvRetry();
+    };
+
+    /**
+     * DcachePort class for the load/store queue.
+     */
+    class DcachePort : public CpuPort
+    {
+      protected:
+
+        /** Pointer to LSQ. */
+        LSQ<Impl> *lsq;
+
+      public:
+        /** Default constructor. */
+        DcachePort(LSQ<Impl> *_lsq, FullO3CPU<Impl>* _cpu)
+            : CpuPort(_lsq->name() + "-dport", _cpu), lsq(_lsq)
+        { }
+
+      protected:
+
+        /** Timing version of receive.  Handles writing back and
+         * completing the load or store that has returned from
+         * memory. */
+        virtual bool recvTiming(PacketPtr pkt);
+
+        /** Handles doing a retry of the previous send. */
+        virtual void recvRetry();
+
+        /**
+         * As this CPU requires snooping to maintain the load store queue
+         * change the behaviour from the base CPU port.
+         *
+         * @param resp list of ranges this port responds to
+         * @param snoop indicating if the port snoops or not
+         */
+        virtual void getDeviceAddressRanges(AddrRangeList& resp,
+                                            bool& snoop)
+        { resp.clear(); snoop = true; }
+    };
+
     class TickEvent : public Event
     {
       private:
@@ -566,6 +642,12 @@ class FullO3CPU : public BaseO3CPU
 
     TheISA::ISA isa[Impl::MaxThreads];
 
+    /** Instruction port. Note that it has to appear after the fetch stage. */
+    IcachePort icachePort;
+
+    /** Data port. Note that it has to appear after the iew stages */
+    DcachePort dcachePort;
+
   public:
     /** Enum to give each stage a specific index, so when calling
      *  activateStage() or deactivateStage(), they can specify which stage
@@ -704,8 +786,11 @@ class FullO3CPU : public BaseO3CPU
                                          data, store_idx);
     }
 
+    /** Used by the fetch unit to get a hold of the instruction port. */
+    Port* getIcachePort() { return &icachePort; }
+
     /** Get the dcache port (used to find block size for translations). */
-    Port *getDcachePort() { return this->iew.ldstQueue.getDcachePort(); }
+    Port* getDcachePort() { return &dcachePort; }
 
     Addr lockAddr;
 
index d09d7f6804adb1fa0694f20838f4f117383ddd7d..f5d275593e5d4928388a400f63ca003a4134bea7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -85,48 +85,6 @@ class DefaultFetch
     typedef TheISA::MachInst MachInst;
     typedef TheISA::ExtMachInst ExtMachInst;
 
-    /** IcachePort class for DefaultFetch.  Handles doing the
-     * communication with the cache/memory.
-     */
-    class IcachePort : public Port
-    {
-      protected:
-        /** Pointer to fetch. */
-        DefaultFetch<Impl> *fetch;
-
-      public:
-        /** Default constructor. */
-        IcachePort(DefaultFetch<Impl> *_fetch)
-            : Port(_fetch->name() + "-iport", _fetch->cpu), fetch(_fetch)
-        { }
-
-        bool snoopRangeSent;
-
-        virtual void setPeer(Port *port);
-
-      protected:
-        /** Atomic version of receive.  Panics. */
-        virtual Tick recvAtomic(PacketPtr pkt);
-
-        /** Functional version of receive.  Panics. */
-        virtual void recvFunctional(PacketPtr pkt);
-
-        /** Receives status change.  Other than range changing, panics. */
-        virtual void recvStatusChange(Status status);
-
-        /** Returns the address ranges of this device. */
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            bool &snoop)
-        { resp.clear(); snoop = true; }
-
-        /** Timing version of receive.  Handles setting fetch to the
-         * proper status to start fetching. */
-        virtual bool recvTiming(PacketPtr pkt);
-
-        /** Handles doing a retry of a failed fetch. */
-        virtual void recvRetry();
-    };
-
     class FetchTranslation : public BaseTLB::Translation
     {
       protected:
@@ -248,9 +206,6 @@ class DefaultFetch
     /** Registers statistics. */
     void regStats();
 
-    /** Returns the icache port. */
-    Port *getIcachePort() { return icachePort; }
-
     /** Sets the main backwards communication time buffer pointer. */
     void setTimeBuffer(TimeBuffer<TimeStruct> *time_buffer);
 
@@ -266,6 +221,9 @@ class DefaultFetch
     /** Tells the fetch stage that the Icache is set. */
     void setIcache();
 
+    /** Handles retrying the fetch access. */
+    void recvRetry();
+
     /** Processes cache completion event. */
     void processCacheCompletion(PacketPtr pkt);
 
@@ -389,9 +347,6 @@ class DefaultFetch
                          StaticInstPtr curMacroop, TheISA::PCState thisPC,
                          TheISA::PCState nextPC, bool trace);
 
-    /** Handles retrying the fetch access. */
-    void recvRetry();
-
     /** Returns the appropriate thread to fetch, given the fetch policy. */
     ThreadID getFetchingThread(FetchPriority &fetch_priority);
 
@@ -440,9 +395,6 @@ class DefaultFetch
     /** Wire used to write any information heading to decode. */
     typename TimeBuffer<FetchStruct>::wire toDecode;
 
-    /** Icache interface. */
-    IcachePort *icachePort;
-
     /** BPredUnit. */
     BPredUnit branchPred;
 
index ccab47d2f6bdfba1f57809537fb283f127a5c633..d145fb09904f40bdc385dabff51d96c78a46264f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
 
 using namespace std;
 
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::setPeer(Port *port)
-{
-    Port::setPeer(port);
-
-    fetch->setIcache();
-}
-
-template<class Impl>
-Tick
-DefaultFetch<Impl>::IcachePort::recvAtomic(PacketPtr pkt)
-{
-    panic("DefaultFetch doesn't expect recvAtomic callback!");
-    return curTick();
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
-{
-    DPRINTF(Fetch, "DefaultFetch doesn't update its state from a "
-            "functional call.\n");
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::recvStatusChange(Status status)
-{
-    if (status == RangeChange) {
-        if (!snoopRangeSent) {
-            snoopRangeSent = true;
-            sendStatusChange(Port::RangeChange);
-        }
-        return;
-    }
-
-    panic("DefaultFetch doesn't expect recvStatusChange callback!");
-}
-
-template<class Impl>
-bool
-DefaultFetch<Impl>::IcachePort::recvTiming(PacketPtr pkt)
-{
-    DPRINTF(Fetch, "Received timing\n");
-    if (pkt->isResponse()) {
-        // We shouldn't ever get a block in ownership state
-        assert(!(pkt->memInhibitAsserted() && !pkt->sharedAsserted()));
-
-        fetch->processCacheCompletion(pkt);
-    }
-    //else Snooped a coherence request, just return
-    return true;
-}
-
-template<class Impl>
-void
-DefaultFetch<Impl>::IcachePort::recvRetry()
-{
-    fetch->recvRetry();
-}
-
 template<class Impl>
 DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params)
     : cpu(_cpu),
@@ -191,17 +129,6 @@ DefaultFetch<Impl>::DefaultFetch(O3CPU *_cpu, DerivO3CPUParams *params)
 
     // Get the size of an instruction.
     instSize = sizeof(TheISA::MachInst);
-
-    // Name is finally available, so create the port.
-    icachePort = new IcachePort(this);
-
-    icachePort->snoopRangeSent = false;
-
-#if USE_CHECKER
-    if (cpu->checker) {
-        cpu->checker->setIcachePort(icachePort);
-    }
-#endif
 }
 
 template <class Impl>
@@ -404,8 +331,10 @@ template<class Impl>
 void
 DefaultFetch<Impl>::setIcache()
 {
+    assert(cpu->getIcachePort()->isConnected());
+
     // Size of cache block.
-    cacheBlkSize = icachePort->peerBlockSize();
+    cacheBlkSize = cpu->getIcachePort()->peerBlockSize();
 
     // Create mask to get rid of offset bits.
     cacheBlkMask = (cacheBlkSize - 1);
@@ -496,6 +425,10 @@ template <class Impl>
 void
 DefaultFetch<Impl>::takeOverFrom()
 {
+    // the instruction port is now connected so we can get the block
+    // size
+    setIcache();
+
     // Reset all state
     for (ThreadID i = 0; i < Impl::MaxThreads; ++i) {
         stalls[i].decode = 0;
@@ -686,7 +619,7 @@ DefaultFetch<Impl>::finishTranslation(Fault fault, RequestPtr mem_req)
         fetchedCacheLines++;
 
         // Access the cache.
-        if (!icachePort->sendTiming(data_pkt)) {
+        if (!cpu->getIcachePort()->sendTiming(data_pkt)) {
             assert(retryPkt == NULL);
             assert(retryTid == InvalidThreadID);
             DPRINTF(Fetch, "[tid:%i] Out of MSHRs!\n", tid);
@@ -1405,7 +1338,7 @@ DefaultFetch<Impl>::recvRetry()
         assert(retryTid != InvalidThreadID);
         assert(fetchStatus[retryTid] == IcacheWaitRetry);
 
-        if (icachePort->sendTiming(retryPkt)) {
+        if (cpu->getIcachePort()->sendTiming(retryPkt)) {
             fetchStatus[retryTid] = IcacheWaitResponse;
             retryPkt = NULL;
             retryTid = InvalidThreadID;
index 113d0756e0fc23e4ba0b889e82733bc7e552a00b..c58361cd6951ac6c9af59b2e0f60438324aaa5da 100644 (file)
@@ -139,9 +139,6 @@ class DefaultIEW
     /** Initializes stage; sends back the number of free IQ and LSQ entries. */
     void initStage();
 
-    /** Returns the dcache port. */
-    Port *getDcachePort() { return ldstQueue.getDcachePort(); }
-
     /** Sets main time buffer used for backwards communication. */
     void setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr);
 
index d01a6b0a47f2bd9cdb13136a36eca374fe58a269..731c67ae6e33d3f8decbc3e440ba06c33b067318 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2004-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -66,13 +78,6 @@ class LSQ {
     /** Registers statistics of each LSQ unit. */
     void regStats();
 
-    /** Returns dcache port.
-     *  @todo: Dcache port needs to be moved up to this level for SMT
-     *  to work.  For now it just returns the port from one of the
-     *  threads.
-     */
-    Port *getDcachePort() { return &dcachePort; }
-
     /** Sets the pointer to the list of active threads. */
     void setActiveThreads(std::list<ThreadID> *at_ptr);
     /** Switches out the LSQ. */
@@ -282,56 +287,25 @@ class LSQ {
     Fault write(RequestPtr req, RequestPtr sreqLow, RequestPtr sreqHigh,
                 uint8_t *data, int store_idx);
 
+    /**
+     * Retry the previous send that failed.
+     */
+    void recvRetry();
+
+    /**
+     * Handles writing back and completing the load or store that has
+     * returned from memory.
+     *
+     * @param pkt Response packet from the memory sub-system
+     */
+    bool recvTiming(PacketPtr pkt);
+
     /** The CPU pointer. */
     O3CPU *cpu;
 
     /** The IEW stage pointer. */
     IEW *iewStage;
 
-    /** DcachePort class for this LSQ.  Handles doing the
-     * communication with the cache/memory.
-     */
-    class DcachePort : public Port
-    {
-      protected:
-        /** Pointer to LSQ. */
-        LSQ *lsq;
-
-      public:
-        /** Default constructor. */
-        DcachePort(LSQ *_lsq)
-            : Port(_lsq->name() + "-dport", _lsq->cpu), lsq(_lsq)
-        { }
-
-        bool snoopRangeSent;
-
-      protected:
-        /** Atomic version of receive.  Panics. */
-        virtual Tick recvAtomic(PacketPtr pkt);
-
-        /** Functional version of receive.  Panics. */
-        virtual void recvFunctional(PacketPtr pkt);
-
-        /** Receives status change.  Other than range changing, panics. */
-        virtual void recvStatusChange(Status status);
-
-        /** Returns the address ranges of this device. */
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            bool &snoop)
-        { resp.clear(); snoop = true; }
-
-        /** Timing version of receive.  Handles writing back and
-         * completing the load or store that has returned from
-         * memory. */
-        virtual bool recvTiming(PacketPtr pkt);
-
-        /** Handles doing a retry of the previous send. */
-        virtual void recvRetry();
-    };
-
-    /** D-cache port. */
-    DcachePort dcachePort;
-
   protected:
     /** The LSQ policy for SMT mode. */
     LSQPolicy lsqPolicy;
index 61dced14f574c2b2c03b74d8a5cddbf47644e751..f1642be9c0fada6e4b0431cf0dac8c31a317c4c6 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2011 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2005-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
 
 using namespace std;
 
-template <class Impl>
-Tick
-LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt)
-{
-    panic("O3CPU model does not work with atomic mode!");
-    return curTick();
-}
-
-template <class Impl>
-void
-LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
-{
-    DPRINTF(LSQ, "LSQ doesn't update things on a recvFunctional.\n");
-}
-
-template <class Impl>
-void
-LSQ<Impl>::DcachePort::recvStatusChange(Status status)
-{
-    if (status == RangeChange) {
-        if (!snoopRangeSent) {
-            snoopRangeSent = true;
-            sendStatusChange(Port::RangeChange);
-        }
-        return;
-    }
-    panic("O3CPU doesn't expect recvStatusChange callback!");
-}
-
-template <class Impl>
-bool
-LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
-{
-    if (pkt->isError())
-        DPRINTF(LSQ, "Got error packet back for address: %#X\n", pkt->getAddr());
-    if (pkt->isResponse()) {
-        lsq->thread[pkt->req->threadId()].completeDataAccess(pkt);
-    } else {
-        DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
-                pkt->cmdString());
-
-        // must be a snoop
-        if (pkt->isInvalidate()) {
-            DPRINTF(LSQ, "received invalidation for addr:%#x\n", pkt->getAddr());
-            for (ThreadID tid = 0; tid < lsq->numThreads; tid++) {
-                lsq->thread[tid].checkSnoop(pkt);
-            }
-        }
-        // to provide stronger consistency model
-    }
-    return true;
-}
-
-template <class Impl>
-void
-LSQ<Impl>::DcachePort::recvRetry()
-{
-    if (lsq->retryTid == -1)
-    {
-        //Squashed, so drop it
-        return;
-    }
-    int curr_retry_tid = lsq->retryTid;
-    // Speculatively clear the retry Tid.  This will get set again if
-    // the LSQUnit was unable to complete its access.
-    lsq->retryTid = -1;
-    lsq->thread[curr_retry_tid].recvRetry();
-}
-
 template <class Impl>
 LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
-    : cpu(cpu_ptr), iewStage(iew_ptr), dcachePort(this),
+    : cpu(cpu_ptr), iewStage(iew_ptr),
       LQEntries(params->LQEntries),
       SQEntries(params->SQEntries),
       numThreads(params->numThreads),
       retryTid(-1)
 {
-    dcachePort.snoopRangeSent = false;
-
     //**********************************************/
     //************ Handle SMT Parameters ***********/
     //**********************************************/
@@ -170,7 +111,7 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
     for (ThreadID tid = 0; tid < numThreads; tid++) {
         thread[tid].init(cpu, iew_ptr, params, this,
                          maxLQEntries, maxSQEntries, tid);
-        thread[tid].setDcachePort(&dcachePort);
+        thread[tid].setDcachePort(cpu_ptr->getDcachePort());
     }
 }
 
@@ -360,6 +301,48 @@ LSQ<Impl>::violation()
     return false;
 }
 
+template <class Impl>
+void
+LSQ<Impl>::recvRetry()
+{
+    if (retryTid == InvalidThreadID)
+    {
+        //Squashed, so drop it
+        return;
+    }
+    int curr_retry_tid = retryTid;
+    // Speculatively clear the retry Tid.  This will get set again if
+    // the LSQUnit was unable to complete its access.
+    retryTid = -1;
+    thread[curr_retry_tid].recvRetry();
+}
+
+template <class Impl>
+bool
+LSQ<Impl>::recvTiming(PacketPtr pkt)
+{
+    if (pkt->isError())
+        DPRINTF(LSQ, "Got error packet back for address: %#X\n",
+                pkt->getAddr());
+    if (pkt->isResponse()) {
+        thread[pkt->req->threadId()].completeDataAccess(pkt);
+    } else {
+        DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(),
+                pkt->cmdString());
+
+        // must be a snoop
+        if (pkt->isInvalidate()) {
+            DPRINTF(LSQ, "received invalidation for addr:%#x\n",
+                    pkt->getAddr());
+            for (ThreadID tid = 0; tid < numThreads; tid++) {
+                thread[tid].checkSnoop(pkt);
+            }
+        }
+        // to provide stronger consistency model
+    }
+    return true;
+}
+
 template<class Impl>
 int
 LSQ<Impl>::getCount()
index a4d807f86460c6b3f507bda967f96b8a7ca246f6..93cd02ba731d03a5c620ef6f2088dece834695b2 100644 (file)
@@ -34,8 +34,4 @@ class AtomicSimpleCPU(BaseSimpleCPU):
     width = Param.Int(1, "CPU width")
     simulate_data_stalls = Param.Bool(False, "Simulate dcache stall cycles")
     simulate_inst_stalls = Param.Bool(False, "Simulate icache stall cycles")
-    icache_port = Port("Instruction Port")
-    dcache_port = Port("Data Port")
     physmem_port = Port("Physical Memory Port")
-    _cached_ports = BaseSimpleCPU._cached_ports + \
-                    ['icache_port', 'dcache_port']
index 8d6888f72e653e2fefbf27cd7d4fcb833583ec98..61491b0872ce7491af9fc4a1f52bfe18d234e6b0 100644 (file)
@@ -31,6 +31,3 @@ from BaseSimpleCPU import BaseSimpleCPU
 
 class TimingSimpleCPU(BaseSimpleCPU):
     type = 'TimingSimpleCPU'
-    icache_port = Port("Instruction Port")
-    dcache_port = Port("Data Port")
-    _cached_ports = BaseSimpleCPU._cached_ports + ['icache_port', 'dcache_port']
index b40109ec12581747136819f26fd1e13d4b1cfe78..84f42da08cfe68cdb63673cfe2235c036b66595e 100644 (file)
@@ -107,47 +107,6 @@ AtomicSimpleCPU::init()
     data_write_req.setThreadContext(_cpuId, 0); // Add thread ID here too
 }
 
-bool
-AtomicSimpleCPU::CpuPort::recvTiming(PacketPtr pkt)
-{
-    panic("AtomicSimpleCPU doesn't expect recvTiming callback!");
-    return true;
-}
-
-Tick
-AtomicSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt)
-{
-    //Snooping a coherence request, just return
-    return 0;
-}
-
-void
-AtomicSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt)
-{
-    //No internal storage to update, just return
-    return;
-}
-
-void
-AtomicSimpleCPU::CpuPort::recvStatusChange(Status status)
-{
-    if (status == RangeChange) {
-        if (!snoopRangeSent) {
-            snoopRangeSent = true;
-            sendStatusChange(Port::RangeChange);
-        }
-        return;
-    }
-
-    panic("AtomicSimpleCPU doesn't expect recvStatusChange callback!");
-}
-
-void
-AtomicSimpleCPU::CpuPort::recvRetry()
-{
-    panic("AtomicSimpleCPU doesn't expect recvRetry callback!");
-}
-
 AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
     : BaseSimpleCPU(p), tickEvent(this), width(p->width), locked(false),
       simulate_data_stalls(p->simulate_data_stalls),
@@ -156,10 +115,6 @@ AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
       physmemPort(name() + "-iport", this), hasPhysMemPort(false)
 {
     _status = Idle;
-
-    icachePort.snoopRangeSent = false;
-    dcachePort.snoopRangeSent = false;
-
 }
 
 
index c3d78a3815845f09339de910c8b4ce1daea2fa1c..77a9d6b0d58a5dbd4d7ff3ebb0a98bda2b8a6259 100644 (file)
@@ -64,38 +64,31 @@ class AtomicSimpleCPU : public BaseSimpleCPU
     // main simulation loop (one cycle)
     void tick();
 
-    class CpuPort : public Port
+    /**
+     * An AtomicCPUPort overrides the default behaviour of the
+     * recvAtomic and ignores the packet instead of panicking.
+     */
+    class AtomicCPUPort : public CpuPort
     {
+
       public:
 
-        CpuPort(const std::string &_name, AtomicSimpleCPU *_cpu)
-            : Port(_name, _cpu), cpu(_cpu)
+        AtomicCPUPort(const std::string &_name, BaseCPU* _cpu)
+            : CpuPort(_name, _cpu)
         { }
 
-        bool snoopRangeSent;
-
       protected:
 
-        AtomicSimpleCPU *cpu;
-
-        virtual bool recvTiming(PacketPtr pkt);
-
-        virtual Tick recvAtomic(PacketPtr pkt);
-
-        virtual void recvFunctional(PacketPtr pkt);
-
-        virtual void recvStatusChange(Status status);
-
-        virtual void recvRetry();
-
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-            bool &snoop)
-        { resp.clear(); snoop = true; }
+        virtual Tick recvAtomic(PacketPtr pkt)
+        {
+            // Snooping a coherence request, just return
+            return 0;
+        }
 
     };
-    CpuPort icachePort;
 
-    CpuPort dcachePort;
+    AtomicCPUPort icachePort;
+    AtomicCPUPort dcachePort;
 
     CpuPort physmemPort;
     bool hasPhysMemPort;
index 4375d2549e5684445a227d25aa8c6ea8cfd0e2cc..70583cae968b98d729bf38ffe2ab8ab1b9b20d78 100644 (file)
@@ -87,51 +87,19 @@ TimingSimpleCPU::init()
 #endif
 }
 
-Tick
-TimingSimpleCPU::CpuPort::recvAtomic(PacketPtr pkt)
-{
-    panic("TimingSimpleCPU doesn't expect recvAtomic callback!");
-    return curTick();
-}
-
 void
-TimingSimpleCPU::CpuPort::recvFunctional(PacketPtr pkt)
-{
-    //No internal storage to update, jusst return
-    return;
-}
-
-void
-TimingSimpleCPU::CpuPort::recvStatusChange(Status status)
-{
-    if (status == RangeChange) {
-        if (!snoopRangeSent) {
-            snoopRangeSent = true;
-            sendStatusChange(Port::RangeChange);
-        }
-        return;
-    }
-
-    panic("TimingSimpleCPU doesn't expect recvStatusChange callback!");
-}
-
-
-void
-TimingSimpleCPU::CpuPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
+TimingSimpleCPU::TimingCPUPort::TickEvent::schedule(PacketPtr _pkt, Tick t)
 {
     pkt = _pkt;
     cpu->schedule(this, t);
 }
 
 TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p)
-    : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this, p->clock),
-    dcachePort(this, p->clock), fetchEvent(this)
+    : BaseSimpleCPU(p), fetchTranslation(this), icachePort(this),
+    dcachePort(this), fetchEvent(this)
 {
     _status = Idle;
 
-    icachePort.snoopRangeSent = false;
-    dcachePort.snoopRangeSent = false;
-
     ifetch_pkt = dcache_pkt = NULL;
     drainEvent = NULL;
     previousTick = 0;
index 6e95ddd9dba7b570e45cb007b9730079f15449d7..dce3c58ff4962c726a0be9fe1f4a38fadc581ae8 100644 (file)
@@ -137,31 +137,23 @@ class TimingSimpleCPU : public BaseSimpleCPU
     // This function always implicitly uses dcache_pkt.
     bool handleWritePacket();
 
-    class CpuPort : public Port
+    /**
+     * A TimingCPUPort overrides the default behaviour of the
+     * recvTiming and recvRetry and implements events for the
+     * scheduling of handling of incoming packets in the following
+     * cycle.
+     */
+    class TimingCPUPort : public CpuPort
     {
-      protected:
-        TimingSimpleCPU *cpu;
-        Tick lat;
-
       public:
 
-        CpuPort(const std::string &_name, TimingSimpleCPU *_cpu, Tick _lat)
-            : Port(_name, _cpu), cpu(_cpu), lat(_lat), retryEvent(this)
+        TimingCPUPort(const std::string& _name, TimingSimpleCPU* _cpu)
+            : CpuPort(_name, _cpu), cpu(_cpu), retryEvent(this)
         { }
 
-        bool snoopRangeSent;
-
       protected:
 
-        virtual Tick recvAtomic(PacketPtr pkt);
-
-        virtual void recvFunctional(PacketPtr pkt);
-
-        virtual void recvStatusChange(Status status);
-
-        virtual void getDeviceAddressRanges(AddrRangeList &resp,
-                                            bool &snoop)
-        { resp.clear(); snoop = false; }
+        TimingSimpleCPU* cpu;
 
         struct TickEvent : public Event
         {
@@ -169,7 +161,7 @@ class TimingSimpleCPU : public BaseSimpleCPU
             TimingSimpleCPU *cpu;
             CpuPort *port;
 
-            TickEvent(TimingSimpleCPU *_cpu) : cpu(_cpu) {}
+            TickEvent(TimingSimpleCPU *_cpu) : pkt(NULL), cpu(_cpu) {}
             const char *description() const { return "Timing CPU tick"; }
             void schedule(PacketPtr _pkt, Tick t);
         };
@@ -177,12 +169,13 @@ class TimingSimpleCPU : public BaseSimpleCPU
         EventWrapper<Port, &Port::sendRetry> retryEvent;
     };
 
-    class IcachePort : public CpuPort
+    class IcachePort : public TimingCPUPort
     {
       public:
 
-        IcachePort(TimingSimpleCPU *_cpu, Tick _lat)
-            : CpuPort(_cpu->name() + "-iport", _cpu, _lat), tickEvent(_cpu)
+        IcachePort(TimingSimpleCPU *_cpu)
+            : TimingCPUPort(_cpu->name() + "-iport", _cpu),
+              tickEvent(_cpu)
         { }
 
       protected:
@@ -204,12 +197,12 @@ class TimingSimpleCPU : public BaseSimpleCPU
 
     };
 
-    class DcachePort : public CpuPort
+    class DcachePort : public TimingCPUPort
     {
       public:
 
-        DcachePort(TimingSimpleCPU *_cpu, Tick _lat)
-            : CpuPort(_cpu->name() + "-dport", _cpu, _lat), tickEvent(_cpu)
+        DcachePort(TimingSimpleCPU *_cpu)
+            : TimingCPUPort(_cpu->name() + "-dport", _cpu), tickEvent(_cpu)
         { }
 
       protected: