Port: Add protocol-agnostic ports in the port hierarchy

This patch adds an additional level of ports in the inheritance
hierarchy, separating out the protocol-specific and protocl-agnostic
parts. All the functionality related to the binding of ports is now
confined to use BaseMaster/BaseSlavePorts, and all the
protocol-specific parts stay in the Master/SlavePort. In the future it
will be possible to add other protocol-specific implementations.

The functions used in the binding of ports, i.e. getMaster/SlavePort
now use the base classes, and the index parameter is updated to use
the PortID typedef with the symbolic InvalidPortID as the default.
This commit is contained in:
Andreas Hansson 2012-10-15 08:12:35 -04:00
parent 9baa35ba80
commit 2a740aa096
53 changed files with 290 additions and 192 deletions

View file

@ -110,8 +110,8 @@ TableWalker::resume()
}
}
MasterPort&
TableWalker::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort&
TableWalker::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "port") {
return port;

View file

@ -399,8 +399,8 @@ class TableWalker : public MemObject
void completeDrain();
virtual unsigned int drain(Event *de);
virtual void resume();
virtual MasterPort& getMasterPort(const std::string &if_name,
int idx = -1);
virtual BaseMasterPort& getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
Fault walk(RequestPtr req, ThreadContext *tc, uint8_t cid, TLB::Mode mode,
TLB::Translation *_trans, bool timing, bool functional = false);

View file

@ -722,7 +722,7 @@ TLB::translateTiming(RequestPtr req, ThreadContext *tc,
return fault;
}
MasterPort*
BaseMasterPort*
TLB::getMasterPort()
{
return &tableWalker->getMasterPort("port");

View file

@ -224,7 +224,7 @@ class TLB : public BaseTLB
*
* @return A pointer to the walker master port
*/
virtual MasterPort* getMasterPort();
virtual BaseMasterPort* getMasterPort();
// Caching misc register values here.
// Writing to misc registers needs to invalidate them.

View file

@ -238,7 +238,8 @@ class Interrupts : public BasicPioDevice, IntDev
AddrRangeList getAddrRanges() const;
AddrRangeList getIntAddrRange() const;
MasterPort &getMasterPort(const std::string &if_name, int idx = -1)
BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID)
{
if (if_name == "int_master") {
return intMasterPort;
@ -246,7 +247,8 @@ class Interrupts : public BasicPioDevice, IntDev
return BasicPioDevice::getMasterPort(if_name, idx);
}
SlavePort &getSlavePort(const std::string &if_name, int idx = -1)
BaseSlavePort &getSlavePort(const std::string &if_name,
PortID idx = InvalidPortID)
{
if (if_name == "int_slave") {
return intSlavePort;

View file

@ -173,8 +173,8 @@ bool Walker::sendTiming(WalkerState* sendingState, PacketPtr pkt)
return port.sendTimingReq(pkt);
}
MasterPort &
Walker::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
Walker::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "port")
return port;

View file

@ -169,7 +169,8 @@ namespace X86ISA
RequestPtr req, BaseTLB::Mode mode);
Fault startFunctional(ThreadContext * _tc, Addr &addr,
unsigned &logBytes, BaseTLB::Mode mode);
MasterPort &getMasterPort(const std::string &if_name, int idx = -1);
BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
protected:
// The TLB we're supposed to load.

View file

@ -435,7 +435,7 @@ TLB::unserialize(Checkpoint *cp, const std::string &section)
{
}
MasterPort *
BaseMasterPort *
TLB::getMasterPort()
{
return &walker->getMasterPort("port");

View file

@ -147,7 +147,7 @@ namespace X86ISA
*
* @return A pointer to the walker master port
*/
virtual MasterPort *getMasterPort();
virtual BaseMasterPort *getMasterPort();
};
}

View file

@ -296,8 +296,8 @@ BaseCPU::regStats()
threadContexts[0]->regStats(name());
}
MasterPort &
BaseCPU::getMasterPort(const string &if_name, int idx)
BaseMasterPort &
BaseCPU::getMasterPort(const string &if_name, PortID idx)
{
// Get the right port based on name. This applies to all the
// subclasses of the base CPU and relies on their implementation
@ -380,17 +380,17 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
ThreadContext::compare(oldTC, newTC);
*/
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();
BaseMasterPort *old_itb_port = oldTC->getITBPtr()->getMasterPort();
BaseMasterPort *old_dtb_port = oldTC->getDTBPtr()->getMasterPort();
BaseMasterPort *new_itb_port = newTC->getITBPtr()->getMasterPort();
BaseMasterPort *new_dtb_port = newTC->getDTBPtr()->getMasterPort();
// Move over any table walker ports if they exist
if (new_itb_port) {
assert(!new_itb_port->isConnected());
assert(old_itb_port);
assert(old_itb_port->isConnected());
SlavePort &slavePort = old_itb_port->getSlavePort();
BaseSlavePort &slavePort = old_itb_port->getSlavePort();
old_itb_port->unbind();
new_itb_port->bind(slavePort);
}
@ -398,7 +398,7 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
assert(!new_dtb_port->isConnected());
assert(old_dtb_port);
assert(old_dtb_port->isConnected());
SlavePort &slavePort = old_dtb_port->getSlavePort();
BaseSlavePort &slavePort = old_dtb_port->getSlavePort();
old_dtb_port->unbind();
new_dtb_port->bind(slavePort);
}
@ -408,13 +408,13 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
CheckerCPU *oldChecker = oldTC->getCheckerCpuPtr();
CheckerCPU *newChecker = newTC->getCheckerCpuPtr();
if (oldChecker && newChecker) {
MasterPort *old_checker_itb_port =
BaseMasterPort *old_checker_itb_port =
oldChecker->getITBPtr()->getMasterPort();
MasterPort *old_checker_dtb_port =
BaseMasterPort *old_checker_dtb_port =
oldChecker->getDTBPtr()->getMasterPort();
MasterPort *new_checker_itb_port =
BaseMasterPort *new_checker_itb_port =
newChecker->getITBPtr()->getMasterPort();
MasterPort *new_checker_dtb_port =
BaseMasterPort *new_checker_dtb_port =
newChecker->getDTBPtr()->getMasterPort();
// Move over any table walker ports if they exist for checker
@ -422,7 +422,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
assert(!new_checker_itb_port->isConnected());
assert(old_checker_itb_port);
assert(old_checker_itb_port->isConnected());
SlavePort &slavePort = old_checker_itb_port->getSlavePort();
BaseSlavePort &slavePort =
old_checker_itb_port->getSlavePort();
old_checker_itb_port->unbind();
new_checker_itb_port->bind(slavePort);
}
@ -430,7 +431,8 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
assert(!new_checker_dtb_port->isConnected());
assert(old_checker_dtb_port);
assert(old_checker_dtb_port->isConnected());
SlavePort &slavePort = old_checker_dtb_port->getSlavePort();
BaseSlavePort &slavePort =
old_checker_dtb_port->getSlavePort();
old_checker_dtb_port->unbind();
new_checker_dtb_port->bind(slavePort);
}
@ -455,13 +457,13 @@ BaseCPU::takeOverFrom(BaseCPU *oldCPU)
// we are switching to.
assert(!getInstPort().isConnected());
assert(oldCPU->getInstPort().isConnected());
SlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort();
BaseSlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort();
oldCPU->getInstPort().unbind();
getInstPort().bind(inst_peer_port);
assert(!getDataPort().isConnected());
assert(oldCPU->getDataPort().isConnected());
SlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort();
BaseSlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort();
oldCPU->getDataPort().unbind();
getDataPort().bind(data_peer_port);
}

View file

@ -171,7 +171,8 @@ class BaseCPU : public MemObject
*
* @return a reference to the port with the given name
*/
MasterPort &getMasterPort(const std::string &if_name, int idx = -1);
BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
inline void workItemBegin() { numWorkItemsStarted++; }
inline void workItemEnd() { numWorkItemsCompleted++; }

View file

@ -74,8 +74,8 @@ RubyDirectedTester::init()
generator->setDirectedTester(this);
}
MasterPort &
RubyDirectedTester::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
RubyDirectedTester::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name != "cpuPort") {
// pass it along to our super class

View file

@ -68,8 +68,8 @@ class RubyDirectedTester : public MemObject
RubyDirectedTester(const Params *p);
~RubyDirectedTester();
virtual MasterPort &getMasterPort(const std::string &if_name,
int idx = -1);
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
MasterPort* getCpuPort(int idx);

View file

@ -131,8 +131,8 @@ MemTest::MemTest(const Params *p)
dmaOutstanding = false;
}
MasterPort &
MemTest::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
MemTest::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "functional")
return funcPort;

View file

@ -59,8 +59,8 @@ class MemTest : public MemObject
// main simulation loop (one cycle)
void tick();
virtual MasterPort &getMasterPort(const std::string &if_name,
int idx = -1);
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
/**
* Print state of address in memory system via PrintReq (for

View file

@ -97,8 +97,8 @@ NetworkTest::NetworkTest(const Params *p)
name(), id);
}
MasterPort &
NetworkTest::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
NetworkTest::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "test")
return cachePort;

View file

@ -54,8 +54,8 @@ class NetworkTest : public MemObject
// main simulation loop (one cycle)
void tick();
virtual MasterPort &getMasterPort(const std::string &if_name,
int idx = -1);
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
/**
* Print state of address in memory system via PrintReq (for

View file

@ -111,8 +111,8 @@ RubyTester::init()
m_checkTable_ptr = new CheckTable(m_num_writers, m_num_readers, this);
}
MasterPort &
RubyTester::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
RubyTester::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name != "cpuInstPort" && if_name != "cpuDataPort") {
// pass it along to our super class
@ -134,7 +134,7 @@ RubyTester::getMasterPort(const std::string &if_name, int idx)
// index
//
int read_idx = idx + m_num_inst_ports;
if (read_idx >= static_cast<int>(readPorts.size())) {
if (read_idx >= static_cast<PortID>(readPorts.size())) {
panic("RubyTester::getMasterPort: unknown data port idx %d\n",
idx);
}

View file

@ -89,8 +89,8 @@ class RubyTester : public MemObject
RubyTester(const Params *p);
~RubyTester();
virtual MasterPort &getMasterPort(const std::string &if_name,
int idx = -1);
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
bool isInstReadableCpuPort(int idx);

View file

@ -66,8 +66,8 @@ TrafficGenParams::create()
return new TrafficGen(this);
}
MasterPort&
TrafficGen::getMasterPort(const string& if_name, int idx)
BaseMasterPort&
TrafficGen::getMasterPort(const string& if_name, PortID idx)
{
if (if_name == "port") {
return port;

View file

@ -597,8 +597,8 @@ class TrafficGen : public MemObject
~TrafficGen() {}
virtual MasterPort& getMasterPort(const std::string &if_name,
int idx = InvalidPortID);
virtual BaseMasterPort& getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
void init();

View file

@ -110,8 +110,8 @@ CopyEngine::CopyEngineChannel::~CopyEngineChannel()
delete [] copyBuffer;
}
MasterPort &
CopyEngine::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
CopyEngine::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name != "dma") {
// pass it along to our super class
@ -126,7 +126,7 @@ CopyEngine::getMasterPort(const std::string &if_name, int idx)
}
MasterPort &
BaseMasterPort &
CopyEngine::CopyEngineChannel::getMasterPort()
{
return cePort;

View file

@ -94,7 +94,7 @@ class CopyEngine : public PciDev
public:
CopyEngineChannel(CopyEngine *_ce, int cid);
virtual ~CopyEngineChannel();
MasterPort &getMasterPort();
BaseMasterPort &getMasterPort();
std::string name() { assert(ce); return ce->name() + csprintf("-chan%d", channelId); }
virtual Tick read(PacketPtr pkt)
@ -196,8 +196,8 @@ class CopyEngine : public PciDev
void regStats();
virtual MasterPort &getMasterPort(const std::string &if_name,
int idx = -1);
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
virtual Tick read(PacketPtr pkt);
virtual Tick write(PacketPtr pkt);

View file

@ -254,8 +254,8 @@ DmaPort::sendDma()
panic("Unknown memory mode.");
}
MasterPort &
DmaDevice::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
DmaDevice::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "dma") {
return dmaPort;

View file

@ -156,8 +156,8 @@ class DmaDevice : public PioDevice
unsigned cacheBlockSize() const { return dmaPort.cacheBlockSize(); }
virtual MasterPort &getMasterPort(const std::string &if_name,
int idx = -1);
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
friend class DmaPort;
};

View file

@ -79,8 +79,8 @@ PioDevice::init()
pioPort.sendRangeChange();
}
SlavePort &
PioDevice::getSlavePort(const std::string &if_name, int idx)
BaseSlavePort &
PioDevice::getSlavePort(const std::string &if_name, PortID idx)
{
if (if_name == "pio") {
return pioPort;

View file

@ -127,7 +127,8 @@ class PioDevice : public MemObject
virtual unsigned int drain(Event *de);
virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1);
virtual BaseSlavePort &getSlavePort(const std::string &if_name,
PortID idx = InvalidPortID);
friend class PioPort;

View file

@ -218,7 +218,8 @@ class PciDev : public DmaDevice
virtual unsigned int drain(Event *de);
virtual SlavePort &getSlavePort(const std::string &if_name, int idx = -1)
virtual BaseSlavePort &getSlavePort(const std::string &if_name,
PortID idx = InvalidPortID)
{
if (if_name == "config") {
return configPort;

View file

@ -120,7 +120,8 @@ class I82094AA : public PioDevice, public IntDev
void writeReg(uint8_t offset, uint32_t value);
uint32_t readReg(uint8_t offset);
MasterPort &getMasterPort(const std::string &if_name, int idx = -1)
BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID)
{
if (if_name == "int_master")
return intMasterPort;

View file

@ -59,8 +59,8 @@ AddrMapper::init()
slavePort.peerBlockSize(), masterPort.peerBlockSize());
}
MasterPort&
AddrMapper::getMasterPort(const std::string& if_name, int idx)
BaseMasterPort&
AddrMapper::getMasterPort(const std::string& if_name, PortID idx)
{
if (if_name == "master") {
return masterPort;
@ -69,8 +69,8 @@ AddrMapper::getMasterPort(const std::string& if_name, int idx)
}
}
SlavePort&
AddrMapper::getSlavePort(const std::string& if_name, int idx)
BaseSlavePort&
AddrMapper::getSlavePort(const std::string& if_name, PortID idx)
{
if (if_name == "slave") {
return slavePort;
@ -192,7 +192,7 @@ AddrMapper::recvTimingSnoopResp(PacketPtr pkt)
bool
AddrMapper::isSnooping() const
{
if (slavePort.getMasterPort().isSnooping())
if (slavePort.isSnooping())
fatal("AddrMapper doesn't support remapping of snooping requests\n");
return false;
}
@ -266,7 +266,7 @@ AddrRangeList
RangeAddrMapper::getAddrRanges() const
{
AddrRangeList ranges;
AddrRangeList actualRanges = masterPort.getSlavePort().getAddrRanges();
AddrRangeList actualRanges = masterPort.getAddrRanges();
for (AddrRangeIter r = actualRanges.begin(); r != actualRanges.end(); ++r) {
AddrRange range = *r;

View file

@ -62,11 +62,11 @@ class AddrMapper : public MemObject
virtual ~AddrMapper() { }
virtual MasterPort& getMasterPort(const std::string& if_name,
int idx = -1);
virtual BaseMasterPort& getMasterPort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual SlavePort& getSlavePort(const std::string& if_name,
int idx = -1);
virtual BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual void init();

View file

@ -83,8 +83,8 @@ Bridge::Bridge(Params *p)
{
}
MasterPort&
Bridge::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort&
Bridge::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "master")
return masterPort;
@ -93,8 +93,8 @@ Bridge::getMasterPort(const std::string &if_name, int idx)
return MemObject::getMasterPort(if_name, idx);
}
SlavePort&
Bridge::getSlavePort(const std::string &if_name, int idx)
BaseSlavePort&
Bridge::getSlavePort(const std::string &if_name, PortID idx)
{
if (if_name == "slave")
return slavePort;

View file

@ -338,9 +338,10 @@ class Bridge : public MemObject
public:
virtual MasterPort& getMasterPort(const std::string& if_name,
int idx = -1);
virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
virtual BaseMasterPort& getMasterPort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual void init();

View file

@ -105,8 +105,8 @@ BaseBus::init()
warn_once("Block size is neither 16, 32, 64 or 128 bytes.\n");
}
MasterPort &
BaseBus::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
BaseBus::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "master" && idx < masterPorts.size()) {
// the master port index translates directly to the vector position
@ -118,8 +118,8 @@ BaseBus::getMasterPort(const std::string &if_name, int idx)
}
}
SlavePort &
BaseBus::getSlavePort(const std::string &if_name, int idx)
BaseSlavePort &
BaseBus::getSlavePort(const std::string &if_name, PortID idx)
{
if (if_name == "slave" && idx < slavePorts.size()) {
// the slave port index translates directly to the vector position

View file

@ -361,8 +361,10 @@ class BaseBus : public MemObject
virtual void init();
/** A function used to return the port associated with this bus object. */
virtual MasterPort& getMasterPort(const std::string& if_name, int idx = -1);
virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
BaseMasterPort& getMasterPort(const std::string& if_name,
PortID idx = InvalidPortID);
BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual unsigned int drain(Event *de) = 0;

View file

@ -118,8 +118,8 @@ BaseCache::init()
cpuSidePort->sendRangeChange();
}
MasterPort &
BaseCache::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
BaseCache::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "mem_side") {
return *memSidePort;
@ -128,8 +128,8 @@ BaseCache::getMasterPort(const std::string &if_name, int idx)
}
}
SlavePort &
BaseCache::getSlavePort(const std::string &if_name, int idx)
BaseSlavePort &
BaseCache::getSlavePort(const std::string &if_name, PortID idx)
{
if (if_name == "cpu_side") {
return *cpuSidePort;

View file

@ -430,8 +430,10 @@ 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);
virtual BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
virtual BaseSlavePort &getSlavePort(const std::string &if_name,
PortID idx = InvalidPortID);
/**
* Query block size of a cache.

View file

@ -74,8 +74,8 @@ CommMonitor::init()
fatal("Communication monitor is not connected on both sides.\n");
}
MasterPort&
CommMonitor::getMasterPort(const std::string& if_name, int idx)
BaseMasterPort&
CommMonitor::getMasterPort(const std::string& if_name, PortID idx)
{
if (if_name == "master") {
return masterPort;
@ -84,8 +84,8 @@ CommMonitor::getMasterPort(const std::string& if_name, int idx)
}
}
SlavePort&
CommMonitor::getSlavePort(const std::string& if_name, int idx)
BaseSlavePort&
CommMonitor::getSlavePort(const std::string& if_name, PortID idx)
{
if (if_name == "slave") {
return slavePort;

View file

@ -77,11 +77,11 @@ class CommMonitor : public MemObject
/** Destructor */
~CommMonitor() { }
virtual MasterPort& getMasterPort(const std::string& if_name,
int idx = -1);
virtual BaseMasterPort& getMasterPort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual SlavePort& getSlavePort(const std::string& if_name,
int idx = -1);
virtual BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual void init();

View file

@ -48,14 +48,14 @@ MemObject::MemObject(const Params *params)
{
}
MasterPort&
MemObject::getMasterPort(const std::string& if_name, int idx)
BaseMasterPort&
MemObject::getMasterPort(const std::string& if_name, PortID 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)
BaseSlavePort&
MemObject::getSlavePort(const std::string& if_name, PortID idx)
{
fatal("%s does not have any slave port named %s\n", name(), if_name);
}

View file

@ -67,26 +67,30 @@ class MemObject : public ClockedObject
MemObject(const Params *params);
/**
* Get a master port with a given name and index.
* Get a master port with a given name and index. This is used at
* binding time and returns a reference to a protocol-agnostic
* base master port.
*
* @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);
virtual BaseMasterPort& getMasterPort(const std::string& if_name,
PortID idx = InvalidPortID);
/**
* Get a slave port with a given name and index.
* Get a slave port with a given name and index. This is used at
* binding time and returns a reference to a protocol-agnostic
* base master port.
*
* @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);
virtual BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
};
#endif //__MEM_MEM_OBJECT_HH__

View file

@ -59,11 +59,63 @@ Port::~Port()
{
}
BaseMasterPort::BaseMasterPort(const std::string& name, MemObject* owner,
PortID _id)
: Port(name, *owner, _id), _baseSlavePort(NULL)
{
}
BaseMasterPort::~BaseMasterPort()
{
}
BaseSlavePort&
BaseMasterPort::getSlavePort() const
{
if(_baseSlavePort == NULL)
panic("Cannot getSlavePort on master port %s that is not connected\n",
name());
return *_baseSlavePort;
}
bool
BaseMasterPort::isConnected() const
{
return _baseSlavePort != NULL;
}
BaseSlavePort::BaseSlavePort(const std::string& name, MemObject* owner,
PortID _id)
: Port(name, *owner, _id), _baseMasterPort(NULL)
{
}
BaseSlavePort::~BaseSlavePort()
{
}
BaseMasterPort&
BaseSlavePort::getMasterPort() const
{
if(_baseMasterPort == NULL)
panic("Cannot getMasterPort on slave port %s that is not connected\n",
name());
return *_baseMasterPort;
}
bool
BaseSlavePort::isConnected() const
{
return _baseMasterPort != NULL;
}
/**
* Master port
*/
MasterPort::MasterPort(const std::string& name, MemObject* owner, PortID _id)
: Port(name, *owner, _id), _slavePort(NULL)
: BaseMasterPort(name, owner, _id), _slavePort(NULL)
{
}
@ -71,14 +123,25 @@ MasterPort::~MasterPort()
{
}
SlavePort&
MasterPort::getSlavePort() const
void
MasterPort::bind(BaseSlavePort& slave_port)
{
if(_slavePort == NULL)
panic("Cannot getSlavePort on master port %s that is not connected\n",
name());
// bind on the level of the base ports
_baseSlavePort = &slave_port;
return *_slavePort;
// also attempt to base the slave to the appropriate type
SlavePort* cast_slave_port = dynamic_cast<SlavePort*>(&slave_port);
// if this port is compatible, then proceed with the binding
if (cast_slave_port != NULL) {
// master port keeps track of the slave port
_slavePort = cast_slave_port;
// slave port also keeps track of master port
_slavePort->bind(*this);
} else {
fatal("Master port %s cannot bind to %s\n", name(),
slave_port.name());
}
}
void
@ -89,26 +152,7 @@ MasterPort::unbind()
name());
_slavePort->unbind();
_slavePort = NULL;
}
void
MasterPort::bind(SlavePort& slave_port)
{
if (_slavePort != NULL)
panic("Attempting to bind master port %s that is already connected\n",
name());
// master port keeps track of the slave port
_slavePort = &slave_port;
// slave port also keeps track of master port
_slavePort->bind(*this);
}
bool
MasterPort::isConnected() const
{
return _slavePort != NULL;
_baseSlavePort = NULL;
}
unsigned
@ -172,7 +216,7 @@ MasterPort::printAddr(Addr a)
* Slave port
*/
SlavePort::SlavePort(const std::string& name, MemObject* owner, PortID id)
: Port(name, *owner, id), _masterPort(NULL)
: BaseSlavePort(name, owner, id), _masterPort(NULL)
{
}
@ -183,37 +227,23 @@ SlavePort::~SlavePort()
void
SlavePort::unbind()
{
_baseMasterPort = NULL;
_masterPort = NULL;
}
void
SlavePort::bind(MasterPort& master_port)
{
_baseMasterPort = &master_port;
_masterPort = &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;
}
Tick
SlavePort::sendAtomicSnoop(PacketPtr pkt)
{

View file

@ -116,16 +116,68 @@ class Port
};
/** Forward declaration */
class BaseSlavePort;
/**
* A BaseMasterPort is a protocol-agnostic master port, responsible
* only for the structural connection to a slave port. The final
* master port that inherits from the base class must override the
* bind member function for the specific slave port class.
*/
class BaseMasterPort : public Port
{
protected:
BaseSlavePort* _baseSlavePort;
BaseMasterPort(const std::string& name, MemObject* owner,
PortID id = InvalidPortID);
virtual ~BaseMasterPort();
public:
virtual void bind(BaseSlavePort& slave_port) = 0;
virtual void unbind() = 0;
BaseSlavePort& getSlavePort() const;
bool isConnected() const;
};
/**
* A BaseSlavePort is a protocol-agnostic slave port, responsible
* only for the structural connection to a master port.
*/
class BaseSlavePort : public Port
{
protected:
BaseMasterPort* _baseMasterPort;
BaseSlavePort(const std::string& name, MemObject* owner,
PortID id = InvalidPortID);
virtual ~BaseSlavePort();
public:
BaseMasterPort& getMasterPort() const;
bool isConnected() const;
};
/** 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.
* A MasterPort is a specialisation of a BaseMasterPort, which
* implements the default protocol for the three different level of
* transport functions. In addition to the basic functionality of
* sending packets, it also has functions to receive range changes or
* determine if the port is snooping or not.
*/
class MasterPort : public Port
class MasterPort : public BaseMasterPort
{
friend class SlavePort;
@ -144,16 +196,13 @@ class MasterPort : public Port
* Bind this master port to a slave port. This also does the
* mirror action and binds the slave port to the master port.
*/
void bind(SlavePort& slave_port);
void bind(BaseSlavePort& slave_port);
/**
* Unbind this master port and the associated slave port.
*/
void unbind();
SlavePort& getSlavePort() const;
bool isConnected() const;
/**
* Send an atomic request packet, where the data is moved and the
* state is updated in zero time, without interleaving with other
@ -292,7 +341,7 @@ class MasterPort : public Port
* 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
class SlavePort : public BaseSlavePort
{
friend class MasterPort;
@ -307,9 +356,6 @@ class SlavePort : public Port
PortID id = InvalidPortID);
virtual ~SlavePort();
MasterPort& getMasterPort() const;
bool isConnected() const;
/**
* Send an atomic snoop request packet, where the data is moved
* and the state is updated in zero time, without interleaving

View file

@ -78,8 +78,8 @@ RubyPort::init()
m_mandatory_q_ptr = m_controller->getMandatoryQueue();
}
MasterPort &
RubyPort::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort &
RubyPort::getMasterPort(const std::string &if_name, PortID idx)
{
if (if_name == "pio_port") {
return pio_port;
@ -91,7 +91,7 @@ RubyPort::getMasterPort(const std::string &if_name, int idx)
// pass it along to our super class
return MemObject::getMasterPort(if_name, idx);
} else {
if (idx >= static_cast<int>(master_ports.size())) {
if (idx >= static_cast<PortID>(master_ports.size())) {
panic("RubyPort::getMasterPort: unknown index %d\n", idx);
}
@ -99,8 +99,8 @@ RubyPort::getMasterPort(const std::string &if_name, int idx)
}
}
SlavePort &
RubyPort::getSlavePort(const std::string &if_name, int idx)
BaseSlavePort &
RubyPort::getSlavePort(const std::string &if_name, PortID idx)
{
// used by the CPUs to connect the caches to the interconnect, and
// for the x86 case also the interrupt master
@ -108,7 +108,7 @@ RubyPort::getSlavePort(const std::string &if_name, int idx)
// pass it along to our super class
return MemObject::getSlavePort(if_name, idx);
} else {
if (idx >= static_cast<int>(slave_ports.size())) {
if (idx >= static_cast<PortID>(slave_ports.size())) {
panic("RubyPort::getSlavePort: unknown index %d\n", idx);
}

View file

@ -126,8 +126,10 @@ class RubyPort : public MemObject
void init();
MasterPort &getMasterPort(const std::string &if_name, int idx);
SlavePort &getSlavePort(const std::string &if_name, int idx);
BaseMasterPort &getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
BaseSlavePort &getSlavePort(const std::string &if_name,
PortID idx = InvalidPortID);
virtual RequestStatus makeRequest(PacketPtr pkt) = 0;
virtual int outstandingCount() const = 0;

View file

@ -1186,8 +1186,8 @@ SimpleDRAM::recvFunctional(PacketPtr pkt)
functionalAccess(pkt);
}
SlavePort&
SimpleDRAM::getSlavePort(const string &if_name, int idx)
BaseSlavePort&
SimpleDRAM::getSlavePort(const string &if_name, PortID idx)
{
if (if_name != "port") {
return MemObject::getSlavePort(if_name, idx);

View file

@ -461,8 +461,8 @@ class SimpleDRAM : public AbstractMemory
unsigned int drain(Event* de);
virtual SlavePort& getSlavePort(const std::string& if_name,
int idx = InvalidPortID);
virtual BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual void init();
virtual void startup();

View file

@ -165,8 +165,8 @@ SimpleMemory::release()
}
}
SlavePort &
SimpleMemory::getSlavePort(const std::string &if_name, int idx)
BaseSlavePort &
SimpleMemory::getSlavePort(const std::string &if_name, PortID idx)
{
if (if_name != "port") {
return MemObject::getSlavePort(if_name, idx);

View file

@ -125,7 +125,8 @@ class SimpleMemory : public AbstractMemory
unsigned int drain(Event* de);
virtual SlavePort& getSlavePort(const std::string& if_name, int idx = -1);
virtual BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
virtual void init();
protected:

View file

@ -102,8 +102,8 @@ connectPorts(SimObject *o1, const std::string &name1, int i1,
}
// generic master/slave port connection
MasterPort& masterPort = mo1->getMasterPort(name1, i1);
SlavePort& slavePort = mo2->getSlavePort(name2, i2);
BaseMasterPort& masterPort = mo1->getMasterPort(name1, i1);
BaseSlavePort& slavePort = mo2->getSlavePort(name2, i2);
masterPort.bind(slavePort);

View file

@ -171,8 +171,8 @@ System::init()
panic("System port on %s is not connected.\n", name());
}
MasterPort&
System::getMasterPort(const std::string &if_name, int idx)
BaseMasterPort&
System::getMasterPort(const std::string &if_name, PortID idx)
{
// no need to distinguish at the moment (besides checking)
return _systemPort;

View file

@ -117,7 +117,8 @@ class System : public MemObject
/**
* Additional function to return the Port of a memory object.
*/
MasterPort& getMasterPort(const std::string &if_name, int idx = -1);
BaseMasterPort& getMasterPort(const std::string &if_name,
PortID idx = InvalidPortID);
static const char *MemoryModeStrings[3];

View file

@ -49,7 +49,7 @@
#include "sim/sim_object.hh"
class ThreadContext;
class MasterPort;
class BaseMasterPort;
class BaseTLB : public SimObject
{
@ -73,7 +73,7 @@ class BaseTLB : public SimObject
*
* @return A pointer to the walker master port or NULL if not present
*/
virtual MasterPort* getMasterPort() { return NULL; }
virtual BaseMasterPort* getMasterPort() { return NULL; }
class Translation
{