/*
+ * Copyright (c) 2012,2015 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 "mem/packet_impl.hh"
+#include "base/trace.hh"
+#include "mem/mem_object.hh"
#include "mem/port.hh"
+Port::Port(const std::string &_name, MemObject& _owner, PortID _id)
+ : portName(_name), id(_id), owner(_owner)
+{
+}
+
+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)
+ : BaseMasterPort(name, owner, _id), _slavePort(NULL)
+{
+}
+
+MasterPort::~MasterPort()
+{
+}
+
void
-Port::blobHelper(Addr addr, uint8_t *p, int size, Command cmd)
-{
- Request req(false);
- Packet pkt;
- pkt.req = &req;
- pkt.cmd = cmd;
- pkt.dest = Packet::Broadcast;
-
- for (ChunkGenerator gen(addr, size, peerBlockSize());
- !gen.done(); gen.next()) {
- req.setPaddr(pkt.addr = gen.addr());
- req.setSize(pkt.size = gen.size());
- pkt.dataStatic(p);
- sendFunctional(&pkt);
- p += gen.size();
+MasterPort::bind(BaseSlavePort& slave_port)
+{
+ // bind on the level of the base ports
+ _baseSlavePort = &slave_port;
+
+ // 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
-Port::writeBlob(Addr addr, uint8_t *p, int size)
+MasterPort::unbind()
+{
+ if (_slavePort == NULL)
+ panic("Attempting to unbind master port %s that is not connected\n",
+ name());
+ _slavePort->unbind();
+ _slavePort = NULL;
+ _baseSlavePort = NULL;
+}
+
+AddrRangeList
+MasterPort::getAddrRanges() const
+{
+ return _slavePort->getAddrRanges();
+}
+
+Tick
+MasterPort::sendAtomic(PacketPtr pkt)
+{
+ assert(pkt->isRequest());
+ return _slavePort->recvAtomic(pkt);
+}
+
+void
+MasterPort::sendFunctional(PacketPtr pkt)
+{
+ assert(pkt->isRequest());
+ return _slavePort->recvFunctional(pkt);
+}
+
+bool
+MasterPort::sendTimingReq(PacketPtr pkt)
+{
+ assert(pkt->isRequest());
+ return _slavePort->recvTimingReq(pkt);
+}
+
+bool
+MasterPort::sendTimingSnoopResp(PacketPtr pkt)
+{
+ assert(pkt->isResponse());
+ return _slavePort->recvTimingSnoopResp(pkt);
+}
+
+void
+MasterPort::sendRetryResp()
+{
+ _slavePort->recvRespRetry();
+}
+
+void
+MasterPort::printAddr(Addr a)
+{
+ Request req(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, owner, id), _masterPort(NULL)
+{
+}
+
+SlavePort::~SlavePort()
+{
+}
+
+void
+SlavePort::unbind()
{
- blobHelper(addr, p, size, Write);
+ _baseMasterPort = NULL;
+ _masterPort = NULL;
}
void
-Port::readBlob(Addr addr, uint8_t *p, int size)
+SlavePort::bind(MasterPort& master_port)
+{
+ _baseMasterPort = &master_port;
+ _masterPort = &master_port;
+}
+
+Tick
+SlavePort::sendAtomicSnoop(PacketPtr pkt)
{
- blobHelper(addr, p, size, Read);
+ assert(pkt->isRequest());
+ return _masterPort->recvAtomicSnoop(pkt);
}
void
-Port::memsetBlob(Addr addr, uint8_t val, int size)
+SlavePort::sendFunctionalSnoop(PacketPtr pkt)
{
- // quick and dirty...
- uint8_t *buf = new uint8_t[size];
+ assert(pkt->isRequest());
+ return _masterPort->recvFunctionalSnoop(pkt);
+}
- memset(buf, val, size);
- blobHelper(addr, buf, size, Write);
+bool
+SlavePort::sendTimingResp(PacketPtr pkt)
+{
+ assert(pkt->isResponse());
+ return _masterPort->recvTimingResp(pkt);
+}
+
+void
+SlavePort::sendTimingSnoopReq(PacketPtr pkt)
+{
+ assert(pkt->isRequest());
+ _masterPort->recvTimingSnoopReq(pkt);
+}
- delete [] buf;
+void
+SlavePort::sendRetryReq()
+{
+ _masterPort->recvReqRetry();
+}
+
+void
+SlavePort::sendRetrySnoopResp()
+{
+ _masterPort->recvRetrySnoopResp();
}