summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wang <william.wang@arm.com>2012-03-30 09:40:11 -0400
committerWilliam Wang <william.wang@arm.com>2012-03-30 09:40:11 -0400
commitf9d403a7b95c50a8b75f8442101eb87ca465f967 (patch)
treea8302eb02dd5947d53b9437cc19d552145267189
parenta14013af3a9e04d68985aea7bcff6c1e70bdbb82 (diff)
downloadgem5-f9d403a7b95c50a8b75f8442101eb87ca465f967.tar.xz
MEM: Introduce the master/slave port sub-classes in C++
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.
-rw-r--r--src/arch/arm/table_walker.cc8
-rw-r--r--src/arch/arm/table_walker.hh3
-rw-r--r--src/arch/arm/tlb.cc6
-rw-r--r--src/arch/arm/tlb.hh13
-rw-r--r--src/arch/x86/interrupts.cc17
-rw-r--r--src/arch/x86/interrupts.hh21
-rw-r--r--src/arch/x86/pagetable_walker.cc13
-rw-r--r--src/arch/x86/pagetable_walker.hh9
-rw-r--r--src/arch/x86/tlb.cc6
-rw-r--r--src/arch/x86/tlb.hh12
-rw-r--r--src/cpu/base.cc75
-rw-r--r--src/cpu/base.hh15
-rw-r--r--src/cpu/checker/cpu.hh6
-rw-r--r--src/cpu/inorder/resources/cache_unit.hh2
-rw-r--r--src/cpu/o3/cpu.hh3
-rw-r--r--src/cpu/o3/lsq_unit.hh4
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh2
-rw-r--r--src/cpu/ozone/OzoneCPU.py3
-rw-r--r--src/cpu/ozone/cpu.hh2
-rw-r--r--src/cpu/ozone/cpu_impl.hh12
-rw-r--r--src/cpu/ozone/front_end.hh5
-rw-r--r--src/cpu/ozone/front_end_impl.hh6
-rw-r--r--src/cpu/ozone/lw_lsq.hh7
-rw-r--r--src/cpu/ozone/lw_lsq_impl.hh6
-rw-r--r--src/cpu/simple/atomic.cc10
-rw-r--r--src/cpu/simple/atomic.hh7
-rw-r--r--src/cpu/testers/directedtest/RubyDirectedTester.cc20
-rw-r--r--src/cpu/testers/directedtest/RubyDirectedTester.hh12
-rw-r--r--src/cpu/testers/memtest/memtest.cc15
-rw-r--r--src/cpu/testers/memtest/memtest.hh9
-rw-r--r--src/cpu/testers/networktest/networktest.cc13
-rw-r--r--src/cpu/testers/networktest/networktest.hh9
-rw-r--r--src/cpu/testers/rubytest/RubyTester.cc19
-rw-r--r--src/cpu/testers/rubytest/RubyTester.hh12
-rw-r--r--src/dev/copy_engine.cc23
-rw-r--r--src/dev/copy_engine.hh5
-rw-r--r--src/dev/io_device.cc19
-rw-r--r--src/dev/io_device.hh16
-rw-r--r--src/dev/pcidev.hh6
-rw-r--r--src/dev/x86/i82094aa.cc4
-rw-r--r--src/dev/x86/i82094aa.hh6
-rw-r--r--src/dev/x86/intdev.cc8
-rw-r--r--src/dev/x86/intdev.hh37
-rw-r--r--src/kern/tru64/tru64_events.cc4
-rw-r--r--src/mem/bridge.cc45
-rw-r--r--src/mem/bridge.hh21
-rw-r--r--src/mem/bus.cc117
-rw-r--r--src/mem/bus.hh103
-rw-r--r--src/mem/cache/base.cc25
-rw-r--r--src/mem/cache/base.hh11
-rw-r--r--src/mem/cache/builder.cc1
-rw-r--r--src/mem/cache/cache.hh2
-rw-r--r--src/mem/cache/cache_impl.hh15
-rw-r--r--src/mem/fs_translating_port_proxy.cc2
-rw-r--r--src/mem/fs_translating_port_proxy.hh2
-rw-r--r--src/mem/mem_object.cc25
-rw-r--r--src/mem/mem_object.hh43
-rw-r--r--src/mem/mport.cc17
-rw-r--r--src/mem/mport.hh41
-rw-r--r--src/mem/physical.cc23
-rw-r--r--src/mem/physical.hh4
-rw-r--r--src/mem/port.cc105
-rw-r--r--src/mem/port.hh267
-rw-r--r--src/mem/port_proxy.hh4
-rw-r--r--src/mem/qport.hh50
-rw-r--r--src/mem/ruby/system/RubyPort.cc137
-rw-r--r--src/mem/ruby/system/RubyPort.hh25
-rw-r--r--src/mem/se_translating_port_proxy.cc2
-rw-r--r--src/mem/se_translating_port_proxy.hh2
-rw-r--r--src/mem/tport.cc5
-rw-r--r--src/mem/tport.hh2
-rw-r--r--src/python/swig/pyobject.cc37
-rw-r--r--src/sim/system.cc6
-rw-r--r--src/sim/system.hh18
-rw-r--r--src/sim/tlb.hh17
75 files changed, 1031 insertions, 653 deletions
diff --git a/src/arch/arm/table_walker.cc b/src/arch/arm/table_walker.cc
index 8bffe68f8..73a691cff 100644
--- a/src/arch/arm/table_walker.cc
+++ b/src/arch/arm/table_walker.cc
@@ -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
diff --git a/src/arch/arm/table_walker.hh b/src/arch/arm/table_walker.hh
index b5099bb27..a6ff2585b 100644
--- a/src/arch/arm/table_walker.hh
+++ b/src/arch/arm/table_walker.hh
@@ -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);
diff --git a/src/arch/arm/tlb.cc b/src/arch/arm/tlb.cc
index 0b003e9fb..f9b2e6fe7 100644
--- a/src/arch/arm/tlb.cc
+++ b/src/arch/arm/tlb.cc
@@ -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");
}
diff --git a/src/arch/arm/tlb.hh b/src/arch/arm/tlb.hh
index daf59f01d..a20957f6a 100644
--- a/src/arch/arm/tlb.hh
+++ b/src/arch/arm/tlb.hh
@@ -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.
diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc
index 6a9f07af2..a422a4758 100644
--- a/src/arch/x86/interrupts.cc
+++ b/src/arch/x86/interrupts.cc
@@ -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;
diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh
index abf3040bd..328e7159d 100644
--- a/src/arch/x86/interrupts.hh
+++ b/src/arch/x86/interrupts.hh
@@ -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);
}
/*
diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc
index f29531cd5..87505f4df 100644
--- a/src/arch/x86/pagetable_walker.cc
+++ b/src/arch/x86/pagetable_walker.cc
@@ -154,11 +154,6 @@ Walker::WalkerPort::recvFunctional(PacketPtr pkt)
}
void
-Walker::WalkerPort::recvRangeChange()
-{
-}
-
-void
Walker::WalkerPort::recvRetry()
{
walker->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
diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh
index 90f075280..bf7a9e615 100644
--- a/src/arch/x86/pagetable_walker.hh
+++ b/src/arch/x86/pagetable_walker.hh
@@ -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.
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index 10ef217e1..89561f851 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -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
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
index 078b8b8d6..bcadda762 100644
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -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();
};
}
diff --git a/src/cpu/base.cc b/src/cpu/base.cc
index 5d5f704db..d01dcbef3 100644
--- a/src/cpu/base.cc
+++ b/src/cpu/base.cc
@@ -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()
-{
-}
diff --git a/src/cpu/base.hh b/src/cpu/base.hh
index 149d26aa3..145b014aa 100644
--- a/src/cpu/base.hh
+++ b/src/cpu/base.hh
@@ -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; }
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index afc453f87..d816578ae 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -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;
diff --git a/src/cpu/inorder/resources/cache_unit.hh b/src/cpu/inorder/resources/cache_unit.hh
index d9f98e42c..3f3ef12e6 100644
--- a/src/cpu/inorder/resources/cache_unit.hh
+++ b/src/cpu/inorder/resources/cache_unit.hh
@@ -139,7 +139,7 @@ class CacheUnit : public Resource
protected:
/** Cache interface. */
- Port *cachePort;
+ MasterPort *cachePort;
bool cachePortBlocked;
diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh
index 42e9f01f9..493730458 100644
--- a/src/cpu/o3/cpu.hh
+++ b/src/cpu/o3/cpu.hh
@@ -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
diff --git a/src/cpu/o3/lsq_unit.hh b/src/cpu/o3/lsq_unit.hh
index 702606d39..44898eb38 100644
--- a/src/cpu/o3/lsq_unit.hh
+++ b/src/cpu/o3/lsq_unit.hh
@@ -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
diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh
index d0a630f6d..2de349242 100644
--- a/src/cpu/o3/lsq_unit_impl.hh
+++ b/src/cpu/o3/lsq_unit_impl.hh
@@ -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;
}
diff --git a/src/cpu/ozone/OzoneCPU.py b/src/cpu/ozone/OzoneCPU.py
index d50d8d715..b4f37220c 100644
--- a/src/cpu/ozone/OzoneCPU.py
+++ b/src/cpu/ozone/OzoneCPU.py
@@ -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")
diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh
index d2b90bff3..1bd2ee25b 100644
--- a/src/cpu/ozone/cpu.hh
+++ b/src/cpu/ozone/cpu.hh
@@ -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;
diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh
index b111d4425..3a32c07c6 100644
--- a/src/cpu/ozone/cpu_impl.hh
+++ b/src/cpu/ozone/cpu_impl.hh
@@ -391,18 +391,6 @@ OzoneCPU<Impl>::init()
}
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)
{
diff --git a/src/cpu/ozone/front_end.hh b/src/cpu/ozone/front_end.hh
index 41b86aab8..6c63bf8d9 100644
--- a/src/cpu/ozone/front_end.hh
+++ b/src/cpu/ozone/front_end.hh
@@ -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);
diff --git a/src/cpu/ozone/front_end_impl.hh b/src/cpu/ozone/front_end_impl.hh
index 2c9c70872..12aa0a321 100644
--- a/src/cpu/ozone/front_end_impl.hh
+++ b/src/cpu/ozone/front_end_impl.hh
@@ -59,12 +59,6 @@ FrontEnd<Impl>::IcachePort::recvFunctional(PacketPtr pkt)
}
template<class Impl>
-void
-FrontEnd<Impl>::IcachePort::recvRangeChange()
-{
-}
-
-template<class Impl>
bool
FrontEnd<Impl>::IcachePort::recvTiming(PacketPtr pkt)
{
diff --git a/src/cpu/ozone/lw_lsq.hh b/src/cpu/ozone/lw_lsq.hh
index 809725c0d..a581b242f 100644
--- a/src/cpu/ozone/lw_lsq.hh
+++ b/src/cpu/ozone/lw_lsq.hh
@@ -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);
diff --git a/src/cpu/ozone/lw_lsq_impl.hh b/src/cpu/ozone/lw_lsq_impl.hh
index 82d0b4e8b..c0c6d7276 100644
--- a/src/cpu/ozone/lw_lsq_impl.hh
+++ b/src/cpu/ozone/lw_lsq_impl.hh
@@ -75,12 +75,6 @@ OzoneLWLSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt)
}
template <class Impl>
-void
-OzoneLWLSQ<Impl>::DcachePort::recvRangeChange()
-{
-}
-
-template <class Impl>
bool
OzoneLWLSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt)
{
diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc
index e5b3bd67d..d7ad07a5e 100644
--- a/src/cpu/simple/atomic.cc
+++ b/src/cpu/simple/atomic.cc
@@ -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
diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh
index 8a1c9000f..126cd3765 100644
--- a/src/cpu/simple/atomic.hh
+++ b/src/cpu/simple/atomic.hh
@@ -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);
diff --git a/src/cpu/testers/directedtest/RubyDirectedTester.cc b/src/cpu/testers/directedtest/RubyDirectedTester.cc
index 4518066eb..bfdd28e08 100644
--- a/src/cpu/testers/directedtest/RubyDirectedTester.cc
+++ b/src/cpu/testers/directedtest/RubyDirectedTester.cc
@@ -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());
diff --git a/src/cpu/testers/directedtest/RubyDirectedTester.hh b/src/cpu/testers/directedtest/RubyDirectedTester.hh
index cd0632976..cb207ff80 100644
--- a/src/cpu/testers/directedtest/RubyDirectedTester.hh
+++ b/src/cpu/testers/directedtest/RubyDirectedTester.hh
@@ -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();
diff --git a/src/cpu/testers/memtest/memtest.cc b/src/cpu/testers/memtest/memtest.cc
index dffaa71ed..07cdf73a6 100644
--- a/src/cpu/testers/memtest/memtest.cc
+++ b/src/cpu/testers/memtest/memtest.cc
@@ -85,11 +85,6 @@ MemTest::CpuPort::recvFunctional(PacketPtr pkt)
}
void
-MemTest::CpuPort::recvRangeChange()
-{
-}
-
-void
MemTest::CpuPort::recvRetry()
{
memtest->doRetry();
@@ -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
diff --git a/src/cpu/testers/memtest/memtest.hh b/src/cpu/testers/memtest/memtest.hh
index c56a37574..d179fa530 100644
--- a/src/cpu/testers/memtest/memtest.hh
+++ b/src/cpu/testers/memtest/memtest.hh
@@ -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();
};
diff --git a/src/cpu/testers/networktest/networktest.cc b/src/cpu/testers/networktest/networktest.cc
index 3fe153c4e..01f247707 100644
--- a/src/cpu/testers/networktest/networktest.cc
+++ b/src/cpu/testers/networktest/networktest.cc
@@ -82,11 +82,6 @@ NetworkTest::CpuPort::recvFunctional(PacketPtr pkt)
}
void
-NetworkTest::CpuPort::recvRangeChange()
-{
-}
-
-void
NetworkTest::CpuPort::recvRetry()
{
networktest->doRetry();
@@ -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
diff --git a/src/cpu/testers/networktest/networktest.hh b/src/cpu/testers/networktest/networktest.hh
index de67d41a0..21984f45d 100644
--- a/src/cpu/testers/networktest/networktest.hh
+++ b/src/cpu/testers/networktest/networktest.hh
@@ -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();
};
diff --git a/src/cpu/testers/rubytest/RubyTester.cc b/src/cpu/testers/rubytest/RubyTester.cc
index 70ee40aed..e1942cf61 100644
--- a/src/cpu/testers/rubytest/RubyTester.cc
+++ b/src/cpu/testers/rubytest/RubyTester.cc
@@ -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());
diff --git a/src/cpu/testers/rubytest/RubyTester.hh b/src/cpu/testers/rubytest/RubyTester.hh
index e8cf4c874..b24dddd83 100644
--- a/src/cpu/testers/rubytest/RubyTester.hh
+++ b/src/cpu/testers/rubytest/RubyTester.hh
@@ -45,23 +45,24 @@
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();
diff --git a/src/dev/copy_engine.cc b/src/dev/copy_engine.cc
index 7b17a86a3..809649718 100644
--- a/src/dev/copy_engine.cc
+++ b/src/dev/copy_engine.cc
@@ -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
diff --git a/src/dev/copy_engine.hh b/src/dev/copy_engine.hh
index aa0bf0896..28fc6315c 100644
--- a/src/dev/copy_engine.hh
+++ b/src/dev/copy_engine.hh
@@ -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);
diff --git a/src/dev/io_device.cc b/src/dev/io_device.cc
index f7b8db09d..2937c66b1 100644
--- a/src/dev/io_device.cc
+++ b/src/dev/io_device.cc
@@ -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);
}
diff --git a/src/dev/io_device.hh b/src/dev/io_device.hh
index 400263957..9bb2c3d87 100644
--- a/src/dev/io_device.hh
+++ b/src/dev/io_device.hh
@@ -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;
};
diff --git a/src/dev/pcidev.hh b/src/dev/pcidev.hh
index 07089fd0e..435188342 100644
--- a/src/dev/pcidev.hh
+++ b/src/dev/pcidev.hh
@@ -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);
}
};
diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc
index 3d7454dfd..54824c778 100644
--- a/src/dev/x86/i82094aa.cc
+++ b/src/dev/x86/i82094aa.cc
@@ -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);
}
}
diff --git a/src/dev/x86/i82094aa.hh b/src/dev/x86/i82094aa.hh
index f0837cc27..d3eedea7b 100644
--- a/src/dev/x86/i82094aa.hh
+++ b/src/dev/x86/i82094aa.hh
@@ -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);
diff --git a/src/dev/x86/intdev.cc b/src/dev/x86/intdev.cc
index 0d038b93d..8580ae943 100644
--- a/src/dev/x86/intdev.cc
+++ b/src/dev/x86/intdev.cc
@@ -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 *
diff --git a/src/dev/x86/intdev.hh b/src/dev/x86/intdev.hh
index 5549df637..bbdd98b24 100644
--- a/src/dev/x86/intdev.hh
+++ b/src/dev/x86/intdev.hh
@@ -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)
{
}
diff --git a/src/kern/tru64/tru64_events.cc b/src/kern/tru64/tru64_events.cc
index 357665184..89f2990b9 100644
--- a/src/kern/tru64/tru64_events.cc
+++ b/src/kern/tru64/tru64_events.cc
@@ -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;
diff --git a/src/mem/bridge.cc b/src/mem/bridge.cc
index 0733b6ea8..ebb37e792 100644
--- a/src/mem/bridge.cc
+++ b/src/mem/bridge.cc
@@ -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()
{
diff --git a/src/mem/bridge.hh b/src/mem/bridge.hh
index 3e0040514..e7dbc0a28 100644
--- a/src/mem/bridge.hh
+++ b/src/mem/bridge.hh
@@ -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();
diff --git a/src/mem/bus.cc b/src/mem/bus.cc
index 0c0e3c3e2..c89455f02 100644
--- a/src/mem/bus.cc
+++ b/src/mem/bus.cc
@@ -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;
}
diff --git a/src/mem/bus.hh b/src/mem/bus.hh
index 4ea92308a..e79e9df9e 100644
--- a/src/mem/bus.hh
+++ b/src/mem/bus.hh
@@ -40,6 +40,7 @@
* Authors: Ron Dreslinski
* Ali Saidi
* Andreas Hansson
+ * William Wang
*/
/**
@@ -65,21 +66,85 @@
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();
diff --git a/src/mem/cache/base.cc b/src/mem/cache/base.cc
index a2cb59a76..4ae6376db 100644
--- a/src/mem/cache/base.cc
+++ b/src/mem/cache/base.cc
@@ -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()
diff --git a/src/mem/cache/base.hh b/src/mem/cache/base.hh
index c13d27d42..47cbaf7a0 100644
--- a/src/mem/cache/base.hh
+++ b/src/mem/cache/base.hh
@@ -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
diff --git a/src/mem/cache/builder.cc b/src/mem/cache/builder.cc
index cc206b784..ca8c378fb 100644
--- a/src/mem/cache/builder.cc
+++ b/src/mem/cache/builder.cc
@@ -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
diff --git a/src/mem/cache/cache.hh b/src/mem/cache/cache.hh
index 782749aab..e745529a7 100644
--- a/src/mem/cache/cache.hh
+++ b/src/mem/cache/cache.hh
@@ -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();
/**
diff --git a/src/mem/cache/cache_impl.hh b/src/mem/cache/cache_impl.hh
index 2463071de..3525e0777 100644
--- a/src/mem/cache/cache_impl.hh
+++ b/src/mem/cache/cache_impl.hh
@@ -92,19 +92,6 @@ Cache<TagStore>::regStats()
}
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);
diff --git a/src/mem/fs_translating_port_proxy.cc b/src/mem/fs_translating_port_proxy.cc
index 2e9a0fa00..bf0c076c6 100644
--- a/src/mem/fs_translating_port_proxy.cc
+++ b/src/mem/fs_translating_port_proxy.cc
@@ -58,7 +58,7 @@ FSTranslatingPortProxy::FSTranslatingPortProxy(ThreadContext *tc)
{
}
-FSTranslatingPortProxy::FSTranslatingPortProxy(Port &port)
+FSTranslatingPortProxy::FSTranslatingPortProxy(MasterPort &port)
: PortProxy(port), _tc(NULL)
{
}
diff --git a/src/mem/fs_translating_port_proxy.hh b/src/mem/fs_translating_port_proxy.hh
index 2217a46aa..c022f3d09 100644
--- a/src/mem/fs_translating_port_proxy.hh
+++ b/src/mem/fs_translating_port_proxy.hh
@@ -78,7 +78,7 @@ class FSTranslatingPortProxy : public PortProxy
FSTranslatingPortProxy(ThreadContext* tc);
- FSTranslatingPortProxy(Port &port);
+ FSTranslatingPortProxy(MasterPort &port);
virtual ~FSTranslatingPortProxy();
diff --git a/src/mem/mem_object.cc b/src/mem/mem_object.cc
index 111d3718c..ce8badbe7 100644
--- a/src/mem/mem_object.cc
+++ b/src/mem/mem_object.cc
@@ -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);
+}
diff --git a/src/mem/mem_object.hh b/src/mem/mem_object.hh
index 5865fc935..d8e6bdcb0 100644
--- a/src/mem/mem_object.hh
+++ b/src/mem/mem_object.hh
@@ -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,11 +38,12 @@
* 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__
diff --git a/src/mem/mport.cc b/src/mem/mport.cc
index 2c57030b1..9af394d27 100644
--- a/src/mem/mport.cc
+++ b/src/mem/mport.cc
@@ -43,17 +43,26 @@
#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());
}
}
diff --git a/src/mem/mport.hh b/src/mem/mport.hh
index 7f167c227..664acc559 100644
--- a/src/mem/mport.hh
+++ b/src/mem/mport.hh
@@ -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.
*
@@ -41,15 +53,15 @@
* 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)
diff --git a/src/mem/physical.cc b/src/mem/physical.cc
index f11fbb947..9c953e562 100644
--- a/src/mem/physical.cc
+++ b/src/mem/physical.cc
@@ -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()
{
diff --git a/src/mem/physical.hh b/src/mem/physical.hh
index b447237c7..452ac3fc0 100644
--- a/src/mem/physical.hh
+++ b/src/mem/physical.hh
@@ -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);
diff --git a/src/mem/port.cc b/src/mem/port.cc
index 8edca16f7..3305541c7 100644
--- a/src/mem/port.cc
+++ b/src/mem/port.cc
@@ -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
*/
/**
@@ -33,11 +47,10 @@
* 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;
+}
diff --git a/src/mem/port.hh b/src/mem/port.hh
index fef0c839d..80bb3b085 100644
--- a/src/mem/port.hh
+++ b/src/mem/port.hh
@@ -39,15 +39,12 @@
*
* 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__
diff --git a/src/mem/port_proxy.hh b/src/mem/port_proxy.hh
index b2b27312e..4600cd407 100644
--- a/src/mem/port_proxy.hh
+++ b/src/mem/port_proxy.hh
@@ -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() { }
/**
diff --git a/src/mem/qport.hh b/src/mem/qport.hh
index 39612d22f..6ee71a572 100644
--- a/src/mem/qport.hh
+++ b/src/mem/qport.hh
@@ -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. */
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc
index aca6604c6..1769c51fd 100644
--- a/src/mem/ruby/system/RubyPort.cc
+++ b/src/mem/ruby/system/RubyPort.cc
@@ -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.
@@ -35,26 +47,27 @@
#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);
+ }
}
}
diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh
index bef291d63..d97f6e69e 100644
--- a/src/mem/ruby/system/RubyPort.hh
+++ b/src/mem/ruby/system/RubyPort.hh
@@ -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;
diff --git a/src/mem/se_translating_port_proxy.cc b/src/mem/se_translating_port_proxy.cc
index 2ab130744..72466655c 100644
--- a/src/mem/se_translating_port_proxy.cc
+++ b/src/mem/se_translating_port_proxy.cc
@@ -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)
diff --git a/src/mem/se_translating_port_proxy.hh b/src/mem/se_translating_port_proxy.hh
index 31874e6b8..c0e522611 100644
--- a/src/mem/se_translating_port_proxy.hh
+++ b/src/mem/se_translating_port_proxy.hh
@@ -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;
diff --git a/src/mem/tport.cc b/src/mem/tport.cc
index bf3d59a8f..db2c72bbc 100644
--- a/src/mem/tport.cc
+++ b/src/mem/tport.cc
@@ -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
diff --git a/src/mem/tport.hh b/src/mem/tport.hh
index c77166386..91706fbe9 100644
--- a/src/mem/tport.hh
+++ b/src/mem/tport.hh
@@ -57,7 +57,7 @@
* recvFunctional and recvTiming through recvAtomic. It is always a
* slave port.
*/
-class SimpleTimingPort : public QueuedPort
+class SimpleTimingPort : public QueuedSlavePort
{
protected:
diff --git a/src/python/swig/pyobject.cc b/src/python/swig/pyobject.cc
index 3478310b1..05698e794 100644
--- a/src/python/swig/pyobject.cc
+++ b/src/python/swig/pyobject.cc
@@ -44,24 +44,6 @@
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;
}
diff --git a/src/sim/system.cc b/src/sim/system.cc
index 4601d2d52..2c5d4e44b 100644
--- a/src/sim/system.cc
+++ b/src/sim/system.cc
@@ -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
diff --git a/src/sim/system.hh b/src/sim/system.hh
index dd122161d..d5e45fa0d 100644
--- a/src/sim/system.hh
+++ b/src/sim/system.hh
@@ -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];
diff --git a/src/sim/tlb.hh b/src/sim/tlb.hh
index 253f12072..379cdd343 100644
--- a/src/sim/tlb.hh
+++ b/src/sim/tlb.hh
@@ -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
{