mem, sim, systemc: Reorganize Port and co.s bind, unbind slightly.

The base Port class can keep track of its peer, and also whether it's
connected. This is partially delegated away from the port subclasses
which still keep track of a cast version of their peer pointer for
their own conveneince, so that it can be used by generic code. Even
with the Port mechanism's new flexibility, each port still has
exactly one peer and is either connected or not based on whether there
is a peer currently.

Change-Id: Id3228617dd1604d196814254a1aadeac5ade7cde
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/20232
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Gabe Black <gabeblack@google.com>
This commit is contained in:
Gabe Black
2019-08-16 15:27:35 -07:00
parent 3126e84db7
commit 2a566b4fa7
6 changed files with 69 additions and 14 deletions

View File

@@ -70,6 +70,22 @@ BaseMasterPort::getSlavePort() const
return *_baseSlavePort;
}
void
BaseMasterPort::bind(Port &peer)
{
_baseSlavePort = dynamic_cast<BaseSlavePort *>(&peer);
fatal_if(!_baseSlavePort, "Attempt to bind port %s to non-master port %s.",
name(), peer.name());
Port::bind(peer);
}
void
BaseMasterPort::unbind()
{
_baseSlavePort = nullptr;
Port::unbind();
}
BaseSlavePort::BaseSlavePort(const std::string &name, PortID _id)
: Port(name, _id), _baseMasterPort(NULL)
{
@@ -89,6 +105,22 @@ BaseSlavePort::getMasterPort() const
return *_baseMasterPort;
}
void
BaseSlavePort::bind(Port &peer)
{
_baseMasterPort = dynamic_cast<BaseMasterPort *>(&peer);
fatal_if(!_baseMasterPort, "Attempt to bind port %s to non-slave port %s.",
name(), peer.name());
Port::bind(peer);
}
void
BaseSlavePort::unbind()
{
_baseMasterPort = nullptr;
Port::unbind();
}
/**
* Master port
*/
@@ -109,12 +141,9 @@ MasterPort::bind(Port &peer)
fatal("Attempt to bind port %s to non-slave port %s.",
name(), peer.name());
}
// bind on the level of the base ports
_baseSlavePort = slave_port;
// master port keeps track of the slave port
_slavePort = slave_port;
_connected = true;
BaseMasterPort::bind(peer);
// slave port also keeps track of master port
_slavePort->slaveBind(*this);
}
@@ -126,9 +155,8 @@ MasterPort::unbind()
panic("Attempting to unbind master port %s that is not connected\n",
name());
_slavePort->slaveUnbind();
_slavePort = NULL;
_connected = false;
_baseSlavePort = NULL;
_slavePort = nullptr;
BaseMasterPort::unbind();
}
AddrRangeList
@@ -166,17 +194,15 @@ SlavePort::~SlavePort()
void
SlavePort::slaveUnbind()
{
_baseMasterPort = NULL;
_masterPort = NULL;
_connected = false;
BaseSlavePort::unbind();
}
void
SlavePort::slaveBind(MasterPort& master_port)
{
_baseMasterPort = &master_port;
_masterPort = &master_port;
_connected = true;
BaseSlavePort::bind(master_port);
}
Tick

View File

@@ -78,6 +78,8 @@ class BaseMasterPort : public Port
public:
BaseSlavePort& getSlavePort() const;
void bind(Port &peer) override;
void unbind() override;
};
/**
@@ -94,6 +96,8 @@ class BaseSlavePort : public Port
public:
BaseMasterPort& getMasterPort() const;
void bind(Port &peer) override;
void unbind() override;
};
/** Forward declaration */

View File

@@ -50,6 +50,6 @@
#include "sim/port.hh"
Port::Port(const std::string& _name, PortID _id) :
portName(_name), id(_id), _connected(false)
portName(_name), id(_id), _peer(nullptr), _connected(false)
{}
Port::~Port() {}

View File

@@ -72,6 +72,13 @@ class Port
* to InvalidPortID in case this port is not part of a vector.
*/
const PortID id;
/**
* A pointer to this port's peer.
*/
Port *_peer;
/**
* Whether this port is currently connected to a peer port.
*/
@@ -92,6 +99,9 @@ class Port
public:
/** Return a reference to this port's peer. */
Port &getPeer() { return *_peer; }
/** Return port name (for DPRINTF). */
const std::string name() const { return portName; }
@@ -99,10 +109,20 @@ class Port
PortID getId() const { return id; }
/** Attach to a peer port. */
virtual void bind(Port &peer) = 0;
virtual void
bind(Port &peer)
{
_peer = &peer;
_connected = true;
}
/** Dettach from a peer port. */
virtual void unbind() = 0;
virtual void
unbind()
{
_peer = nullptr;
_connected = false;
}
/** Is this port currently connected to a peer? */
bool isConnected() const { return _connected; }

View File

@@ -85,6 +85,7 @@ class ScPortWrapper : public ::Port
fatal("Attempt to bind sc_port %s to incompatible port %s.",
name(), peer.name());
}
Port::bind(peer);
}
private:
@@ -123,6 +124,7 @@ class ScInterfaceWrapper : public ::Port
// Don't bind to peer otherwise we may have error messages saying that
// this interface has already be bound since the peer may already did
// that. Just let sc_port or sc_export do the binding
Port::bind(peer);
}
private:
@@ -160,6 +162,7 @@ class ScExportWrapper : public ::Port
name(), peer.name());
port_.bind(iface->interface());
Port::bind(peer);
}
private:

View File

@@ -74,6 +74,7 @@ class TlmInitiatorWrapper : public ::Port
"incompatible port %s.", name(), peer.name());
initiator().bind(target->target());
Port::bind(peer);
}
void
@@ -107,6 +108,7 @@ class TlmTargetWrapper : public ::Port
{
// Ignore attempts to bind a target socket. The initiator will
// handle it.
Port::bind(peer);
}
void