mem-cache: Add match functions to QueueEntry
[gem5.git] / src / mem / port.cc
index 8edca16f74f4f8ae0612c860c6bb0271f5f85885..933e98243947d0798d12ae58516979670314d40a 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012,2015,2017 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Steve Reinhardt
+ *          Andreas Hansson
+ *          William Wang
  */
 
 /**
  * @file
  * Port object definitions.
  */
+#include "mem/port.hh"
+
 #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)
-    : portName(_name), peer(NULL), owner(_owner)
+BaseMasterPort::BaseMasterPort(const std::string &name, PortID _id)
+    : Port(name, _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;
+}
+
+BaseSlavePort::BaseSlavePort(const std::string &name, PortID _id)
+    : Port(name, _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;
+}
+
+/**
+ * Master port
+ */
+MasterPort::MasterPort(const std::string& name, MemObject* _owner, PortID _id)
+    : BaseMasterPort(name, _id), _slavePort(NULL), owner(*_owner)
 {
 }
 
-Port::~Port()
+MasterPort::~MasterPort()
 {
 }
 
 void
-Port::setPeer(Port *port)
+MasterPort::bind(Port &peer)
 {
-    DPRINTF(Config, "setting peer to %s\n", port->name());
+    auto *slave_port = dynamic_cast<SlavePort *>(&peer);
+    if (!slave_port) {
+        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;
 
-    peer = port;
+    // master port keeps track of the slave port
+    _slavePort = slave_port;
+    _connected = true;
+    // slave port also keeps track of master port
+    _slavePort->slaveBind(*this);
 }
 
 void
-Port::setOwner(MemObject *_owner)
+MasterPort::unbind()
+{
+    if (_slavePort == NULL)
+        panic("Attempting to unbind master port %s that is not connected\n",
+              name());
+    _slavePort->slaveUnbind();
+    _slavePort = NULL;
+    _connected = false;
+    _baseSlavePort = NULL;
+}
+
+AddrRangeList
+MasterPort::getAddrRanges() const
+{
+    return _slavePort->getAddrRanges();
+}
+
+Tick
+MasterPort::sendAtomic(PacketPtr pkt)
+{
+    assert(pkt->isRequest());
+    return _slavePort->recvAtomic(pkt);
+}
+
+Tick
+MasterPort::sendAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
 {
-    owner = _owner;
+    assert(pkt->isRequest());
+    return _slavePort->recvAtomicBackdoor(pkt, backdoor);
 }
 
 void
-Port::printAddr(Addr a)
+MasterPort::sendFunctional(PacketPtr pkt)
 {
-    Request req(a, 1, 0, Request::funcMasterId);
-    Packet pkt(&req, MemCmd::PrintReq, Packet::Broadcast);
+    assert(pkt->isRequest());
+    return _slavePort->recvFunctional(pkt);
+}
+
+bool
+MasterPort::sendTimingReq(PacketPtr pkt)
+{
+    assert(pkt->isRequest());
+    return _slavePort->recvTimingReq(pkt);
+}
+
+bool
+MasterPort::tryTiming(PacketPtr pkt) const
+{
+  assert(pkt->isRequest());
+  return _slavePort->tryTiming(pkt);
+}
+
+bool
+MasterPort::sendTimingSnoopResp(PacketPtr pkt)
+{
+    assert(pkt->isResponse());
+    return _slavePort->recvTimingSnoopResp(pkt);
+}
+
+void
+MasterPort::sendRetryResp()
+{
+    _slavePort->recvRespRetry();
+}
+
+void
+MasterPort::printAddr(Addr a)
+{
+    auto req = std::make_shared<Request>(
+        a, 1, 0, Request::funcMasterId);
+
+    Packet pkt(req, MemCmd::PrintReq);
     Packet::PrintReqState prs(std::cerr);
     pkt.senderState = &prs;
 
     sendFunctional(&pkt);
 }
+
+/**
+ * Slave port
+ */
+SlavePort::SlavePort(const std::string& name, MemObject* _owner, PortID id)
+    : BaseSlavePort(name, id), _masterPort(NULL), defaultBackdoorWarned(false),
+    owner(*_owner)
+{
+}
+
+SlavePort::~SlavePort()
+{
+}
+
+void
+SlavePort::slaveUnbind()
+{
+    _baseMasterPort = NULL;
+    _masterPort = NULL;
+    _connected = false;
+}
+
+void
+SlavePort::slaveBind(MasterPort& master_port)
+{
+    _baseMasterPort = &master_port;
+    _masterPort = &master_port;
+    _connected = true;
+}
+
+Tick
+SlavePort::recvAtomicBackdoor(PacketPtr pkt, MemBackdoorPtr &backdoor)
+{
+    if (!defaultBackdoorWarned) {
+        warn("Port %s doesn't support requesting a back door.", name());
+        defaultBackdoorWarned = true;
+    }
+    return recvAtomic(pkt);
+}
+
+Tick
+SlavePort::sendAtomicSnoop(PacketPtr pkt)
+{
+    assert(pkt->isRequest());
+    return _masterPort->recvAtomicSnoop(pkt);
+}
+
+void
+SlavePort::sendFunctionalSnoop(PacketPtr pkt)
+{
+    assert(pkt->isRequest());
+    return _masterPort->recvFunctionalSnoop(pkt);
+}
+
+bool
+SlavePort::sendTimingResp(PacketPtr pkt)
+{
+    assert(pkt->isResponse());
+    return _masterPort->recvTimingResp(pkt);
+}
+
+void
+SlavePort::sendTimingSnoopReq(PacketPtr pkt)
+{
+    assert(pkt->isRequest());
+    _masterPort->recvTimingSnoopReq(pkt);
+}
+
+void
+SlavePort::sendRetryReq()
+{
+    _masterPort->recvReqRetry();
+}
+
+void
+SlavePort::sendRetrySnoopResp()
+{
+    _masterPort->recvRetrySnoopResp();
+}