MEM: Introduce the master/slave port sub-classes in C++
[gem5.git] / src / mem / port.cc
index 651cb739a28e860ea89a46e8045a00f8200849eb..3305541c72b5e2b00698f6b859e6c917dd768d68 100644 (file)
@@ -1,4 +1,16 @@
 /*
+ * Copyright (c) 2012 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
  * Copyright (c) 2002-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Steve Reinhardt
+ *          Andreas Hansson
+ *          William Wang
  */
 
 /**
- * @file Port object definitions.
+ * @file
+ * Port object definitions.
  */
-
-#include "base/chunk_generator.hh"
 #include "base/trace.hh"
-#include "mem/packet_impl.hh"
+#include "mem/mem_object.hh"
 #include "mem/port.hh"
 
-void
-Port::setPeer(Port *port)
+Port::Port(const std::string &_name, MemObject& _owner)
+    : portName(_name), peer(NULL), owner(_owner)
 {
-    DPRINTF(Config, "setting peer to %s\n", port->name());
-    peer = port;
 }
 
-void
-Port::blobHelper(Addr addr, uint8_t *p, int size, Packet::Command cmd)
+Port::~Port()
 {
-    Request req(false);
-    Packet pkt(&req, cmd, Packet::Broadcast);
-
-    for (ChunkGenerator gen(addr, size, peerBlockSize());
-         !gen.done(); gen.next()) {
-        req.setPaddr(gen.addr());
-        req.setSize(gen.size());
-        pkt.reinitFromRequest();
-        pkt.dataStatic(p);
-        sendFunctional(&pkt);
-        p += gen.size();
-    }
 }
 
-void
-Port::writeBlob(Addr addr, uint8_t *p, int size)
+/**
+ * Master port
+ */
+MasterPort::MasterPort(const std::string& name, MemObject* owner)
+    : Port(name, *owner), _slavePort(NULL)
+{
+}
+
+MasterPort::~MasterPort()
+{
+}
+
+SlavePort&
+MasterPort::getSlavePort() const
 {
-    blobHelper(addr, p, size, Packet::WriteReq);
+    if(_slavePort == NULL)
+        panic("Cannot getSlavePort on master port %s that is not connected\n",
+              name());
+
+    return *_slavePort;
 }
 
 void
-Port::readBlob(Addr addr, uint8_t *p, int size)
+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);
+    Packet::PrintReqState prs(std::cerr);
+    pkt.senderState = &prs;
+
+    sendFunctional(&pkt);
+}
+
+/**
+ * Slave port
+ */
+SlavePort::SlavePort(const std::string& name, MemObject* owner)
+    : Port(name, *owner), _masterPort(NULL)
+{
+}
+
+SlavePort::~SlavePort()
 {
-    blobHelper(addr, p, size, Packet::ReadReq);
 }
 
 void
-Port::memsetBlob(Addr addr, uint8_t val, int size)
+SlavePort::bind(MasterPort& master_port)
+{
+    _masterPort = &master_port;
+    peer = &master_port;
+}
+
+MasterPort&
+SlavePort::getMasterPort() const
 {
-    // quick and dirty...
-    uint8_t *buf = new uint8_t[size];
+    if (_masterPort == NULL)
+        panic("Cannot getMasterPort on slave port %s that is not connected\n",
+              name());
 
-    memset(buf, val, size);
-    blobHelper(addr, buf, size, Packet::WriteReq);
+    return *_masterPort;
+}
 
-    delete [] buf;
+unsigned
+SlavePort::peerBlockSize() const
+{
+    return _masterPort->deviceBlockSize();
+}
+
+bool
+SlavePort::isConnected() const
+{
+    return _masterPort != NULL;
 }