MEM: Introduce the master/slave port sub-classes in C++
authorWilliam Wang <william.wang@arm.com>
Fri, 30 Mar 2012 13:40:11 +0000 (09:40 -0400)
committerWilliam Wang <william.wang@arm.com>
Fri, 30 Mar 2012 13:40:11 +0000 (09:40 -0400)
This patch introduces the notion of a master and slave port in the C++
code, thus bringing the previous classification from the Python
classes into the corresponding simulation objects and memory objects.

The patch enables us to classify behaviours into the two bins and add
assumptions and enfore compliance, also simplifying the two
interfaces. As a starting point, isSnooping is confined to a master
port, and getAddrRanges to slave ports. More of these specilisations
are to come in later patches.

The getPort function is not getMasterPort and getSlavePort, and
returns a port reference rather than a pointer as NULL would never be
a valid return value. The default implementation of these two
functions is placed in MemObject, and calls fatal.

The one drawback with this specific patch is that it requires some
code duplication, e.g. QueuedPort becomes QueuedMasterPort and
QueuedSlavePort, and BusPort becomes BusMasterPort and BusSlavePort
(avoiding multiple inheritance). With the later introduction of the
port interfaces, moving the functionality outside the port itself, a
lot of the duplicated code will disappear again.

75 files changed:
src/arch/arm/table_walker.cc
src/arch/arm/table_walker.hh
src/arch/arm/tlb.cc
src/arch/arm/tlb.hh
src/arch/x86/interrupts.cc
src/arch/x86/interrupts.hh
src/arch/x86/pagetable_walker.cc
src/arch/x86/pagetable_walker.hh
src/arch/x86/tlb.cc
src/arch/x86/tlb.hh
src/cpu/base.cc
src/cpu/base.hh
src/cpu/checker/cpu.hh
src/cpu/inorder/resources/cache_unit.hh
src/cpu/o3/cpu.hh
src/cpu/o3/lsq_unit.hh
src/cpu/o3/lsq_unit_impl.hh
src/cpu/ozone/OzoneCPU.py
src/cpu/ozone/cpu.hh
src/cpu/ozone/cpu_impl.hh
src/cpu/ozone/front_end.hh
src/cpu/ozone/front_end_impl.hh
src/cpu/ozone/lw_lsq.hh
src/cpu/ozone/lw_lsq_impl.hh
src/cpu/simple/atomic.cc
src/cpu/simple/atomic.hh
src/cpu/testers/directedtest/RubyDirectedTester.cc
src/cpu/testers/directedtest/RubyDirectedTester.hh
src/cpu/testers/memtest/memtest.cc
src/cpu/testers/memtest/memtest.hh
src/cpu/testers/networktest/networktest.cc
src/cpu/testers/networktest/networktest.hh
src/cpu/testers/rubytest/RubyTester.cc
src/cpu/testers/rubytest/RubyTester.hh
src/dev/copy_engine.cc
src/dev/copy_engine.hh
src/dev/io_device.cc
src/dev/io_device.hh
src/dev/pcidev.hh
src/dev/x86/i82094aa.cc
src/dev/x86/i82094aa.hh
src/dev/x86/intdev.cc
src/dev/x86/intdev.hh
src/kern/tru64/tru64_events.cc
src/mem/bridge.cc
src/mem/bridge.hh
src/mem/bus.cc
src/mem/bus.hh
src/mem/cache/base.cc
src/mem/cache/base.hh
src/mem/cache/builder.cc
src/mem/cache/cache.hh
src/mem/cache/cache_impl.hh
src/mem/fs_translating_port_proxy.cc
src/mem/fs_translating_port_proxy.hh
src/mem/mem_object.cc
src/mem/mem_object.hh
src/mem/mport.cc
src/mem/mport.hh
src/mem/physical.cc
src/mem/physical.hh
src/mem/port.cc
src/mem/port.hh
src/mem/port_proxy.hh
src/mem/qport.hh
src/mem/ruby/system/RubyPort.cc
src/mem/ruby/system/RubyPort.hh
src/mem/se_translating_port_proxy.cc
src/mem/se_translating_port_proxy.hh
src/mem/tport.cc
src/mem/tport.hh
src/python/swig/pyobject.cc
src/sim/system.cc
src/sim/system.hh
src/sim/tlb.hh

index 8bffe68f8d6a00bf55b1a2c221cbf5ee2ac307d2..73a691cff30f8a70c612b0e7986df01d938ac43e 100644 (file)
@@ -91,13 +91,13 @@ TableWalker::resume()
     }
 }
 
-Port*
-TableWalker::getPort(const std::string &if_name, int idx)
+MasterPort&
+TableWalker::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name == "port") {
-        return &port;
+        return port;
     }
-    return NULL;
+    return MemObject::getMasterPort(if_name, idx);
 }
 
 Fault
index b5099bb27d4ab8917bd76b5a0385848579facb48..a6ff2585b1c1886b33170ebe3a15c62bfbf82b8b 100644 (file)
@@ -358,7 +358,8 @@ class TableWalker : public MemObject
 
     virtual unsigned int drain(Event *de);
     virtual void resume();
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort& getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
     Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode,
             TLB::Translation *_trans, bool timing, bool functional = false);
index 0b003e9fb06eb3d019b67b2f33c4ab7231c9e354..f9b2e6fe76072bac5a9bdbad4c774f8af4fba089 100644 (file)
@@ -722,10 +722,10 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc,
     return fault;
 }
 
-Port*
-TLB::getPort()
+MasterPort*
+TLB::getMasterPort()
 {
-    return tableWalker->getPort("port");
+    return &tableWalker->getMasterPort("port");
 }
 
 
index daf59f01d17b6ad60a65eef66cd41781679eddf8..a20957f6a4678b12b05df0c9bc35a17e1950af16 100644 (file)
@@ -214,8 +214,17 @@ class TLB : public BaseTLB
 
     void regStats();
 
-    // Get the port from the table walker and return it
-    virtual Port *getPort();
+    /**
+     * Get the table walker master port. This is used for migrating
+     * port connections during a CPU takeOverFrom() call. For
+     * architectures that do not have a table walker, NULL is
+     * returned, hence the use of a pointer rather than a
+     * reference. For ARM this method will always return a valid port
+     * pointer.
+     *
+     * @return A pointer to the walker master port
+     */
+    virtual MasterPort* getMasterPort();
 
     // Caching misc register values here.
     // Writing to misc registers needs to invalidate them.
index 6a9f07af2a5ee021a08ebc588c2f0e3e4c9758bf..a422a4758a0932ccaa059624db1600d0016d3bf9 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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) 2008 The Hewlett-Packard Development Company
  * All rights reserved.
  *
@@ -304,6 +316,9 @@ X86ISA::Interrupts::init()
     //
     BasicPioDevice::init();
     IntDev::init();
+
+    // the slave port has a range so inform the connected master
+    intSlavePort.sendRangeChange();
 }
 
 
@@ -554,7 +569,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
                 break;
             }
             pendingIPIs += apics.size();
-            intPort.sendMessage(apics, message, timing);
+            intMasterPort.sendMessage(apics, message, timing);
             newVal = regs[APIC_INTERRUPT_COMMAND_LOW];
         }
         break;
index abf3040bd4970efb1c3c2539582c4299bde19890..328e7159d15d9c2a297a91d73a3d9408d9e7dbf8 100644 (file)
@@ -189,7 +189,7 @@ class Interrupts : public BasicPioDevice, IntDev
     int initialApicId;
 
     // Port for receiving interrupts
-    IntPort intSlavePort;
+    IntSlavePort intSlavePort;
 
   public:
 
@@ -239,17 +239,20 @@ class Interrupts : public BasicPioDevice, IntDev
     AddrRangeList getAddrRanges();
     AddrRangeList getIntAddrRange();
 
-    Port *getPort(const std::string &if_name, int idx = -1)
+    MasterPort &getMasterPort(const std::string &if_name, int idx = -1)
     {
-        // a bit of an odd one since there is now two ports in the
-        // Python class we also need two ports even if they are
-        // identical
         if (if_name == "int_master") {
-            return &intPort;
-        } else if (if_name == "int_slave") {
-            return &intSlavePort;
+            return intMasterPort;
         }
-        return BasicPioDevice::getPort(if_name, idx);
+        return BasicPioDevice::getMasterPort(if_name, idx);
+    }
+
+    SlavePort &getSlavePort(const std::string &if_name, int idx = -1)
+    {
+        if (if_name == "int_slave") {
+            return intSlavePort;
+        }
+        return BasicPioDevice::getSlavePort(if_name, idx);
     }
 
     /*
index f29531cd5e6f1879c5a6c28d72d32e5ee0f4641f..87505f4df4e1ecb1ef0b5ee5622b3bde9e141751 100644 (file)
@@ -153,11 +153,6 @@ Walker::WalkerPort::recvFunctional(PacketPtr pkt)
     return;
 }
 
-void
-Walker::WalkerPort::recvRangeChange()
-{
-}
-
 void
 Walker::WalkerPort::recvRetry()
 {
@@ -182,13 +177,13 @@ bool Walker::sendTiming(WalkerState* sendingState, PacketPtr pkt)
     return port.sendTiming(pkt);
 }
 
-Port *
-Walker::getPort(const std::string &if_name, int idx)
+MasterPort &
+Walker::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name == "port")
-        return &port;
+        return port;
     else
-        panic("No page table walker port named %s!\n", if_name);
+        return MemObject::getMasterPort(if_name, idx);
 }
 
 void
index 90f07528060df3ff8bd03f322c75c42142c6d371..bf7a9e6150d8a06628ff459ba8594be38490fb9b 100644 (file)
@@ -60,11 +60,11 @@ namespace X86ISA
     {
       protected:
         // Port for accessing memory
-        class WalkerPort : public Port
+        class WalkerPort : public MasterPort
         {
           public:
             WalkerPort(const std::string &_name, Walker * _walker) :
-                  Port(_name, _walker), walker(_walker)
+                  MasterPort(_name, _walker), walker(_walker)
             {}
 
           protected:
@@ -73,9 +73,8 @@ namespace X86ISA
             bool recvTiming(PacketPtr pkt);
             Tick recvAtomic(PacketPtr pkt);
             void recvFunctional(PacketPtr pkt);
-            void recvRangeChange();
             void recvRetry();
-            bool isSnooping() { return true; }
+            bool isSnooping() const { return true; }
         };
 
         friend class WalkerPort;
@@ -166,7 +165,7 @@ namespace X86ISA
                 RequestPtr req, BaseTLB::Mode mode);
         Fault startFunctional(ThreadContext * _tc, Addr &addr,
                 Addr &pageSize, BaseTLB::Mode mode);
-        Port *getPort(const std::string &if_name, int idx = -1);
+        MasterPort &getMasterPort(const std::string &if_name, int idx = -1);
 
       protected:
         // The TLB we're supposed to load.
index 10ef217e1cea92548dc282049ed269321d6ff051..89561f8515c46955093207be81e2546df4a8515c 100644 (file)
@@ -428,10 +428,10 @@ TLB::unserialize(Checkpoint *cp, const std::string &section)
 {
 }
 
-Port *
-TLB::getPort()
+MasterPort *
+TLB::getMasterPort()
 {
-    return walker->getPort("port");
+    return &walker->getMasterPort("port");
 }
 
 } // namespace X86ISA
index 078b8b8d6de78f9f3a3bc08fc07010ed6667c09a..bcadda762ec6b163c531dc940e052c21078ca795 100644 (file)
@@ -125,7 +125,17 @@ namespace X86ISA
         virtual void serialize(std::ostream &os);
         virtual void unserialize(Checkpoint *cp, const std::string &section);
 
-        virtual Port * getPort();
+        /**
+         * Get the table walker master port. This is used for
+         * migrating port connections during a CPU takeOverFrom()
+         * call. For architectures that do not have a table walker,
+         * NULL is returned, hence the use of a pointer rather than a
+         * reference. For X86 this method will always return a valid
+         * port pointer.
+         *
+         * @return A pointer to the walker master port
+         */
+        virtual MasterPort *getMasterPort();
     };
 }
 
index 5d5f704db6b269dfbf7c3e6232e6e9417cbb9e61..d01dcbef3982dcd0346ad54eac74744a161eaa86 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 ARM Limited
+ * Copyright (c) 2011-2012 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -299,19 +299,19 @@ BaseCPU::regStats()
         threadContexts[0]->regStats(name());
 }
 
-Port *
-BaseCPU::getPort(const string &if_name, int idx)
+MasterPort &
+BaseCPU::getMasterPort(const string &if_name, int idx)
 {
     // Get the right port based on name. This applies to all the
     // subclasses of the base CPU and relies on their implementation
     // of getDataPort and getInstPort. In all cases there methods
     // return a CpuPort pointer.
     if (if_name == "dcache_port")
-        return &getDataPort();
+        return getDataPort();
     else if (if_name == "icache_port")
-        return &getInstPort();
+        return getInstPort();
     else
-        panic("CPU %s has no port named %s\n", name(), if_name);
+        return MemObject::getMasterPort(if_name, idx);
 }
 
 Tick
@@ -381,8 +381,6 @@ BaseCPU::switchOut()
 void
 BaseCPU::takeOverFrom(BaseCPU *oldCPU)
 {
-    CpuPort &ic = getInstPort();
-    CpuPort &dc = getDataPort();
     assert(threadContexts.size() == oldCPU->threadContexts.size());
 
     _cpuId = oldCPU->cpuId();
@@ -407,24 +405,21 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
             ThreadContext::compare(oldTC, newTC);
         */
 
-        Port  *old_itb_port, *old_dtb_port, *new_itb_port, *new_dtb_port;
-        old_itb_port = oldTC->getITBPtr()->getPort();
-        old_dtb_port = oldTC->getDTBPtr()->getPort();
-        new_itb_port = newTC->getITBPtr()->getPort();
-        new_dtb_port = newTC->getDTBPtr()->getPort();
+        MasterPort *old_itb_port = oldTC->getITBPtr()->getMasterPort();
+        MasterPort *old_dtb_port = oldTC->getDTBPtr()->getMasterPort();
+        MasterPort *new_itb_port = newTC->getITBPtr()->getMasterPort();
+        MasterPort *new_dtb_port = newTC->getDTBPtr()->getMasterPort();
 
         // Move over any table walker ports if they exist
         if (new_itb_port && !new_itb_port->isConnected()) {
             assert(old_itb_port);
-            Port *peer = old_itb_port->getPeer();;
-            new_itb_port->setPeer(peer);
-            peer->setPeer(new_itb_port);
+            SlavePort &slavePort = old_itb_port->getSlavePort();
+            new_itb_port->bind(slavePort);
         }
         if (new_dtb_port && !new_dtb_port->isConnected()) {
             assert(old_dtb_port);
-            Port *peer = old_dtb_port->getPeer();;
-            new_dtb_port->setPeer(peer);
-            peer->setPeer(new_dtb_port);
+            SlavePort &slavePort = old_dtb_port->getSlavePort();
+            new_dtb_port->bind(slavePort);
         }
 
         // Checker whether or not we have to transfer CheckerCPU
@@ -432,26 +427,25 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
         CheckerCPU *oldChecker = oldTC->getCheckerCpuPtr();
         CheckerCPU *newChecker = newTC->getCheckerCpuPtr();
         if (oldChecker && newChecker) {
-            Port *old_checker_itb_port, *old_checker_dtb_port;
-            Port *new_checker_itb_port, *new_checker_dtb_port;
-
-            old_checker_itb_port = oldChecker->getITBPtr()->getPort();
-            old_checker_dtb_port = oldChecker->getDTBPtr()->getPort();
-            new_checker_itb_port = newChecker->getITBPtr()->getPort();
-            new_checker_dtb_port = newChecker->getDTBPtr()->getPort();
+            MasterPort *old_checker_itb_port =
+                oldChecker->getITBPtr()->getMasterPort();
+            MasterPort *old_checker_dtb_port =
+                oldChecker->getDTBPtr()->getMasterPort();
+            MasterPort *new_checker_itb_port =
+                newChecker->getITBPtr()->getMasterPort();
+            MasterPort *new_checker_dtb_port =
+                newChecker->getDTBPtr()->getMasterPort();
 
             // Move over any table walker ports if they exist for checker
             if (new_checker_itb_port && !new_checker_itb_port->isConnected()) {
                 assert(old_checker_itb_port);
-                Port *peer = old_checker_itb_port->getPeer();;
-                new_checker_itb_port->setPeer(peer);
-                peer->setPeer(new_checker_itb_port);
+                SlavePort &slavePort = old_checker_itb_port->getSlavePort();;
+                new_checker_itb_port->bind(slavePort);
             }
             if (new_checker_dtb_port && !new_checker_dtb_port->isConnected()) {
                 assert(old_checker_dtb_port);
-                Port *peer = old_checker_dtb_port->getPeer();;
-                new_checker_dtb_port->setPeer(peer);
-                peer->setPeer(new_checker_dtb_port);
+                SlavePort &slavePort = old_checker_dtb_port->getSlavePort();;
+                new_checker_dtb_port->bind(slavePort);
             }
         }
     }
@@ -470,16 +464,12 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
     // 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.
-    if (!ic.isConnected()) {
-        Port *peer = oldCPU->getInstPort().getPeer();
-        ic.setPeer(peer);
-        peer->setPeer(&ic);
+    if (!getInstPort().isConnected()) {
+        getInstPort().bind(oldCPU->getInstPort().getSlavePort());
     }
 
-    if (!dc.isConnected()) {
-        Port *peer = oldCPU->getDataPort().getPeer();
-        dc.setPeer(peer);
-        peer->setPeer(&dc);
+    if (!getDataPort().isConnected()) {
+        getDataPort().bind(oldCPU->getDataPort().getSlavePort());
     }
 }
 
@@ -568,8 +558,3 @@ BaseCPU::CpuPort::recvFunctional(PacketPtr pkt)
     // long term this should never be called, but that assumed a split
     // into master/slave and request/response.
 }
-
-void
-BaseCPU::CpuPort::recvRangeChange()
-{
-}
index 149d26aa35190b5534d7698e3572d0d682110401..145b014aa6a6dd9173105c3b41106c0e5d5001e9 100644 (file)
@@ -117,7 +117,7 @@ class BaseCPU : public MemObject
      * both atomic and timing access is to panic and the corresponding
      * subclasses have to override these methods.
      */
-    class CpuPort : public Port
+    class CpuPort : public MasterPort
     {
       public:
 
@@ -128,7 +128,7 @@ class BaseCPU : public MemObject
          * @param _name structural owner of this port
          */
         CpuPort(const std::string& _name, MemObject* _owner) :
-            Port(_name, _owner)
+            MasterPort(_name, _owner)
         { }
 
       protected:
@@ -141,8 +141,6 @@ class BaseCPU : public MemObject
 
         void recvFunctional(PacketPtr pkt);
 
-        void recvRangeChange();
-
     };
 
   public:
@@ -172,11 +170,11 @@ class BaseCPU : public MemObject
     MasterID instMasterId() { return _instMasterId; }
 
     /**
-     * Get a port on this MemObject. This method is virtual to allow
+     * Get a master port on this MemObject. This method is virtual to allow
      * the subclasses of the BaseCPU to override it. All CPUs have a
      * data and instruction port, but the Atomic CPU (in its current
      * form) adds a port directly connected to the memory and has to
-     * override getPort.
+     * override getMasterPort.
      *
      * This method uses getDataPort and getInstPort to resolve the two
      * ports.
@@ -184,9 +182,10 @@ class BaseCPU : public MemObject
      * @param if_name the port name
      * @param idx ignored index
      *
-     * @return a pointer to the port with the given name
+     * @return a reference to the port with the given name
      */
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
 //    Tick currentTick;
     inline Tick frequency() const { return SimClock::Frequency / clock; }
index afc453f875155a53585cfb5145676d1b92523fda..d816578ae728cd09da3ff5137d552e9620143c76 100644 (file)
@@ -132,12 +132,6 @@ class CheckerCPU : public BaseCPU
         return *icachePort;
     }
 
-    virtual Port *getPort(const std::string &name, int idx)
-    {
-        panic("Not supported on checker!");
-        return NULL;
-    }
-
   public:
     // Primary thread being run.
     SimpleThread *thread;
index d9f98e42cc3af21d8db7f59c0de9bb798a8e7353..3f3ef12e62210ed97e72cd023ad8b4518f777e98 100644 (file)
@@ -139,7 +139,7 @@ class CacheUnit : public Resource
     
   protected:
     /** Cache interface. */
-    Port *cachePort;
+    MasterPort *cachePort;
 
     bool cachePortBlocked;
 
index 42e9f01f9e93928aba228a8af587bfaafbdc39dc..4937304587eb93ccc33144ec27798500bdf340d7 100644 (file)
@@ -186,8 +186,7 @@ class FullO3CPU : public BaseO3CPU
          *
          * @return true since we have to snoop
          */
-        virtual bool isSnooping()
-        { return true; }
+        virtual bool isSnooping() const { return true; }
     };
 
     class TickEvent : public Event
index 702606d399bd09526ec7c03627453409d5189f77..44898eb389b24ccc170d304fa2fbb68adb71694c 100644 (file)
@@ -90,7 +90,7 @@ class LSQUnit {
     void regStats();
 
     /** Sets the pointer to the dcache port. */
-    void setDcachePort(Port *dcache_port);
+    void setDcachePort(MasterPort *dcache_port);
 
     /** Switches out LSQ unit. */
     void switchOut();
@@ -268,7 +268,7 @@ class LSQUnit {
     LSQ *lsq;
 
     /** Pointer to the dcache port.  Used only for sending. */
-    Port *dcachePort;
+    MasterPort *dcachePort;
 
     /** Derived class to hold any sender state the LSQ needs. */
     class LSQSenderState : public Packet::SenderState, public FastAlloc
index d0a630f6d68f30cedcd503a74ff67f6344b41e93..2de349242a2efbc58097460a6753852d97397553 100644 (file)
@@ -239,7 +239,7 @@ LSQUnit<Impl>::regStats()
 
 template<class Impl>
 void
-LSQUnit<Impl>::setDcachePort(Port *dcache_port)
+LSQUnit<Impl>::setDcachePort(MasterPort *dcache_port)
 {
     dcachePort = dcache_port;
 }
index d50d8d7158ab2a6dc5c4d7bcd95e0e2825f56e2c..b4f37220c2859674c3e628cd7050e8f6076cc125 100644 (file)
@@ -36,9 +36,6 @@ class DerivOzoneCPU(BaseCPU):
 
     numThreads = Param.Unsigned("number of HW thread contexts")
 
-    icache_port = Port("Instruction Port")
-    dcache_port = Port("Data Port")
-
     width = Param.Unsigned("Width")
     frontEndWidth = Param.Unsigned("Front end width")
     frontEndLatency = Param.Unsigned("Front end latency")
index d2b90bff3ae7e8cba500bfefa3ea96b0aebd23c4..1bd2ee25b22661fd0dcc0fc38c83fb218686f3aa 100644 (file)
@@ -316,8 +316,6 @@ class OzoneCPU : public BaseCPU
     System *system;
     PhysicalMemory *physmem;
 
-    virtual Port *getPort(const std::string &name, int idx);
-
     FrontEnd *frontEnd;
 
     BackEnd *backEnd;
index b111d4425640c70751704766e27ce5a41bc268d0..3a32c07c65006543162068873c57e3a8da26cd73 100644 (file)
@@ -390,18 +390,6 @@ OzoneCPU<Impl>::init()
     thread.inSyscall = false;
 }
 
-template <class Impl>
-Port *
-OzoneCPU<Impl>::getPort(const std::string &if_name, int idx)
-{
-    if (if_name == "dcache_port")
-        return backEnd->getDcachePort();
-    else if (if_name == "icache_port")
-        return frontEnd->getIcachePort();
-    else
-        panic("No Such Port\n");
-}
-
 template <class Impl>
 void
 OzoneCPU<Impl>::serialize(std::ostream &os)
index 41b86aab8cfa379c160687f7e80ebef290048c4a..6c63bf8d9d56556f5057150a5b17e64aedb506dc 100644 (file)
@@ -68,7 +68,7 @@ class FrontEnd
     /** IcachePort class.  Handles doing the communication with the
      * cache/memory.
      */
-    class IcachePort : public Port
+    class IcachePort : public MasterPort
     {
       protected:
         /** Pointer to FE. */
@@ -87,9 +87,6 @@ class FrontEnd
         /** Functional version of receive.  Panics. */
         virtual void recvFunctional(PacketPtr pkt);
 
-        /** Receives range change. */
-        virtual void recvRangeChange();
-
         /** Timing version of receive.  Handles setting fetch to the
          * proper status to start fetching. */
         virtual bool recvTiming(PacketPtr pkt);
index 2c9c70872a118a32361703e640713232c143ab91..12aa0a32181a8874f30cc2ace547151bfcc3254d 100644 (file)
@@ -58,12 +58,6 @@ FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
     warn("FrontEnd doesn't update state from functional calls");
 }
 
-template<class Impl>
-void
-FrontEnd<Impl>::IcachePort::recvRangeChange()
-{
-}
-
 template<class Impl>
 bool
 FrontEnd<Impl>::IcachePort::recvTiming(PacketPtr pkt)
index 809725c0d072ec1b338b047c319b80942a212e24..a581b242f89b32e997adf49e9b0cfe3f0514ebe6 100644 (file)
@@ -240,7 +240,7 @@ class OzoneLWLSQ {
     /** Pointer to the back-end stage. */
     BackEnd *be;
 
-    class DcachePort : public Port
+    class DcachePort : public MasterPort
     {
       protected:
         OzoneLWLSQ *lsq;
@@ -255,13 +255,10 @@ class OzoneLWLSQ {
 
         virtual void recvFunctional(PacketPtr pkt);
 
-        virtual void recvRangeChange();
-
         /**
          * Is a snooper due to LSQ maintenance
          */
-        virtual bool isSnooping()
-        { return true; }
+        virtual bool isSnooping() const { return true; }
 
         virtual bool recvTiming(PacketPtr pkt);
 
index 82d0b4e8bc3442a2700acb131d3bfa0ac2b2b25a..c0c6d7276b2443e7c8e4cbc4c89ed4462b08edba 100644 (file)
@@ -74,12 +74,6 @@ OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
     warn("O3CPU doesn't update things on a recvFunctional");
 }
 
-template <class Impl>
-void
-OzoneLWLSQ<Impl>::DcachePort::recvRangeChange()
-{
-}
-
 template <class Impl>
 bool
 OzoneLWLSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
index e5b3bd67da15006f032fa4eebdabb5a42539086f..d7ad07a5ecdeee6119a8ed4ec2eeb822493d733d 100644 (file)
@@ -65,14 +65,14 @@ AtomicSimpleCPU::TickEvent::description() const
     return "AtomicSimpleCPU tick";
 }
 
-Port *
-AtomicSimpleCPU::getPort(const string &if_name, int idx)
+MasterPort &
+AtomicSimpleCPU::getMasterPort(const string &if_name, int idx)
 {
     if (if_name == "physmem_port") {
         hasPhysMemPort = true;
-        return &physmemPort;
+        return physmemPort;
     } else {
-        return BaseCPU::getPort(if_name, idx);
+        return BaseCPU::getMasterPort(if_name, idx);
     }
 }
 
@@ -94,7 +94,7 @@ AtomicSimpleCPU::init()
     }
 
     if (hasPhysMemPort) {
-        AddrRangeList pmAddrList = physmemPort.getPeer()->getAddrRanges();
+        AddrRangeList pmAddrList = physmemPort.getSlavePort().getAddrRanges();
         physMemAddr = *pmAddrList.begin();
     }
     // Atomic doesn't do MT right now, so contextId == threadId
index 8a1c9000fe5b4c5a74b4cf0edfdf93aec7a2d916..126cd376563c7d734cf6029b61c2dfa72d23ab20 100644 (file)
@@ -112,10 +112,11 @@ class AtomicSimpleCPU : public BaseSimpleCPU
   public:
 
     /**
-     * Override the getPort of the BaseCPU so that we can provide a pointer
-     * to the physmemPort, unique to the Atomic CPU.
+     * Override the getMasterPort of the BaseCPU so that we can
+     * provide the physmemPort, unique to the Atomic CPU.
      */
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
     virtual void serialize(std::ostream &os);
     virtual void unserialize(Checkpoint *cp, const std::string &section);
index 4518066ebcd84e16018a3f02577dec7eb64b73c3..bfdd28e0893ec44d401acd76e405c63c0f373123 100644 (file)
@@ -75,19 +75,19 @@ RubyDirectedTester::init()
     generator->setDirectedTester(this);
 }
 
-Port *
-RubyDirectedTester::getPort(const std::string &if_name, int idx)
+MasterPort &
+RubyDirectedTester::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name != "cpuPort") {
-        panic("RubyDirectedTester::getPort: unknown port %s requested",
-              if_name);
-    }
+        // pass it along to our super class
+        return MemObject::getMasterPort(if_name, idx);
+    } else {
+        if (idx >= static_cast<int>(ports.size())) {
+            panic("RubyDirectedTester::getMasterPort: unknown index %d\n", idx);
+        }
 
-    if (idx >= static_cast<int>(ports.size())) {
-        panic("RubyDirectedTester::getPort: unknown index %d requested\n", idx);
+        return *ports[idx];
     }
-
-    return ports[idx];
 }
 
 Tick
@@ -110,7 +110,7 @@ RubyDirectedTester::CpuPort::recvTiming(PacketPtr pkt)
     return true;
 }
 
-Port*
+MasterPort*
 RubyDirectedTester::getCpuPort(int idx)
 {
     assert(idx >= 0 && idx < ports.size());
index cd0632976357adedb85e26bc459a14e5cc37d948..cb207ff8078acf5818db30f1c2703bd2ee8feac5 100644 (file)
@@ -47,7 +47,7 @@ class DirectedGenerator;
 class RubyDirectedTester : public MemObject
 {
   public:
-    class CpuPort : public Port
+    class CpuPort : public MasterPort
     {
       private:
         RubyDirectedTester *tester;
@@ -55,25 +55,27 @@ class RubyDirectedTester : public MemObject
       public:
         CpuPort(const std::string &_name, RubyDirectedTester *_tester,
                 uint32_t _idx)
-            : Port(_name, _tester), tester(_tester), idx(_idx)
+            : MasterPort(_name, _tester), tester(_tester), idx(_idx)
         {}
 
         uint32_t idx;
 
       protected:
         virtual bool recvTiming(PacketPtr pkt);
+        virtual void recvRetry()
+        { panic("%s does not expect a retry\n", name()); }
         virtual Tick recvAtomic(PacketPtr pkt);
         virtual void recvFunctional(PacketPtr pkt) { }
-        virtual void recvRangeChange() { }
     };
 
     typedef RubyDirectedTesterParams Params;
     RubyDirectedTester(const Params *p);
     ~RubyDirectedTester();
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
-    Port* getCpuPort(int idx);
+    MasterPort* getCpuPort(int idx);
 
     virtual void init();
 
index dffaa71edf9678230fe3878cd067524489394ab2..07cdf73a6920a1a1df8da92a55ecbe025d90a683 100644 (file)
@@ -84,11 +84,6 @@ MemTest::CpuPort::recvFunctional(PacketPtr pkt)
     return;
 }
 
-void
-MemTest::CpuPort::recvRangeChange()
-{
-}
-
 void
 MemTest::CpuPort::recvRetry()
 {
@@ -161,15 +156,15 @@ MemTest::MemTest(const Params *p)
     dmaOutstanding = false;
 }
 
-Port *
-MemTest::getPort(const std::string &if_name, int idx)
+MasterPort &
+MemTest::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name == "functional")
-        return &funcPort;
+        return funcPort;
     else if (if_name == "test")
-        return &cachePort;
+        return cachePort;
     else
-        panic("No Such Port\n");
+        return MemObject::getMasterPort(if_name, idx);
 }
 
 void
index c56a37574866934600f21dba1235583816c8b8ca..d179fa5302ecf8271ec7ab9a4047a23a2d0e8544 100644 (file)
@@ -62,7 +62,8 @@ class MemTest : public MemObject
     // main simulation loop (one cycle)
     void tick();
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
     /**
      * Print state of address in memory system via PrintReq (for
@@ -84,14 +85,14 @@ class MemTest : public MemObject
 
     TickEvent tickEvent;
 
-    class CpuPort : public Port
+    class CpuPort : public MasterPort
     {
         MemTest *memtest;
 
       public:
 
         CpuPort(const std::string &_name, MemTest *_memtest)
-            : Port(_name, _memtest), memtest(_memtest)
+            : MasterPort(_name, _memtest), memtest(_memtest)
         { }
 
       protected:
@@ -102,8 +103,6 @@ class MemTest : public MemObject
 
         virtual void recvFunctional(PacketPtr pkt);
 
-        virtual void recvRangeChange();
-
         virtual void recvRetry();
     };
 
index 3fe153c4e2fdf8d903e14cf3b066f89d6bb8de65..01f2477070be4606ec7910853cf4ce07830d2ef7 100644 (file)
@@ -81,11 +81,6 @@ NetworkTest::CpuPort::recvFunctional(PacketPtr pkt)
     return;
 }
 
-void
-NetworkTest::CpuPort::recvRangeChange()
-{
-}
-
 void
 NetworkTest::CpuPort::recvRetry()
 {
@@ -126,13 +121,13 @@ NetworkTest::NetworkTest(const Params *p)
             name(), id);
 }
 
-Port *
-NetworkTest::getPort(const std::string &if_name, int idx)
+MasterPort &
+NetworkTest::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name == "test")
-        return &cachePort;
+        return cachePort;
     else
-        panic("No Such Port\n");
+        return MemObject::getMasterPort(if_name, idx);
 }
 
 void
index de67d41a055469a84cd8ebece85955a212333263..21984f45d05e10b71ba5469e9d379551e9964ba5 100644 (file)
@@ -57,7 +57,8 @@ class NetworkTest : public MemObject
     // main simulation loop (one cycle)
     void tick();
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
     /**
      * Print state of address in memory system via PrintReq (for
@@ -79,14 +80,14 @@ class NetworkTest : public MemObject
 
     TickEvent tickEvent;
 
-    class CpuPort : public Port
+    class CpuPort : public MasterPort
     {
         NetworkTest *networktest;
 
       public:
 
         CpuPort(const std::string &_name, NetworkTest *_networktest)
-            : Port(_name, _networktest), networktest(_networktest)
+            : MasterPort(_name, _networktest), networktest(_networktest)
         { }
 
       protected:
@@ -97,8 +98,6 @@ class NetworkTest : public MemObject
 
         virtual void recvFunctional(PacketPtr pkt);
 
-        virtual void recvRangeChange();
-
         virtual void recvRetry();
     };
 
index 70ee40aedf633469a36a277a58ba31ee3b0c740a..e1942cf6162b7bbe386e7a034843c2c7581dd789 100644 (file)
@@ -92,18 +92,19 @@ RubyTester::init()
     m_checkTable_ptr = new CheckTable(m_num_cpu_sequencers, this);
 }
 
-Port *
-RubyTester::getPort(const std::string &if_name, int idx)
+MasterPort &
+RubyTester::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name != "cpuPort") {
-        panic("RubyTester::getPort: unknown port %s requested\n", if_name);
-    }
+        // pass it along to our super class
+        return MemObject::getMasterPort(if_name, idx);
+    } else {
+        if (idx >= static_cast<int>(ports.size())) {
+            panic("RubyTester::getMasterPort: unknown index %d\n", idx);
+        }
 
-    if (idx >= static_cast<int>(ports.size())) {
-        panic("RubyTester::getPort: unknown index %d requested\n", idx);
+        return *ports[idx];
     }
-
-    return ports[idx];
 }
 
 Tick
@@ -135,7 +136,7 @@ RubyTester::CpuPort::recvTiming(PacketPtr pkt)
     return true;
 }
 
-Port*
+MasterPort*
 RubyTester::getCpuPort(int idx)
 {
     assert(idx >= 0 && idx < ports.size());
index e8cf4c87461ba2872fca1fea41dcef214a81e4bf..b24dddd836242b429ae84f9a4a8fcb91854ba813 100644 (file)
 class RubyTester : public MemObject
 {
   public:
-    class CpuPort : public Port
+    class CpuPort : public MasterPort
     {
       private:
         RubyTester *tester;
 
       public:
         CpuPort(const std::string &_name, RubyTester *_tester, int _idx)
-            : Port(_name, _tester), tester(_tester), idx(_idx)
+            : MasterPort(_name, _tester), tester(_tester), idx(_idx)
         {}
 
         int idx;
 
       protected:
         virtual bool recvTiming(PacketPtr pkt);
+        virtual void recvRetry()
+        { panic("%s does not expect a retry\n", name()); }
         virtual Tick recvAtomic(PacketPtr pkt);
         virtual void recvFunctional(PacketPtr pkt) { }
-        virtual void recvRangeChange() { }
     };
 
     struct SenderState : public Packet::SenderState
@@ -86,9 +87,10 @@ class RubyTester : public MemObject
     RubyTester(const Params *p);
     ~RubyTester();
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
-    Port* getCpuPort(int idx);
+    MasterPort* getCpuPort(int idx);
 
     virtual void init();
 
index 7b17a86a342cb55e0b35c099c3e6b5f681af5e88..809649718b19b3a325e6a578c6ae0c63643f1ee1 100644 (file)
@@ -110,21 +110,26 @@ CopyEngine::CopyEngineChannel::~CopyEngineChannel()
     delete [] copyBuffer;
 }
 
-Port *
-CopyEngine::getPort(const std::string &if_name, int idx)
+MasterPort &
+CopyEngine::getMasterPort(const std::string &if_name, int idx)
 {
-    if (if_name == "dma") {
-        if (idx < chan.size())
-            return chan[idx]->getPort();
+    if (if_name != "dma") {
+        // pass it along to our super class
+        return PciDev::getMasterPort(if_name, idx);
+    } else {
+        if (idx >= static_cast<int>(chan.size())) {
+            panic("CopyEngine::getMasterPort: unknown index %d\n", idx);
+        }
+
+        return chan[idx]->getMasterPort();
     }
-    return PciDev::getPort(if_name, idx);
 }
 
 
-Port *
-CopyEngine::CopyEngineChannel::getPort()
+MasterPort &
+CopyEngine::CopyEngineChannel::getMasterPort()
 {
-    return &cePort;
+    return cePort;
 }
 
 void
index aa0bf08967abcb062a9a7442f634c2f86566f92c..28fc6315c8f58887006f7d24d66da51ca4969b5a 100644 (file)
@@ -94,7 +94,7 @@ class CopyEngine : public PciDev
       public:
         CopyEngineChannel(CopyEngine *_ce, int cid);
         virtual ~CopyEngineChannel();
-        Port *getPort();
+        MasterPort &getMasterPort();
 
         std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); }
         virtual Tick read(PacketPtr pkt)
@@ -196,7 +196,8 @@ class CopyEngine : public PciDev
 
     void regStats();
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
     virtual Tick read(PacketPtr pkt);
     virtual Tick write(PacketPtr pkt);
index f7b8db09d3db751bc1ad2d544daaa0576bfa054f..2937c66b188974d48af45e80afd7e6c44a116190 100644 (file)
@@ -71,14 +71,13 @@ PioDevice::init()
     pioPort.sendRangeChange();
 }
 
-Port *
-PioDevice::getPort(const std::string &if_name, int idx)
+SlavePort &
+PioDevice::getSlavePort(const std::string &if_name, int idx)
 {
     if (if_name == "pio") {
-        return &pioPort;
+        return pioPort;
     }
-    panic("PioDevice %s has no port named %s\n", name(), if_name);
-    return NULL;
+    return MemObject::getSlavePort(if_name, idx);
 }
 
 unsigned int
@@ -111,7 +110,7 @@ BasicPioDevice::getAddrRanges()
 
 DmaPort::DmaPort(MemObject *dev, System *s, Tick min_backoff, Tick max_backoff,
                  bool recv_snoops)
-    : Port(dev->name() + "-dmaport", dev), device(dev), sys(s),
+    : MasterPort(dev->name() + "-dmaport", dev), device(dev), sys(s),
       masterId(s->getMasterId(dev->name())),
       pendingCount(0), actionInProgress(0), drainEvent(NULL),
       backoffTime(0), minBackoffDelay(min_backoff),
@@ -370,12 +369,12 @@ DmaDevice::~DmaDevice()
 }
 
 
-Port *
-DmaDevice::getPort(const std::string &if_name, int idx)
+MasterPort &
+DmaDevice::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name == "dma") {
-        return &dmaPort;
+        return dmaPort;
     }
-    return PioDevice::getPort(if_name, idx);
+    return PioDevice::getMasterPort(if_name, idx);
 }
 
index 400263957114ca64af53002cbf18bcbb7f0712c3..9bb2c3d87253bea7053c9e1a6a773c795f62995b 100644 (file)
@@ -69,7 +69,7 @@ class PioPort : public SimpleTimingPort
 };
 
 
-class DmaPort : public Port
+class DmaPort : public MasterPort
 {
   protected:
     struct DmaReqState : public Packet::SenderState, public FastAlloc
@@ -148,16 +148,9 @@ class DmaPort : public Port
         panic("dma port shouldn't be used for pio access.");
     }
 
-    virtual void recvRangeChange()
-    {
-        // DMA port is a master with a single slave so there is no choice and
-        // thus no need to worry about any address changes
-    }
-
     virtual void recvRetry() ;
 
-    virtual bool isSnooping()
-    { return recvSnoops; }
+    virtual bool isSnooping() const { return recvSnoops; }
 
     void queueDma(PacketPtr pkt, bool front = false);
     void sendDma();
@@ -231,7 +224,7 @@ class PioDevice : public MemObject
 
     virtual unsigned int drain(Event *de);
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1);
 
     friend class PioPort;
 
@@ -304,7 +297,8 @@ class DmaDevice : public PioDevice
 
     unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); }
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort &getMasterPort(const std::string &if_name,
+                                      int idx = -1);
 
     friend class DmaPort;
 };
index 07089fd0e208d8c91a617e67b087e67da80f80ce..43518834292c468d1feeb1cb8d8c7b24b511a625 100644 (file)
@@ -218,12 +218,12 @@ class PciDev : public DmaDevice
 
     virtual unsigned int drain(Event *de);
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1)
+    virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1)
     {
         if (if_name == "config") {
-            return &configPort;
+            return configPort;
         }
-        return DmaDevice::getPort(if_name, idx);
+        return DmaDevice::getSlavePort(if_name, idx);
     }
 
 };
index 3d7454dfd2eaf75324d4f967b3b6c2423f8ed56c..54824c778073ecf2d890e59fe752b34287e1c2e4 100644 (file)
@@ -222,8 +222,8 @@ X86ISA::I82094AA::signalInterrupt(int line)
                 apics.push_back(selected);
             }
         }
-        intPort.sendMessage(apics, message,
-                            sys->getMemoryMode() == Enums::timing);
+        intMasterPort.sendMessage(apics, message,
+                                  sys->getMemoryMode() == Enums::timing);
     }
 }
 
index f0837cc27fd190d7f3da1aa152ff693f09f491bf..d3eedea7bdc84f6afe98fe549cfd213a9729aa07 100644 (file)
@@ -121,11 +121,11 @@ class I82094AA : public PioDevice, public IntDev
     void writeReg(uint8_t offset, uint32_t value);
     uint32_t readReg(uint8_t offset);
 
-    Port *getPort(const std::string &if_name, int idx = -1)
+    MasterPort &getMasterPort(const std::string &if_name, int idx = -1)
     {
         if (if_name == "int_master")
-            return &intPort;
-        return PioDevice::getPort(if_name, idx);
+            return intMasterPort;
+        return PioDevice::getMasterPort(if_name, idx);
     }
 
     void signalInterrupt(int line);
index 0d038b93d023b7821a73130914d7e48e26b353a6..8580ae9439e2f6dca55a23f8ea7cdcd7c878f225 100644 (file)
@@ -43,8 +43,9 @@
 #include "dev/x86/intdev.hh"
 
 void
-X86ISA::IntDev::IntPort::sendMessage(ApicList apics, TriggerIntMessage message,
-                                     bool timing)
+X86ISA::IntDev::IntMasterPort::sendMessage(ApicList apics,
+                                           TriggerIntMessage message,
+                                           bool timing)
 {
     ApicList::iterator apicIt;
     for (apicIt = apics.begin(); apicIt != apics.end(); apicIt++) {
@@ -67,10 +68,9 @@ X86ISA::IntDev::IntPort::sendMessage(ApicList apics, TriggerIntMessage message,
 void
 X86ISA::IntDev::init()
 {
-    if (!intPort.isConnected()) {
+    if (!intMasterPort.isConnected()) {
         panic("Int port not connected to anything!");
     }
-    intPort.sendRangeChange();
 }
 
 X86ISA::IntSourcePin *
index 5549df63790abecc61b6e2247093f28ba2f19525..bbdd98b24f94b40b4ae15dbaf1e0de162933334d 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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) 2008 The Regents of The University of Michigan
  * All rights reserved.
  *
@@ -51,15 +63,14 @@ typedef std::list<int> ApicList;
 class IntDev
 {
   protected:
-    class IntPort : public MessagePort
+    class IntSlavePort : public MessageSlavePort
     {
         IntDev * device;
         Tick latency;
-        Addr intAddr;
       public:
-        IntPort(const std::string &_name, MemObject * _parent,
-                IntDev *dev, Tick _latency) :
-            MessagePort(_name, _parent), device(dev), latency(_latency)
+        IntSlavePort(const std::string& _name, MemObject* _parent,
+                     IntDev* dev, Tick _latency) :
+            MessageSlavePort(_name, _parent), device(dev), latency(_latency)
         {
         }
 
@@ -72,6 +83,18 @@ class IntDev
         {
             return device->recvMessage(pkt);
         }
+    };
+
+    class IntMasterPort : public MessageMasterPort
+    {
+        IntDev* device;
+        Tick latency;
+      public:
+        IntMasterPort(const std::string& _name, MemObject* _parent,
+                      IntDev* dev, Tick _latency) :
+            MessageMasterPort(_name, _parent), device(dev), latency(_latency)
+        {
+        }
 
         Tick recvResponse(PacketPtr pkt)
         {
@@ -84,11 +107,11 @@ class IntDev
                 TriggerIntMessage message, bool timing);
     };
 
-    IntPort intPort;
+    IntMasterPort intMasterPort;
 
   public:
     IntDev(MemObject * parent, Tick latency = 0) :
-        intPort(parent->name() + ".int_master", parent, this, latency)
+        intMasterPort(parent->name() + ".int_master", parent, this, latency)
     {
     }
 
index 3576651840e2bdbe08128d7ee8c8a43f236c1b9e..89f2990b9a2502f47d4a39658ada64c1d82e3dca 100644 (file)
@@ -60,9 +60,9 @@ BadAddrEvent::process(ThreadContext *tc)
     AddrRangeIter iter;
     bool found = false;
 
-    Port &dataPort = tc->getCpuPtr()->getDataPort();
+    MasterPort &dataPort = tc->getCpuPtr()->getDataPort();
 
-    AddrRangeList resp = dataPort.getPeer()->getAddrRanges();
+    AddrRangeList resp = dataPort.getSlavePort().getAddrRanges();
     for (iter = resp.begin(); iter != resp.end(); iter++) {
         if (*iter == (K0Seg2Phys(a0) & PAddrImplMask))
             found = true;
index 0733b6ea810f493cae5f9c82cafc8265e5fa56c2..ebb37e79202475a9cd476c2eb70f6f353283ee6e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 ARM Limited
+ * Copyright (c) 2011-2012 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -59,7 +59,7 @@ Bridge::BridgeSlavePort::BridgeSlavePort(const std::string &_name,
                                          int _delay, int _nack_delay,
                                          int _resp_limit,
                                          std::vector<Range<Addr> > _ranges)
-    : Port(_name, _bridge), bridge(_bridge), masterPort(_masterPort),
+    : SlavePort(_name, _bridge), bridge(_bridge), masterPort(_masterPort),
       delay(_delay), nackDelay(_nack_delay),
       ranges(_ranges.begin(), _ranges.end()),
       outstandingResponses(0), inRetry(false),
@@ -71,7 +71,7 @@ Bridge::BridgeMasterPort::BridgeMasterPort(const std::string &_name,
                                            Bridge* _bridge,
                                            BridgeSlavePort& _slavePort,
                                            int _delay, int _req_limit)
-    : Port(_name, _bridge), bridge(_bridge), slavePort(_slavePort),
+    : MasterPort(_name, _bridge), bridge(_bridge), slavePort(_slavePort),
       delay(_delay), inRetry(false), reqQueueLimit(_req_limit),
       sendEvent(*this)
 {
@@ -88,19 +88,25 @@ Bridge::Bridge(Params *p)
         panic("No support for acknowledging writes\n");
 }
 
-Port*
-Bridge::getPort(const std::string &if_name, int idx)
+MasterPort&
+Bridge::getMasterPort(const std::string &if_name, int idx)
 {
-    if (if_name == "slave")
-        return &slavePort;
-    else if (if_name == "master")
-        return &masterPort;
-    else {
-        panic("Bridge %s has no port named %s\n", name(), if_name);
-        return NULL;
-    }
+    if (if_name == "master")
+        return masterPort;
+    else
+        // pass it along to our super class
+        return MemObject::getMasterPort(if_name, idx);
 }
 
+SlavePort&
+Bridge::getSlavePort(const std::string &if_name, int idx)
+{
+    if (if_name == "slave")
+        return slavePort;
+    else
+        // pass it along to our super class
+        return MemObject::getSlavePort(if_name, idx);
+}
 
 void
 Bridge::init()
@@ -473,19 +479,6 @@ Bridge::BridgeMasterPort::checkFunctional(PacketPtr pkt)
     return found;
 }
 
-/** Function called by the port when the bridge is receiving a range change.*/
-void
-Bridge::BridgeMasterPort::recvRangeChange()
-{
-    // no need to forward as the bridge has a fixed set of ranges
-}
-
-void
-Bridge::BridgeSlavePort::recvRangeChange()
-{
-    // is a slave port so do nothing
-}
-
 AddrRangeList
 Bridge::BridgeSlavePort::getAddrRanges()
 {
index 3e00405149e6679d7f7121b3b1ce0417ce5db317..e7dbc0a288a9076b34404cd73b788438c8045f82 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 ARM Limited
+ * Copyright (c) 2011-2012 ARM Limited
  * All rights reserved
  *
  * The license below extends only to copyright in the software and shall
@@ -122,7 +122,7 @@ class Bridge : public MemObject
      * is responsible for. The slave port also has a buffer for the
      * responses not yet sent.
      */
-    class BridgeSlavePort : public Port
+    class BridgeSlavePort : public SlavePort
     {
 
       private:
@@ -244,11 +244,6 @@ class Bridge : public MemObject
             pass it to the bridge. */
         virtual void recvFunctional(PacketPtr pkt);
 
-        /**
-         * When receiving a range change on the slave side do nothing.
-         */
-        virtual void recvRangeChange();
-
         /** When receiving a address range request the peer port,
             pass it to the bridge. */
         virtual AddrRangeList getAddrRanges();
@@ -260,7 +255,7 @@ class Bridge : public MemObject
      * responses. The master port has a buffer for the requests not
      * yet sent.
      */
-    class BridgeMasterPort : public Port
+    class BridgeMasterPort : public MasterPort
     {
 
       private:
@@ -371,11 +366,6 @@ class Bridge : public MemObject
         /** When receiving a Functional request from the peer port,
             pass it to the bridge. */
         virtual void recvFunctional(PacketPtr pkt);
-
-        /**
-         * When receiving a range change, pass it through the bridge.
-         */
-        virtual void recvRangeChange();
     };
 
     /** Slave port of the bridge. */
@@ -396,8 +386,9 @@ class Bridge : public MemObject
   public:
     const Params *params() const { return _params; }
 
-    /** A function used to return the port associated with this bus object. */
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort& getMasterPort(const std::string& if_name,
+                                      int idx = -1);
+    virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
 
     virtual void init();
 
index 0c0e3c3e288c77ac276ea9e19036f3836dfcfae8..c89455f02ca39079f85f0fc4a52f32dc8f11327f 100644 (file)
@@ -39,6 +39,7 @@
  *
  * Authors: Ali Saidi
  *          Andreas Hansson
+ *          William Wang
  */
 
 /**
@@ -72,12 +73,14 @@ Bus::Bus(const BusParams *p)
     // create the ports based on the size of the master and slave
     // vector ports, and the presence of the default master
 
-    // id used to index into interfaces which is a flat vector of all
-    // ports
+    // id used to index into master and slave ports, that currently
+    // has holes to be able to use the id to index into either
     int id = 0;
     for (int i = 0; i < p->port_master_connection_count; ++i) {
         std::string portName = csprintf("%s-p%d", name(), id);
-        interfaces.push_back(new BusPort(portName, this, id));
+        BusMasterPort* bp = new BusMasterPort(portName, this, id);
+        masterPorts.push_back(bp);
+        slavePorts.push_back(NULL);
         ++id;
     }
 
@@ -86,7 +89,9 @@ Bus::Bus(const BusParams *p)
     if (p->port_default_connection_count) {
         defaultPortId = id;
         std::string portName = csprintf("%s-default", name());
-        interfaces.push_back(new BusPort(portName, this, id));
+        BusMasterPort* bp = new BusMasterPort(portName, this, id);
+        masterPorts.push_back(bp);
+        slavePorts.push_back(NULL);
         ++id;
         // this is an additional master port
         ++nbrMasterPorts;
@@ -96,44 +101,55 @@ Bus::Bus(const BusParams *p)
     // nbrMasterPorts in the vector
     for (int i = 0; i < p->port_slave_connection_count; ++i) {
         std::string portName = csprintf("%s-p%d", name(), id);
-        interfaces.push_back(new BusPort(portName, this, id));
+        BusSlavePort* bp = new BusSlavePort(portName, this, id);
+        masterPorts.push_back(NULL);
+        slavePorts.push_back(bp);
         ++id;
     }
 
     clearPortCache();
 }
 
-Port *
-Bus::getPort(const std::string &if_name, int idx)
+MasterPort &
+Bus::getMasterPort(const std::string &if_name, int idx)
 {
     if (if_name == "master") {
         // the master index translates directly to the interfaces
         // vector as they are stored first
-        return interfaces[idx];
-    } else if (if_name == "slave") {
-        // the slaves are stored after the masters and we must thus
-        // offset the slave index with the number of master ports
-        return interfaces[nbrMasterPorts + idx];
+        return *masterPorts[idx];
     } else  if (if_name == "default") {
-        return interfaces[defaultPortId];
+        return *masterPorts[defaultPortId];
     } else {
-        panic("No port %s %d on bus %s\n", if_name, idx, name());
+        return MemObject::getMasterPort(if_name, idx);
+    }
+}
+
+SlavePort &
+Bus::getSlavePort(const std::string &if_name, int idx)
+{
+    if (if_name == "slave") {
+        return *slavePorts[nbrMasterPorts + idx];
+    } else {
+        return MemObject::getSlavePort(if_name, idx);
     }
 }
 
 void
 Bus::init()
 {
-    std::vector<BusPort*>::iterator intIter;
+    std::vector<BusSlavePort*>::iterator intIter;
 
     // iterate over our interfaces and determine which of our neighbours
     // are snooping and add them as snoopers
-    for (intIter = interfaces.begin(); intIter != interfaces.end();
+    for (intIter = slavePorts.begin(); intIter != slavePorts.end();
          intIter++) {
-        if ((*intIter)->getPeer()->isSnooping()) {
-            DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n",
-                    (*intIter)->getPeer()->name());
-            snoopPorts.push_back(*intIter);
+        // since there are holes in the vector, check for NULL
+        if (*intIter != NULL) {
+            if ((*intIter)->getMasterPort().isSnooping()) {
+                DPRINTF(BusAddrRanges, "Adding snooping neighbour %s\n",
+                        (*intIter)->getMasterPort().name());
+                snoopPorts.push_back(*intIter);
+            }
         }
     }
 }
@@ -194,7 +210,9 @@ Bus::recvTiming(PacketPtr pkt)
     // get the source id and port
     Packet::NodeID src_id = pkt->getSrc();
 
-    BusPort *src_port = interfaces[src_id];
+    // determine the source port based on the id
+    Port *src_port = slavePorts[src_id] ?
+        (Port*) slavePorts[src_id] : (Port*) masterPorts[src_id];
 
     // If the bus is busy, or other devices are in line ahead of the current
     // one, put this device on the retry list.
@@ -218,14 +236,14 @@ Bus::recvTiming(PacketPtr pkt)
     int dest_id;
     Port *dest_port;
 
-    if (dest == Packet::Broadcast) {
+    if (pkt->isRequest()) {
         // the packet is a memory-mapped request and should be broadcasted to
         // our snoopers
-        assert(pkt->isRequest());
+        assert(dest == Packet::Broadcast);
 
         SnoopIter s_end = snoopPorts.end();
         for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
-            BusPort *p = *s_iter;
+            BusSlavePort *p = *s_iter;
             // we got this request from a snooping master
             // (corresponding to our own slave port that is also in
             // snoopPorts) and should not send it back to where it
@@ -241,16 +259,28 @@ Bus::recvTiming(PacketPtr pkt)
         // determine the destination based on the address and forward
         // through the corresponding master port
         dest_id = findPort(pkt->getAddr());
-        dest_port = interfaces[dest_id];
+        dest_port = masterPorts[dest_id];
     } else {
         // the packet is a response, and it should always go back to
         // the port determined by the destination field
         dest_id = dest;
         assert(dest_id != src_id); // catch infinite loops
-        assert(dest_id < interfaces.size());
-        dest_port = interfaces[dest_id];
+        dest_port = slavePorts[dest_id] ?
+            (Port*) slavePorts[dest_id] : (Port*) masterPorts[dest_id];
+
+            // a normal response from the memory system (i.e. from a
+            // connected slave) should always go back to the master
+            // that issued it through one of our slave ports, however
+            // if this is a snoop response it could go either way, for
+            // example, it could be coming from a slave port
+            // connecting an L1 with a coherent master and another L1
+            // coherent master (one of our slave ports), or coming
+            // from the L1 and going to the L2 slave port (through one
+            // of our master ports)
     }
 
+    assert(dest_port != NULL);
+
     // if this is a snoop from a slave (corresponding to our own
     // master), i.e. the memory side of the bus, then do not send it
     // back to where it came from
@@ -318,8 +348,6 @@ Bus::retryWaiting()
 
     // send a retry to the port at the head of the retry list
     inRetry = true;
-    DPRINTF(Bus, "Sending a retry to %s\n",
-            retryList.front()->getPeer()->name());
 
     // note that we might have blocked on the receiving port being
     // busy (rather than the bus itself) and now call retry before the
@@ -427,7 +455,7 @@ Bus::recvAtomic(PacketPtr pkt)
 
     SnoopIter s_end = snoopPorts.end();
     for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
-        BusPort *p = *s_iter;
+        BusSlavePort *p = *s_iter;
         // we could have gotten this request from a snooping master
         // (corresponding to our own slave port that is also in
         // snoopPorts) and should not send it back to where it came
@@ -464,7 +492,7 @@ Bus::recvAtomic(PacketPtr pkt)
     // master), i.e. the memory side of the bus, then do not send it
     // back to where it came from
     if (dest_id != src_id) {
-        response_latency = interfaces[dest_id]->sendAtomic(pkt);
+        response_latency = masterPorts[dest_id]->sendAtomic(pkt);
     }
 
     // if we got a response from a snooper, restore it here
@@ -504,7 +532,7 @@ Bus::recvFunctional(PacketPtr pkt)
 
     SnoopIter s_end = snoopPorts.end();
     for (SnoopIter s_iter = snoopPorts.begin(); s_iter != s_end; s_iter++) {
-        BusPort *p = *s_iter;
+        BusSlavePort *p = *s_iter;
         // we could have gotten this request from a snooping master
         // (corresponding to our own slave port that is also in
         // snoopPorts) and should not send it back to where it came
@@ -528,7 +556,7 @@ Bus::recvFunctional(PacketPtr pkt)
         // master), i.e. the memory side of the bus, then do not send
         // it back to where it came from,
         if (dest_id != src_id) {
-            interfaces[dest_id]->sendFunctional(pkt);
+            masterPorts[dest_id]->sendFunctional(pkt);
         }
     }
 }
@@ -551,7 +579,8 @@ Bus::recvRangeChange(int id)
         defaultRange.clear();
         // Only try to update these ranges if the user set a default responder.
         if (useDefaultRange) {
-            AddrRangeList ranges = interfaces[id]->getPeer()->getAddrRanges();
+            AddrRangeList ranges =
+                masterPorts[id]->getSlavePort().getAddrRanges();
             for(iter = ranges.begin(); iter != ranges.end(); iter++) {
                 defaultRange.push_back(*iter);
                 DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for default range\n",
@@ -560,8 +589,8 @@ Bus::recvRangeChange(int id)
         }
     } else {
 
-        assert(id < interfaces.size() && id >= 0);
-        BusPort *port = interfaces[id];
+        assert(id < masterPorts.size() && id >= 0);
+        BusMasterPort *port = masterPorts[id];
 
         // Clean out any previously existent ids
         for (PortIter portIter = portMap.begin();
@@ -572,7 +601,7 @@ Bus::recvRangeChange(int id)
                 portIter++;
         }
 
-        ranges = port->getPeer()->getAddrRanges();
+        ranges = port->getSlavePort().getAddrRanges();
 
         for (iter = ranges.begin(); iter != ranges.end(); iter++) {
             DPRINTF(BusAddrRanges, "Adding range %#llx - %#llx for id %d\n",
@@ -580,8 +609,8 @@ Bus::recvRangeChange(int id)
             if (portMap.insert(*iter, id) == portMap.end()) {
                 int conflict_id = portMap.find(*iter)->second;
                 fatal("%s has two ports with same range:\n\t%s\n\t%s\n",
-                      name(), interfaces[id]->getPeer()->name(),
-                      interfaces[conflict_id]->getPeer()->name());
+                      name(), masterPorts[id]->getSlavePort().name(),
+                      masterPorts[conflict_id]->getSlavePort().name());
             }
         }
     }
@@ -589,10 +618,10 @@ Bus::recvRangeChange(int id)
 
     // tell all our peers that our address range has changed.
     // Don't tell the device that caused this change, it already knows
-    std::vector<BusPort*>::const_iterator intIter;
+    std::vector<BusSlavePort*>::const_iterator intIter;
 
-    for (intIter = interfaces.begin(); intIter != interfaces.end(); intIter++)
-        if ((*intIter)->getId() != id)
+    for (intIter = slavePorts.begin(); intIter != slavePorts.end(); intIter++)
+        if (*intIter != NULL && (*intIter)->getId() != id)
             (*intIter)->sendRangeChange();
 
     inRecvRangeChange.erase(id);
@@ -640,7 +669,7 @@ Bus::getAddrRanges(int id)
 }
 
 bool
-Bus::isSnooping(int id)
+Bus::isSnooping(int id) const
 {
     // in essence, answer the question if there are snooping ports
     return !snoopPorts.empty();
@@ -656,7 +685,7 @@ Bus::findBlockSize(int id)
 
     PortIter p_end = portMap.end();
     for (PortIter p_iter = portMap.begin(); p_iter != p_end; p_iter++) {
-        unsigned tmp_bs = interfaces[p_iter->second]->peerBlockSize();
+        unsigned tmp_bs = masterPorts[p_iter->second]->peerBlockSize();
         if (tmp_bs > max_bs)
             max_bs = tmp_bs;
     }
index 4ea92308a64debdf7d566a054441bf2fc93c20a9..e79e9df9eb5cc173c09eab8181209a0cfc304525 100644 (file)
@@ -40,6 +40,7 @@
  * Authors: Ron Dreslinski
  *          Ali Saidi
  *          Andreas Hansson
+ *          William Wang
  */
 
 /**
 
 class Bus : public MemObject
 {
-    /** Declaration of the buses port type, one will be instantiated for each
-        of the interfaces connecting to the bus. */
-    class BusPort : public Port
+    /**
+     * Declaration of the bus slave port type, one will be
+     * instantiated for each of the master interfaces connecting to
+     * the bus.
+     */
+    class BusSlavePort : public SlavePort
+    {
+      private:
+        /** A pointer to the bus to which this port belongs. */
+        Bus *bus;
+
+        /** A id to keep track of the interface ID of this port. */
+        int id;
+
+      public:
+
+        /** Constructor for the BusSlavePort.*/
+        BusSlavePort(const std::string &_name, Bus *_bus, int _id)
+            : SlavePort(_name, _bus), bus(_bus), id(_id)
+        { }
+
+        int getId() const { return id; }
+
+      protected:
+
+        /** When reciving a timing request from the peer port (at id),
+            pass it to the bus. */
+        virtual bool recvTiming(PacketPtr pkt)
+        { pkt->setSrc(id); return bus->recvTiming(pkt); }
+
+        /** When reciving a Atomic requestfrom the peer port (at id),
+            pass it to the bus. */
+        virtual Tick recvAtomic(PacketPtr pkt)
+        { pkt->setSrc(id); return bus->recvAtomic(pkt); }
+
+        /** When reciving a Functional requestfrom the peer port (at id),
+            pass it to the bus. */
+        virtual void recvFunctional(PacketPtr pkt)
+        { pkt->setSrc(id); bus->recvFunctional(pkt); }
+
+        /** When reciving a retry from the peer port (at id),
+            pass it to the bus. */
+        virtual void recvRetry()
+        { bus->recvRetry(id); }
+
+        // This should return all the 'owned' addresses that are
+        // downstream from this bus, yes?  That is, the union of all
+        // the 'owned' address ranges of all the other interfaces on
+        // this bus...
+        virtual AddrRangeList getAddrRanges()
+        { return bus->getAddrRanges(id); }
+
+        // Ask the bus to ask everyone on the bus what their block size is and
+        // take the max of it. This might need to be changed a bit if we ever
+        // support multiple block sizes.
+        virtual unsigned deviceBlockSize() const
+        { return bus->findBlockSize(id); }
+
+    };
+
+    /**
+     * Declaration of the bus master port type, one will be
+     * instantiated for each of the slave interfaces connecting to the
+     * bus.
+     */
+    class BusMasterPort : public MasterPort
     {
+      private:
         /** A pointer to the bus to which this port belongs. */
         Bus *bus;
 
-        /** A id to keep track of the intercafe ID this port is connected to. */
+        /** A id to keep track of the interface ID of this port. */
         int id;
 
       public:
 
-        /** Constructor for the BusPort.*/
-        BusPort(const std::string &_name, Bus *_bus, int _id)
-            : Port(_name, _bus), bus(_bus), id(_id)
+        /** Constructor for the BusMasterPort.*/
+        BusMasterPort(const std::string &_name, Bus *_bus, int _id)
+            : MasterPort(_name, _bus), bus(_bus), id(_id)
         { }
 
         int getId() const { return id; }
@@ -90,7 +155,7 @@ class Bus : public MemObject
          *
          * @return a boolean that is true if this port is snooping
          */
-        virtual bool isSnooping()
+        virtual bool isSnooping() const
         { return bus->isSnooping(id); }
 
       protected:
@@ -120,13 +185,6 @@ class Bus : public MemObject
         virtual void recvRetry()
         { bus->recvRetry(id); }
 
-        // This should return all the 'owned' addresses that are
-        // downstream from this bus, yes?  That is, the union of all
-        // the 'owned' address ranges of all the other interfaces on
-        // this bus...
-        virtual AddrRangeList getAddrRanges()
-        { return bus->getAddrRanges(id); }
-
         // Ask the bus to ask everyone on the bus what their block size is and
         // take the max of it. This might need to be changed a bit if we ever
         // support multiple block sizes.
@@ -151,8 +209,8 @@ class Bus : public MemObject
 
     AddrRangeList defaultRange;
 
-    typedef std::vector<BusPort*>::iterator SnoopIter;
-    std::vector<BusPort*> snoopPorts;
+    typedef std::vector<BusSlavePort*>::iterator SnoopIter;
+    std::vector<BusSlavePort*> snoopPorts;
 
     /** Function called by the port when the bus is recieving a Timing
       transaction.*/
@@ -250,7 +308,7 @@ class Bus : public MemObject
      *
      * @return a boolean indicating if this port is snooping or not
      */
-    bool isSnooping(int id);
+    bool isSnooping(int id) const;
 
     /** Calculate the timing parameters for the packet.  Updates the
      * firstWordTime and finishTime fields of the packet object.
@@ -292,9 +350,9 @@ class Bus : public MemObject
     // interfaces vector
     unsigned int nbrMasterPorts;
 
-    /** An ordered vector of pointers to the peer port interfaces
-        connected to this bus.*/
-    std::vector<BusPort*> interfaces;
+    /** The master and slave ports of the bus */
+    std::vector<BusSlavePort*> slavePorts;
+    std::vector<BusMasterPort*> masterPorts;
 
     /** An array of pointers to ports that retry should be called on because the
      * original send failed for whatever reason.*/
@@ -338,7 +396,8 @@ class Bus : public MemObject
   public:
 
     /** A function used to return the port associated with this bus object. */
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1);
+    virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
 
     virtual void init();
     virtual void startup();
index a2cb59a768c8cb2f5cca83aaef0684c25364ccf4..4ae6376dbdf0bfd252ee09bfa1740fa464d0fcfb 100644 (file)
@@ -57,7 +57,7 @@ using namespace std;
 BaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
                                           BaseCache *_cache,
                                           const std::string &_label)
-    : QueuedPort(_name, _cache, queue), queue(*_cache, *this, _label),
+    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
       blocked(false), mustSendRetry(false), sendRetryEvent(this)
 {
 }
@@ -99,7 +99,7 @@ BaseCache::CacheSlavePort::clearBlocked()
         DPRINTF(CachePort, "Cache port %s sending retry\n", name());
         mustSendRetry = false;
         // @TODO: need to find a better time (next bus cycle?)
-        owner->schedule(sendRetryEvent, curTick() + 1);
+        owner.schedule(sendRetryEvent, curTick() + 1);
     }
 }
 
@@ -108,10 +108,29 @@ void
 BaseCache::init()
 {
     if (!cpuSidePort->isConnected() || !memSidePort->isConnected())
-        panic("Cache %s not hooked up on both sides\n", name());
+        fatal("Cache ports on %s are not connected\n", name());
     cpuSidePort->sendRangeChange();
 }
 
+MasterPort &
+BaseCache::getMasterPort(const std::string &if_name, int idx)
+{
+    if (if_name == "mem_side") {
+        return *memSidePort;
+    }  else {
+        return MemObject::getMasterPort(if_name, idx);
+    }
+}
+
+SlavePort &
+BaseCache::getSlavePort(const std::string &if_name, int idx)
+{
+    if (if_name == "cpu_side") {
+        return *cpuSidePort;
+    } else {
+        return MemObject::getSlavePort(if_name, idx);
+    }
+}
 
 void
 BaseCache::regStats()
index c13d27d42bc0b34acc95d24f3ddaece6bec0d1c6..47cbaf7a0c0fc3dbf3700799e5ceb4beb281f5f0 100644 (file)
@@ -118,7 +118,7 @@ class BaseCache : public MemObject
      * and the sendDeferredPacket of the timing port is modified to
      * consider both the transmit list and the requests from the MSHR.
      */
-    class CacheMasterPort : public QueuedPort
+    class CacheMasterPort : public QueuedMasterPort
     {
 
       public:
@@ -149,7 +149,7 @@ class BaseCache : public MemObject
 
         CacheMasterPort(const std::string &_name, BaseCache *_cache,
                         PacketQueue &_queue) :
-            QueuedPort(_name, _cache, _queue)
+            QueuedMasterPort(_name, _cache, _queue)
         { }
 
         /**
@@ -157,7 +157,7 @@ class BaseCache : public MemObject
          *
          * @return always true
          */
-        virtual bool isSnooping() { return true; }
+        virtual bool isSnooping() const { return true; }
     };
 
     /**
@@ -168,7 +168,7 @@ class BaseCache : public MemObject
      * incoming requests. If blocked, the port will issue a retry once
      * unblocked.
      */
-    class CacheSlavePort : public QueuedPort
+    class CacheSlavePort : public QueuedSlavePort
     {
 
       public:
@@ -444,6 +444,9 @@ class BaseCache : public MemObject
 
     virtual void init();
 
+    virtual MasterPort &getMasterPort(const std::string &if_name, int idx = -1);
+    virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1);
+
     /**
      * Query block size of a cache.
      * @return  The block size
index cc206b7848ecaca6d98846d04c0af4a10b51d153..ca8c378fb9ef9688d4a47848338049bbb8bcd986 100644 (file)
@@ -40,7 +40,6 @@
 #include "mem/cache/base.hh"
 #include "mem/cache/cache.hh"
 #include "mem/config/cache.hh"
-#include "mem/bus.hh"
 #include "params/BaseCache.hh"
 
 // Tag Templates
index 782749aabe719825b1c5dc5183a8239e664ab82a..e745529a75f4bb0f82a846e74b97fcbf49b1872a 100644 (file)
@@ -249,8 +249,6 @@ class Cache : public BaseCache
     /** Instantiates a basic cache object. */
     Cache(const Params *p, TagStore *tags);
 
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
-
     void regStats();
 
     /**
index 2463071de689c937e45205581e27706bb272b7be..3525e0777c92b6881876633fb12feec1f3fbc57c 100644 (file)
@@ -91,19 +91,6 @@ Cache<TagStore>::regStats()
     tags->regStats(name());
 }
 
-template<class TagStore>
-Port *
-Cache<TagStore>::getPort(const std::string &if_name, int idx)
-{
-    if (if_name == "cpu_side") {
-        return cpuSidePort;
-    } else if (if_name == "mem_side") {
-        return memSidePort;
-    }  else {
-        panic("Port name %s unrecognized\n", if_name);
-    }
-}
-
 template<class TagStore>
 void
 Cache<TagStore>::cmpAndSwap(BlkType *blk, PacketPtr pkt)
@@ -795,7 +782,7 @@ Cache<TagStore>::functionalAccess(PacketPtr pkt, bool fromCpuSide)
         // continues towards the memory side
         if (fromCpuSide) {
             memSidePort->sendFunctional(pkt);
-        } else if (forwardSnoops) {
+        } else if (forwardSnoops && cpuSidePort->getMasterPort().isSnooping()) {
             // if it came from the memory side, it must be a snoop request
             // and we should only forward it if we are forwarding snoops
             cpuSidePort->sendFunctional(pkt);
index 2e9a0fa00adf95a633e97c429867e9e8aebf6912..bf0c076c6d94f9260404d4bb2e3358762b536b98 100644 (file)
@@ -58,7 +58,7 @@ FSTranslatingPortProxy::FSTranslatingPortProxy(ThreadContext *tc)
 {
 }
 
-FSTranslatingPortProxy::FSTranslatingPortProxy(Port &port)
+FSTranslatingPortProxy::FSTranslatingPortProxy(MasterPort &port)
     : PortProxy(port), _tc(NULL)
 {
 }
index 2217a46aae632f906fee0fa06860e9a5c901bdfd..c022f3d09db01ea2f3e6ac827b907c8a0a4f0a37 100644 (file)
@@ -78,7 +78,7 @@ class FSTranslatingPortProxy : public PortProxy
 
     FSTranslatingPortProxy(ThreadContext* tc);
 
-    FSTranslatingPortProxy(Port &port);
+    FSTranslatingPortProxy(MasterPort &port);
 
     virtual ~FSTranslatingPortProxy();
 
index 111d3718c2fd22dd9b250739c1653a55f8c46906..ce8badbe7bea72a85c49a371ec34acde57608817 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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
  * All rights reserved.
  *
@@ -26,6 +38,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Steve Reinhardt
+ *          Andreas Hansson
  */
 
 #include "mem/mem_object.hh"
@@ -34,3 +47,15 @@ MemObject::MemObject(const Params *params)
     : SimObject(params)
 {
 }
+
+MasterPort&
+MemObject::getMasterPort(const std::string& if_name, int idx)
+{
+    fatal("%s does not have any master port named %s\n", name(), if_name);
+}
+
+SlavePort&
+MemObject::getSlavePort(const std::string& if_name, int idx)
+{
+    fatal("%s does not have any slave port named %s\n", name(), if_name);
+}
index 5865fc93549162445770c171521c1b0be4f782ed..d8e6bdcb0de8a870a3b11f45a4c1e581e413d1e0 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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
  * All rights reserved.
  *
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Ron Dreslinski
+ *          Andreas Hansson
  */
 
 /**
  * @file
- * Base Memory Object declaration.
+ * MemObject declaration.
  */
 
 #ifndef __MEM_MEM_OBJECT_HH__
@@ -41,8 +54,8 @@
 #include "sim/sim_object.hh"
 
 /**
- * The base MemoryObject class, allows for an accesor function to a
- * simobj that returns the Port.
+ * The MemObject class extends the SimObject with accessor functions
+ * to get its master and slave ports.
  */
 class MemObject : public SimObject
 {
@@ -53,9 +66,27 @@ class MemObject : public SimObject
 
     MemObject(const Params *params);
 
-  public:
-    /** Additional function to return the Port of a memory object. */
-    virtual Port *getPort(const std::string &if_name, int idx = -1) = 0;
+    /**
+     * Get a master port with a given name and index.
+     *
+     * @param if_name Port name
+     * @param idx Index in the case of a VectorPort
+     *
+     * @return A reference to the given port
+     */
+    virtual MasterPort& getMasterPort(const std::string& if_name,
+                                      int idx = -1);
+
+    /**
+     * Get a slave port with a given name and index.
+     *
+     * @param if_name Port name
+     * @param idx Index in the case of a VectorPort
+     *
+     * @return A reference to the given port
+     */
+    virtual SlavePort& getSlavePort(const std::string& if_name,
+                                    int idx = -1);
 };
 
 #endif //__MEM_MEM_OBJECT_HH__
index 2c57030b1b9cd0d0821c538be7f0dd88d067fdb4..9af394d27713110a05f1081f41ff9ccf9bc373a8 100644 (file)
 #include "mem/mport.hh"
 
 Tick
-MessagePort::recvAtomic(PacketPtr pkt)
+MessageSlavePort::recvAtomic(PacketPtr pkt)
 {
     if (pkt->cmd == MemCmd::MessageReq) {
         return recvMessage(pkt);
-    } else if (pkt->cmd == MemCmd::MessageResp) {
+    } else {
+        panic("%s received unexpected atomic command %s from %s.\n",
+              name(), pkt->cmd.toString(), getMasterPort().name());
+    }
+}
+
+Tick
+MessageMasterPort::recvAtomic(PacketPtr pkt)
+{
+    if (pkt->cmd == MemCmd::MessageResp) {
         // normally we would never see responses in recvAtomic, but
         // since the timing port uses recvAtomic to implement
-        // recvTiming we have to deal with both cases
+        // recvTiming we have to deal with them here
         return recvResponse(pkt);
     } else {
         panic("%s received unexpected atomic command %s from %s.\n",
-              name(), pkt->cmd.toString(), getPeer()->name());
+              name(), pkt->cmd.toString(), getSlavePort().name());
     }
 }
index 7f167c2274483fd333d5f5db2b87c40c91dbdfbc..664acc559cddf7caf5a8fce3ff29504ec414b1de 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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) 2008 The Regents of The University of Michigan
  * All rights reserved.
  *
  * the underpinnings of SimpleTimingPort, but it tweaks some of the external
  * functions.
  */
-class MessagePort : public SimpleTimingPort
+class MessageSlavePort : public SimpleTimingPort
 {
 
   public:
-    MessagePort(const std::string &name, MemObject *owner) :
+    MessageSlavePort(const std::string &name, MemObject *owner) :
         SimpleTimingPort(name, owner)
     {}
 
-    virtual ~MessagePort()
+    virtual ~MessageSlavePort()
     {}
 
   protected:
@@ -57,6 +69,29 @@ class MessagePort : public SimpleTimingPort
     Tick recvAtomic(PacketPtr pkt);
 
     virtual Tick recvMessage(PacketPtr pkt) = 0;
+};
+
+class MessageMasterPort : public QueuedMasterPort
+{
+  public:
+
+    MessageMasterPort(const std::string &name, MemObject *owner) :
+        QueuedMasterPort(name, owner, queue), queue(*owner, *this)
+    {}
+
+    virtual ~MessageMasterPort()
+    {}
+
+    void recvFunctional(PacketPtr pkt) { assert(false); }
+
+    Tick recvAtomic(PacketPtr pkt);
+
+    bool recvTiming(PacketPtr pkt) { recvAtomic(pkt); return true; }
+
+  protected:
+
+    /** A packet queue for outgoing packets. */
+    PacketQueue queue;
 
     // Accept and ignore responses.
     virtual Tick recvResponse(PacketPtr pkt)
index f11fbb9478f8cc2eee204ae88b8c59e380bcb9f4..9c953e56225188fe7ede306c64ca8ef0b376b1c1 100644 (file)
@@ -439,18 +439,18 @@ PhysicalMemory::doFunctionalAccess(PacketPtr pkt)
 }
 
 
-Port *
-PhysicalMemory::getPort(const std::string &if_name, int idx)
+SlavePort &
+PhysicalMemory::getSlavePort(const std::string &if_name, int idx)
 {
     if (if_name != "port") {
-        panic("PhysicalMemory::getPort: unknown port %s requested\n", if_name);
-    }
+        return MemObject::getSlavePort(if_name, idx);
+    } else {
+        if (idx >= static_cast<int>(ports.size())) {
+            fatal("PhysicalMemory::getSlavePort: unknown index %d\n", idx);
+        }
 
-    if (idx >= static_cast<int>(ports.size())) {
-        panic("PhysicalMemory::getPort: unknown index %d requested\n", idx);
+        return *ports[idx];
     }
-
-    return ports[idx];
 }
 
 PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
@@ -458,13 +458,6 @@ PhysicalMemory::MemoryPort::MemoryPort(const std::string &_name,
     : SimpleTimingPort(_name, _memory), memory(_memory)
 { }
 
-void
-PhysicalMemory::MemoryPort::recvRangeChange()
-{
-    // memory is a slave and thus should never have to worry about its
-    // neighbours address ranges
-}
-
 AddrRangeList
 PhysicalMemory::MemoryPort::getAddrRanges()
 {
index b447237c70db9b88580d52311bb9edc902fb98bd..452ac3fc0b2c8da496b75769621374bd9af62c80 100644 (file)
@@ -67,8 +67,6 @@ class PhysicalMemory : public MemObject
 
         virtual void recvFunctional(PacketPtr pkt);
 
-        virtual void recvRangeChange();
-
         virtual AddrRangeList getAddrRanges();
 
         virtual unsigned deviceBlockSize() const;
@@ -196,7 +194,7 @@ class PhysicalMemory : public MemObject
   public:
     unsigned deviceBlockSize() const;
     AddrRangeList getAddrRanges();
-    virtual Port *getPort(const std::string &if_name, int idx = -1);
+    virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1);
     void virtual init();
     unsigned int drain(Event *de);
 
index 8edca16f74f4f8ae0612c860c6bb0271f5f85885..3305541c72b5e2b00698f6b859e6c917dd768d68 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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
  * All rights reserved.
  *
@@ -26,6 +38,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Steve Reinhardt
+ *          Andreas Hansson
+ *          William Wang
  */
 
 /**
  * Port object definitions.
  */
 #include "base/trace.hh"
-#include "debug/Config.hh"
 #include "mem/mem_object.hh"
 #include "mem/port.hh"
 
-Port::Port(const std::string &_name, MemObject *_owner)
+Port::Port(const std::string &_name, MemObject_owner)
     : portName(_name), peer(NULL), owner(_owner)
 {
 }
@@ -46,22 +59,53 @@ Port::~Port()
 {
 }
 
-void
-Port::setPeer(Port *port)
+/**
+ * Master port
+ */
+MasterPort::MasterPort(const std::string& name, MemObject* owner)
+    : Port(name, *owner), _slavePort(NULL)
 {
-    DPRINTF(Config, "setting peer to %s\n", port->name());
+}
 
-    peer = port;
+MasterPort::~MasterPort()
+{
 }
 
-void
-Port::setOwner(MemObject *_owner)
+SlavePort&
+MasterPort::getSlavePort() const
 {
-    owner = _owner;
+    if(_slavePort == NULL)
+        panic("Cannot getSlavePort on master port %s that is not connected\n",
+              name());
+
+    return *_slavePort;
 }
 
 void
-Port::printAddr(Addr a)
+MasterPort::bind(SlavePort& slave_port)
+{
+    // master port keeps track of the slave port
+    _slavePort = &slave_port;
+    peer = &slave_port;
+
+    // slave port also keeps track of master port
+    _slavePort->bind(*this);
+}
+
+bool
+MasterPort::isConnected() const
+{
+    return _slavePort != NULL;
+}
+
+unsigned
+MasterPort::peerBlockSize() const
+{
+    return _slavePort->deviceBlockSize();
+}
+
+ void
+MasterPort::printAddr(Addr a)
 {
     Request req(a, 1, 0, Request::funcMasterId);
     Packet pkt(&req, MemCmd::PrintReq, Packet::Broadcast);
@@ -70,3 +114,44 @@ Port::printAddr(Addr a)
 
     sendFunctional(&pkt);
 }
+
+/**
+ * Slave port
+ */
+SlavePort::SlavePort(const std::string& name, MemObject* owner)
+    : Port(name, *owner), _masterPort(NULL)
+{
+}
+
+SlavePort::~SlavePort()
+{
+}
+
+void
+SlavePort::bind(MasterPort& master_port)
+{
+    _masterPort = &master_port;
+    peer = &master_port;
+}
+
+MasterPort&
+SlavePort::getMasterPort() const
+{
+    if (_masterPort == NULL)
+        panic("Cannot getMasterPort on slave port %s that is not connected\n",
+              name());
+
+    return *_masterPort;
+}
+
+unsigned
+SlavePort::peerBlockSize() const
+{
+    return _masterPort->deviceBlockSize();
+}
+
+bool
+SlavePort::isConnected() const
+{
+    return _masterPort != NULL;
+}
index fef0c839dd6eda000022ed1680dc80691cc75fc6..80bb3b085c09844d35d9c3be923c204cbdaf6a33 100644 (file)
  *
  * Authors: Ron Dreslinski
  *          Andreas Hansson
+ *          William Wang
  */
 
 /**
  * @file
- * Port Object Declaration. Ports are used to interface memory objects to
- * each other.  They will always come in pairs, and we refer to the other
- * port object as the peer.  These are used to make the design more
- * modular so that a specific interface between every type of objcet doesn't
- * have to be created.
+ * Port Object Declaration.
  */
 
 #ifndef __MEM_PORT_HH__
@@ -58,7 +55,8 @@
 #include "base/range.hh"
 #include "mem/packet.hh"
 
-/** This typedef is used to clean up getAddrRanges(). It's declared
+/**
+ * This typedef is used to clean up getAddrRanges(). It's declared
  * outside the Port object since it's also used by some mem objects.
  * Eventually we should move this typedef to wherever Addr is
  * defined.
@@ -70,62 +68,47 @@ typedef std::list<Range<Addr> >::iterator AddrRangeIter;
 class MemObject;
 
 /**
- * Ports are used to interface memory objects to
- * each other.  They will always come in pairs, and we refer to the other
- * port object as the peer.  These are used to make the design more
- * modular so that a specific interface between every type of objcet doesn't
- * have to be created.
+ * Ports are used to interface memory objects to each other. A port is
+ * either a master or a slave and the connected peer is always of the
+ * opposite role.
  *
- * Recv accesor functions are being called from the peer interface.
- * Send accessor functions are being called from the device the port is
- * associated with, and it will call the peer recv. accessor function.
+ * Each port has a name and an owner, and enables three basic types of
+ * accesses to the peer port: sendFunctional, sendAtomic and
+ * sendTiming.
  */
 class Port
 {
-  protected:
+
+  private:
+
     /** Descriptive name (for DPRINTF output) */
-    mutable std::string portName;
+    std::string portName;
 
-    /** A pointer to the peer port.  Ports always come in pairs, that way they
-        can use a standardized interface to communicate between different
-        memory objects. */
-    Port *peer;
+  protected:
 
-    /** A pointer to the MemObject that owns this port. This may not be set. */
-    MemObject *owner;
+    /** A pointer to the peer port.  */
+    Port* peer;
+
+    /** A reference to the MemObject that owns this port. */
+    MemObject& owner;
 
-  public:
     /**
-     * Constructor.
+     * Abstract base class for ports
      *
-     * @param _name Port name for DPRINTF output.  Should include name
-     * of memory system object to which the port belongs.
-     * @param _owner Pointer to the MemObject that owns this port.
-     * Will not necessarily be set.
+     * @param _name Port name including the owners name
+     * @param _owner The MemObject that is the structural owner of this port
      */
-    Port(const std::string &_name, MemObject *_owner);
-
-    /** Return port name (for DPRINTF). */
-    const std::string &name() const { return portName; }
+    Port(const std::string& _name, MemObject& _owner);
 
+    /**
+     * Virtual destructor due to inheritance.
+     */
     virtual ~Port();
 
-    void setName(const std::string &name)
-    { portName = name; }
-
-    /** Function to set the pointer for the peer port. */
-    virtual void setPeer(Port *port);
-
-    /** Function to get the pointer to the peer port. */
-    Port *getPeer() { return peer; }
-
-    /** Function to set the owner of this port. */
-    void setOwner(MemObject *_owner);
-
-    /** Function to return the owner of this port. */
-    MemObject *getOwner() { return owner; }
+  public:
 
-    bool isConnected() { return peer != NULL; }
+    /** Return port name (for DPRINTF). */
+    const std::string name() const { return portName; }
 
   protected:
 
@@ -141,89 +124,109 @@ class Port
     /** Called to recive a functional call from the peer port. */
     virtual void recvFunctional(PacketPtr pkt) = 0;
 
-    /** Called to recieve an address range change from the peer port. */
-    virtual void recvRangeChange() = 0;
+    /**
+     * Called by a peer port if sendTiming was unsuccesful, and had to
+     * wait.
+     */
+    virtual void recvRetry() = 0;
 
-    /** Called by a peer port if the send was unsuccesful, and had to
-        wait.  This shouldn't be valid for response paths (IO Devices).
-        so it is set to panic if it isn't already defined.
-    */
-    virtual void recvRetry() { panic("??"); }
+  public:
 
-    /** Called by a peer port in order to determine the block size of the
-        device connected to this port.  It sometimes doesn't make sense for
-        this function to be called, so it just returns 0. Anytthing that is
-        concerned with the size should just ignore that.
+    /**
+     * Attempt to send a timing packet to the peer port by calling its
+     * receive function. If the send does not succeed, as indicated by
+     * the return value, then the sender must wait for a recvRetry at
+     * which point it can re-issue a sendTiming.
+     *
+     * @param pkt Packet to send.
+     *
+     * @return If the send was succesful or not.
     */
-    virtual unsigned deviceBlockSize() const { return 0; }
+    bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); }
 
-  public:
+    /**
+     * Send a retry to a peer port that previously attempted a sendTiming
+     * which was unsuccessful.
+     */
+    void sendRetry() { return peer->recvRetry(); }
 
     /**
-     * Get a list of the non-overlapping address ranges we are
-     * responsible for. The default implementation returns an empty
-     * list and thus no address ranges. Any slave port must override
-     * this function and return a populated list with at least one
-     * item.
+     * Send an atomic packet, where the data is moved and the state
+     * is updated in zero time, without interleaving with other
+     * memory accesses.
      *
-     * @return a list of ranges responded to
+     * @param pkt Packet to send.
+     *
+     * @return Estimated latency of access.
      */
-    virtual AddrRangeList getAddrRanges()
-    { AddrRangeList ranges; return ranges; }
+    Tick sendAtomic(PacketPtr pkt) { return peer->recvAtomic(pkt); }
 
     /**
-     * Determine if this port is snooping or not. The default
-     * implementation returns false and thus tells the neighbour we
-     * are not snooping. Any port that is to snoop (e.g. a cache
-     * connected to a bus) has to override this function.
+     * Send a functional packet, where the data is instantly updated
+     * everywhere in the memory system, without affecting the current
+     * state of any block or moving the block.
      *
-     * @return true if the port should be considered a snooper
+     * @param pkt Packet to send.
      */
-    virtual bool isSnooping()
-    { return false; }
-
-    /** Function called by associated memory device (cache, memory, iodevice)
-        in order to send a timing request to the port.  Simply calls the peer
-        port receive function.
-        @return This function returns if the send was succesful in it's
-        recieve. If it was a failure, then the port will wait for a recvRetry
-        at which point it can possibly issue a successful sendTiming.  This is used in
-        case a cache has a higher priority request come in while waiting for
-        the bus to arbitrate.
-    */
-    bool sendTiming(PacketPtr pkt) { return peer->recvTiming(pkt); }
+    void sendFunctional(PacketPtr pkt) { return peer->recvFunctional(pkt); }
 
-    /** Function called by the associated device to send an atomic
-     *   access, an access in which the data is moved and the state is
-     *   updated in one cycle, without interleaving with other memory
-     *   accesses.  Returns estimated latency of access.
-     */
-    Tick sendAtomic(PacketPtr pkt)
-        { return peer->recvAtomic(pkt); }
+};
 
-    /** Function called by the associated device to send a functional access,
-        an access in which the data is instantly updated everywhere in the
-        memory system, without affecting the current state of any block or
-        moving the block.
-    */
-    void sendFunctional(PacketPtr pkt)
-        { return peer->recvFunctional(pkt); }
+/** Forward declaration */
+class SlavePort;
+
+/**
+ * A MasterPort is a specialisation of a port. In addition to the
+ * basic functionality of sending packets to its slave peer, it also
+ * has functions specific to a master, e.g. to receive range changes
+ * or determine if the port is snooping or not.
+ */
+class MasterPort : public Port
+{
+
+  private:
+
+    SlavePort* _slavePort;
+
+  public:
+
+    MasterPort(const std::string& name, MemObject* owner);
+    virtual ~MasterPort();
+
+    void bind(SlavePort& slave_port);
+    SlavePort& getSlavePort() const;
+    bool isConnected() const;
 
     /**
-     * Called by the associated device to send a status range to the
-     * peer interface.
+     * Called to receive an address range change from the peer slave
+     * port. the default implementation ignored the change and does
+     * nothing. Override this function in a derived class if the owner
+     * needs to be aware of he laesddress ranges, e.g. in an
+     * interconnect component like a bus.
      */
-    void sendRangeChange() const { peer->recvRangeChange(); }
+    virtual void recvRangeChange() { }
 
-    /** When a timing access doesn't return a success, some time later the
-        Retry will be sent.
-    */
-    void sendRetry() { return peer->recvRetry(); }
+    /**
+     * Determine if this master port is snooping or not. The default
+     * implementation returns false and thus tells the neighbour we
+     * are not snooping. Any master port that wants to receive snoop
+     * requests (e.g. a cache connected to a bus) has to override this
+     * function.
+     *
+     * @return true if the port should be considered a snooper
+     */
+    virtual bool isSnooping() const { return false; }
+
+    /**
+     * Called by a peer port in order to determine the block size of
+     * the owner of this port.
+     */
+    virtual unsigned deviceBlockSize() const { return 0; }
 
     /** Called by the associated device if it wishes to find out the blocksize
         of the device on attached to the peer port.
     */
-    unsigned peerBlockSize() const { return peer->deviceBlockSize(); }
+    unsigned peerBlockSize() const;
 
     /** Inject a PrintReq for the given address to print the state of
      * that address throughout the memory system.  For debugging.
@@ -231,4 +234,52 @@ class Port
     void printAddr(Addr a);
 };
 
+/**
+ * A SlavePort is a specialisation of a port. In addition to the
+ * basic functionality of sending packets to its master peer, it also
+ * has functions specific to a slave, e.g. to send range changes
+ * and get the address ranges that the port responds to.
+ */
+class SlavePort : public Port
+{
+
+  private:
+
+    MasterPort* _masterPort;
+
+  public:
+
+    SlavePort(const std::string& name, MemObject* owner);
+    virtual ~SlavePort();
+
+    void bind(MasterPort& master_port);
+    MasterPort& getMasterPort() const;
+    bool isConnected() const;
+
+    /**
+     * Called by a peer port in order to determine the block size of
+     * the owner of this port.
+     */
+    virtual unsigned deviceBlockSize() const { return 0; }
+
+    /** Called by the associated device if it wishes to find out the blocksize
+        of the device on attached to the peer port.
+    */
+    unsigned peerBlockSize() const;
+
+    /**
+     * Called by the owner to send a range change
+     */
+    void sendRangeChange() const { _masterPort->recvRangeChange(); }
+
+    /**
+     * Get a list of the non-overlapping address ranges the owner is
+     * responsible for. All slave ports must override this function
+     * and return a populated list with at least one item.
+     *
+     * @return a list of ranges responded to
+     */
+    virtual AddrRangeList getAddrRanges() = 0;
+};
+
 #endif //__MEM_PORT_HH__
index b2b27312e5e60837855628ffa77ce23079fb9832..4600cd40713e53b17383572f5f497a3f62810da7 100644 (file)
@@ -86,12 +86,12 @@ class PortProxy
   private:
 
     /** The actual physical port used by this proxy. */
-    Port &_port;
+    MasterPort &_port;
 
     void blobHelper(Addr addr, uint8_t *p, int size, MemCmd cmd) const;
 
   public:
-    PortProxy(Port &port) : _port(port) { }
+    PortProxy(MasterPort &port) : _port(port) { }
     virtual ~PortProxy() { }
 
     /**
index 39612d22f9a99477cf0e0942a7b1b33c032fb1ad..6ee71a572d36cc48bfc0c1712cea44875e02cbab 100644 (file)
@@ -56,7 +56,7 @@
  * queue is a parameter to allow tailoring of the queue implementation
  * (used in the cache).
  */
-class QueuedPort : public Port
+class QueuedSlavePort : public SlavePort
 {
 
   protected:
@@ -68,7 +68,46 @@ class QueuedPort : public Port
       * packet again. */
     virtual void recvRetry() { queue.retry(); }
 
-    virtual void recvRangeChange() { }
+  public:
+
+    /**
+     * Create a QueuedPort with a given name, owner, and a supplied
+     * implementation of a packet queue. The external definition of
+     * the queue enables e.g. the cache to implement a specific queue
+     * behaviuor in a subclass, and provide the latter to the
+     * QueuePort constructor.
+     */
+    QueuedSlavePort(const std::string& name, MemObject* owner,
+                    PacketQueue &queue) :
+        SlavePort(name, owner), queue(queue)
+    { }
+
+    virtual ~QueuedSlavePort() { }
+
+    /** Check the list of buffered packets against the supplied
+     * functional request. */
+    bool checkFunctional(PacketPtr pkt) { return queue.checkFunctional(pkt); }
+
+    /**
+     * Hook for draining the queued port.
+     *
+     * @param de an event which is used to signal back to the caller
+     * @returns a number indicating how many times process will be called
+     */
+    unsigned int drain(Event *de) { return queue.drain(de); }
+};
+
+class QueuedMasterPort : public MasterPort
+{
+
+  protected:
+
+    /** Packet queue used to store outgoing requests and responses. */
+    PacketQueue &queue;
+
+     /** This function is notification that the device should attempt to send a
+      * packet again. */
+    virtual void recvRetry() { queue.retry(); }
 
   public:
 
@@ -79,11 +118,12 @@ class QueuedPort : public Port
      * behaviuor in a subclass, and provide the latter to the
      * QueuePort constructor.
      */
-    QueuedPort(const std::string& name, MemObject* owner, PacketQueue &queue) :
-        Port(name, owner), queue(queue)
+    QueuedMasterPort(const std::string& name, MemObject* owner,
+                    PacketQueue &queue) :
+        MasterPort(name, owner), queue(queue)
     { }
 
-    virtual ~QueuedPort() { }
+    virtual ~QueuedMasterPort() { }
 
     /** Check the list of buffered packets against the supplied
      * functional request. */
index aca6604c6fcbb1b71cc419a89d15b07d2c0c6a92..1769c51fd2fbe0de21b5a6cafe23ecc414dc8554 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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) 2009 Advanced Micro Devices, Inc.
  * Copyright (c) 2011 Mark D. Hill and David A. Wood
  * All rights reserved.
 #include "mem/ruby/system/RubyPort.hh"
 
 RubyPort::RubyPort(const Params *p)
-    : MemObject(p), pio_port(csprintf("%s-pio-port", name()), this),
-      physMemPort(csprintf("%s-physMemPort", name()), this)
+    : MemObject(p), m_version(p->version), m_controller(NULL),
+      m_mandatory_q_ptr(NULL),
+      pio_port(csprintf("%s-pio-port", name()), this),
+      m_usingRubyTester(p->using_ruby_tester), m_request_cnt(0),
+      physMemPort(csprintf("%s-physMemPort", name()), this),
+      drainEvent(NULL), physmem(p->physmem), ruby_system(p->ruby_system),
+      waitingOnSequencer(false), access_phys_mem(p->access_phys_mem)
 {
-    m_version = p->version;
     assert(m_version != -1);
 
-    physmem = p->physmem;
-
-    m_controller = NULL;
-    m_mandatory_q_ptr = NULL;
-
-    m_request_cnt = 0;
-
-    m_usingRubyTester = p->using_ruby_tester;
-    access_phys_mem = p->access_phys_mem;
-
-    drainEvent = NULL;
+    // create the slave ports based on the number of connected ports
+    for (size_t i = 0; i < p->port_slave_connection_count; ++i) {
+        slave_ports.push_back(new M5Port(csprintf("%s-slave%d", name(), i),
+                                         this, ruby_system, access_phys_mem));
+    }
 
-    ruby_system = p->ruby_system;
-    waitingOnSequencer = false;
+    // create the master ports based on the number of connected ports
+    for (size_t i = 0; i < p->port_master_connection_count; ++i) {
+        master_ports.push_back(new PioPort(csprintf("%s-master%d", name(), i),
+                                           this));
+    }
 }
 
 void
@@ -64,52 +77,63 @@ RubyPort::init()
     m_mandatory_q_ptr = m_controller->getMandatoryQueue();
 }
 
-Port *
-RubyPort::getPort(const std::string &if_name, int idx)
+MasterPort &
+RubyPort::getMasterPort(const std::string &if_name, int idx)
 {
-    // used by the CPUs to connect the caches to the interconnect, and
-    // for the x86 case also the interrupt master
-    if (if_name == "slave") {
-        M5Port* cpuPort = new M5Port(csprintf("%s-slave%d", name(), idx),
-                                     this, ruby_system, access_phys_mem);
-        cpu_ports.push_back(cpuPort);
-        return cpuPort;
+    if (if_name == "pio_port") {
+        return pio_port;
+    }
+
+    if (if_name == "physMemPort") {
+        return physMemPort;
     }
 
     // used by the x86 CPUs to connect the interrupt PIO and interrupt slave
     // port
-    if (if_name == "master") {
-        PioPort* masterPort = new PioPort(csprintf("%s-master%d", name(), idx),
-                                          this);
+    if (if_name != "master") {
+        // pass it along to our super class
+        return MemObject::getMasterPort(if_name, idx);
+    } else {
+        if (idx >= static_cast<int>(master_ports.size())) {
+            panic("RubyPort::getMasterPort: unknown index %d\n", idx);
+        }
 
-        return masterPort;
+        return *master_ports[idx];
     }
+}
 
-    if (if_name == "pio_port") {
-        return &pio_port;
-    }
+SlavePort &
+RubyPort::getSlavePort(const std::string &if_name, int idx)
+{
+    // used by the CPUs to connect the caches to the interconnect, and
+    // for the x86 case also the interrupt master
+    if (if_name != "slave") {
+        // pass it along to our super class
+        return MemObject::getSlavePort(if_name, idx);
+    } else {
+        if (idx >= static_cast<int>(slave_ports.size())) {
+            panic("RubyPort::getSlavePort: unknown index %d\n", idx);
+        }
 
-    if (if_name == "physMemPort") {
-        return &physMemPort;
+        return *slave_ports[idx];
     }
-
-    return NULL;
 }
 
 RubyPort::PioPort::PioPort(const std::string &_name,
                            RubyPort *_port)
-    : QueuedPort(_name, _port, queue), queue(*_port, *this), ruby_port(_port)
+    : QueuedMasterPort(_name, _port, queue), queue(*_port, *this),
+      ruby_port(_port)
 {
-    DPRINTF(RubyPort, "creating port to ruby sequencer to cpu %s\n", _name);
+    DPRINTF(RubyPort, "creating master port on ruby sequencer %s\n", _name);
 }
 
 RubyPort::M5Port::M5Port(const std::string &_name, RubyPort *_port,
                          RubySystem *_system, bool _access_phys_mem)
-    : QueuedPort(_name, _port, queue), queue(*_port, *this),
+    : QueuedSlavePort(_name, _port, queue), queue(*_port, *this),
       ruby_port(_port), ruby_system(_system),
       _onRetryList(false), access_phys_mem(_access_phys_mem)
 {
-    DPRINTF(RubyPort, "creating port from ruby sequcner to cpu %s\n", _name);
+    DPRINTF(RubyPort, "creating slave port on ruby sequencer %s\n", _name);
 }
 
 Tick
@@ -549,11 +573,15 @@ RubyPort::getDrainCount(Event *de)
         DPRINTF(Config, "count after physmem check %d\n", count);
     }
 
-    for (CpuPortIter p_iter = cpu_ports.begin(); p_iter != cpu_ports.end();
-         p_iter++) {
-        M5Port* cpu_port = *p_iter;
-        count += cpu_port->drain(de);
-        DPRINTF(Config, "count after cpu port check %d\n", count);
+    for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) {
+        count += (*p)->drain(de);
+        DPRINTF(Config, "count after slave port check %d\n", count);
+    }
+
+    for (std::vector<PioPort*>::iterator p = master_ports.begin();
+         p != master_ports.end(); ++p) {
+        count += (*p)->drain(de);
+        DPRINTF(Config, "count after master port check %d\n", count);
     }
 
     DPRINTF(Config, "final count %d\n", count);
@@ -657,11 +685,19 @@ RubyPort::PioPort::sendNextCycle(PacketPtr pkt)
     return true;
 }
 
+AddrRangeList
+RubyPort::M5Port::getAddrRanges()
+{
+    // at the moment the assumption is that the master does not care
+    AddrRangeList ranges;
+    return ranges;
+}
+
 bool
 RubyPort::M5Port::isPhysMemAddress(Addr addr)
 {
     AddrRangeList physMemAddrList =
-        ruby_port->physMemPort.getPeer()->getAddrRanges();
+        ruby_port->physMemPort.getSlavePort().getAddrRanges();
     for (AddrRangeIter iter = physMemAddrList.begin();
          iter != physMemAddrList.end();
          iter++) {
@@ -684,9 +720,12 @@ void
 RubyPort::ruby_eviction_callback(const Address& address)
 {
     DPRINTF(RubyPort, "Sending invalidations.\n");
+    // should this really be using funcMasterId?
     Request req(address.getAddress(), 0, 0, Request::funcMasterId);
-    for (CpuPortIter it = cpu_ports.begin(); it != cpu_ports.end(); it++) {
-        Packet *pkt = new Packet(&req, MemCmd::InvalidationReq, -1);
-        (*it)->sendNextCycle(pkt);
+    for (CpuPortIter p = slave_ports.begin(); p != slave_ports.end(); ++p) {
+        if ((*p)->getMasterPort().isSnooping()) {
+            Packet *pkt = new Packet(&req, MemCmd::InvalidationReq, -1);
+            (*p)->sendNextCycle(pkt);
+        }
     }
 }
index bef291d6354a8c8fa1f86504259e7a799691055d..d97f6e69e7817ef1351f0865a37605c40cd44fec 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 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) 2009 Advanced Micro Devices, Inc.
  * Copyright (c) 2011 Mark D. Hill and David A. Wood
  * All rights reserved.
@@ -46,7 +58,7 @@ class AbstractController;
 class RubyPort : public MemObject
 {
   public:
-    class M5Port : public QueuedPort
+    class M5Port : public QueuedSlavePort
     {
       private:
 
@@ -74,6 +86,7 @@ class RubyPort : public MemObject
         virtual bool recvTiming(PacketPtr pkt);
         virtual Tick recvAtomic(PacketPtr pkt);
         virtual void recvFunctional(PacketPtr pkt);
+        virtual AddrRangeList getAddrRanges();
 
       private:
         bool isPhysMemAddress(Addr addr);
@@ -83,7 +96,7 @@ class RubyPort : public MemObject
 
     friend class M5Port;
 
-    class PioPort : public QueuedPort
+    class PioPort : public QueuedMasterPort
     {
       private:
 
@@ -119,7 +132,8 @@ class RubyPort : public MemObject
 
     void init();
 
-    Port *getPort(const std::string &if_name, int idx);
+    MasterPort &getMasterPort(const std::string &if_name, int idx);
+    SlavePort &getSlavePort(const std::string &if_name, int idx);
 
     virtual RequestStatus makeRequest(PacketPtr pkt) = 0;
     virtual int outstandingCount() const = 0;
@@ -163,9 +177,10 @@ class RubyPort : public MemObject
 
     PioPort physMemPort;
 
-    /*! Vector of CPU Port attached to this Ruby port. */
+    /** Vector of M5 Ports attached to this Ruby port. */
     typedef std::vector<M5Port*>::iterator CpuPortIter;
-    std::vector<M5Port*> cpu_ports;
+    std::vector<M5Port*> slave_ports;
+    std::vector<PioPort*> master_ports;
 
     Event *drainEvent;
 
index 2ab13074441b7e8c610f097a923008aff08fd1df..72466655c40fdac2e906107a7b99de61ddcd917d 100644 (file)
@@ -53,7 +53,7 @@
 
 using namespace TheISA;
 
-SETranslatingPortProxy::SETranslatingPortProxy(Port& port, Process *p,
+SETranslatingPortProxy::SETranslatingPortProxy(MasterPort& port, Process *p,
                                            AllocType alloc)
     : PortProxy(port), pTable(p->pTable), process(p),
       allocating(alloc)
index 31874e6b8e4df64604d80d43dd3c76e68178d612..c0e522611f15f2f6e738df45b09550519690c4d1 100644 (file)
@@ -80,7 +80,7 @@ class SETranslatingPortProxy : public PortProxy
     AllocType allocating;
 
   public:
-    SETranslatingPortProxy(Port& port, Process* p, AllocType alloc);
+    SETranslatingPortProxy(MasterPort& port, Process* p, AllocType alloc);
     virtual ~SETranslatingPortProxy();
 
     bool tryReadBlob(Addr addr, uint8_t *p, int size) const;
index bf3d59a8f93905590d452600b5670f71d9b048d5..db2c72bbc64016fe5e037d0160b60163550a331d 100644 (file)
@@ -46,7 +46,7 @@
 
 SimpleTimingPort::SimpleTimingPort(const std::string& _name,
                                    MemObject* _owner) :
-    QueuedPort(_name, _owner, queue), queue(*_owner, *this)
+    QueuedSlavePort(_name, _owner, queue), queue(*_owner, *this)
 {
 }
 
@@ -63,6 +63,9 @@ SimpleTimingPort::recvFunctional(PacketPtr pkt)
 bool
 SimpleTimingPort::recvTiming(PacketPtr pkt)
 {
+    // the port is a slave and should hence only get timing requests
+    assert(pkt->isRequest());
+
     if (pkt->memInhibitAsserted()) {
         // snooper will supply based on copy of packet
         // still target's responsibility to delete packet
index c77166386ba20aa7aeb733b1226ba7d1223b7392..91706fbe9374b443bcd1ee0381e8be8f9308d8cb 100644 (file)
@@ -57,7 +57,7 @@
  * recvFunctional and recvTiming through recvAtomic. It is always a
  * slave port.
  */
-class SimpleTimingPort : public QueuedPort
+class SimpleTimingPort : public QueuedSlavePort
 {
 
   protected:
index 3478310b1afa58b3354ede59686cc958aad3b3e4..05698e79443b29d0a480714e75f4a32938f3a094 100644 (file)
 
 using namespace std;
 
-/**
- * Look up a MemObject port.  Helper function for connectPorts().
- */
-Port *
-lookupPort(SimObject *so, const std::string &name, int i)
-{
-    MemObject *mo = dynamic_cast<MemObject *>(so);
-    if (mo == NULL) {
-        warn("error casting SimObject %s to MemObject", so->name());
-        return NULL;
-    }
-
-    Port *p = mo->getPort(name, i);
-    if (p == NULL)
-        warn("error looking up port %s on object %s", name, so->name());
-    return p;
-}
-
 EtherInt *
 lookupEthPort(SimObject *so, const std::string &name, int i)
 {
@@ -83,6 +65,7 @@ lookupEthPort(SimObject *so, const std::string &name, int i)
 /**
  * Connect the described MemObject ports.  Called from Python via SWIG.
  * The indices i1 & i2 will be -1 for regular ports, >= 0 for vector ports.
+ * SimObject1 is the master, and SimObject2 is the slave
  */
 int
 connectPorts(SimObject *o1, const std::string &name1, int i1,
@@ -109,16 +92,20 @@ connectPorts(SimObject *o1, const std::string &name1, int i1,
             }
         }
     }
-    Port *p1 = lookupPort(o1, name1, i1);
-    Port *p2 = lookupPort(o2, name2, i2);
+    MemObject *mo1, *mo2;
+    mo1 = dynamic_cast<MemObject*>(o1);
+    mo2 = dynamic_cast<MemObject*>(o2);
 
-    if (p1 == NULL || p2 == NULL) {
-        warn("connectPorts: port lookup error");
-        return 0;
+    if(mo1 == NULL || mo2 == NULL) {
+        panic ("Error casting SimObjects %s and %s to MemObject", o1->name(),
+               o2->name());
     }
 
-    p1->setPeer(p2);
-    p2->setPeer(p1);
+    // generic master/slave port connection
+    MasterPort& masterPort = mo1->getMasterPort(name1, i1);
+    SlavePort& slavePort   = mo2->getSlavePort(name2, i2);
+
+    masterPort.bind(slavePort);
 
     return 1;
 }
index 4601d2d52f2ad34300136240246b56b62c67bdaf..2c5d4e44b29ffa8fe3438b4422727a8a2198c991 100644 (file)
@@ -174,11 +174,11 @@ System::init()
         panic("System port on %s is not connected.\n", name());
 }
 
-Port*
-System::getPort(const std::string &if_name, int idx)
+MasterPort&
+System::getMasterPort(const std::string &if_name, int idx)
 {
     // no need to distinguish at the moment (besides checking)
-    return &_systemPort;
+    return _systemPort;
 }
 
 void
index dd122161dfa9d2dd38302e8846cb6ca3ac409499..d5e45fa0d92f866fc8ae4ef056a919b5744746fa 100644 (file)
@@ -78,7 +78,7 @@ class System : public MemObject
      * master for debug access and for non-structural entities that do
      * not have a port of their own.
      */
-    class SystemPort : public Port
+    class SystemPort : public MasterPort
     {
       public:
 
@@ -86,22 +86,16 @@ class System : public MemObject
          * Create a system port with a name and an owner.
          */
         SystemPort(const std::string &_name, MemObject *_owner)
-            : Port(_name, _owner)
+            : MasterPort(_name, _owner)
         { }
         bool recvTiming(PacketPtr pkt)
         { panic("SystemPort does not receive timing!\n"); return false; }
+        void recvRetry()
+        { panic("SystemPort does not expect retry!\n"); }
         Tick recvAtomic(PacketPtr pkt)
         { panic("SystemPort does not receive atomic!\n"); return 0; }
         void recvFunctional(PacketPtr pkt)
         { panic("SystemPort does not receive functional!\n"); }
-
-        /**
-         * The system port is a master port connected to a single
-         * slave and thus do not care about what ranges the slave
-         * covers (as there is nothing to choose from).
-         */
-        void recvRangeChange() { }
-
     };
 
     SystemPort _systemPort;
@@ -122,12 +116,12 @@ class System : public MemObject
      *
      * @return a reference to the system port we own
      */
-    Port& getSystemPort() { return _systemPort; }
+    MasterPort& getSystemPort() { return _systemPort; }
 
     /**
      * Additional function to return the Port of a memory object.
      */
-    Port *getPort(const std::string &if_name, int idx = -1);
+    MasterPort& getMasterPort(const std::string &if_name, int idx = -1);
 
     static const char *MemoryModeStrings[3];
 
index 253f1207208f19c009f097b1190daca06591ef7a..379cdd3436bddf293c1b864fc5c669498f882792 100644 (file)
@@ -49,8 +49,7 @@
 #include "sim/sim_object.hh"
 
 class ThreadContext;
-class Packet;
-class Port;
+class MasterPort;
 
 class BaseTLB : public SimObject
 {
@@ -65,10 +64,16 @@ class BaseTLB : public SimObject
   public:
     virtual void demapPage(Addr vaddr, uint64_t asn) = 0;
 
-    /** Get any port that the TLB or hardware table walker needs.
-     * This is used for migrating port connections during a takeOverFrom()
-     * call. */
-    virtual Port*  getPort() { return NULL; }
+    /**
+     * Get the table walker master port if present. This is used for
+     * migrating port connections during a CPU takeOverFrom()
+     * call. For architectures that do not have a table walker, NULL
+     * is returned, hence the use of a pointer rather than a
+     * reference.
+     *
+     * @return A pointer to the walker master port or NULL if not present
+     */
+    virtual MasterPort* getMasterPort() { return NULL; }
 
     class Translation
     {