summaryrefslogtreecommitdiff
path: root/src/mem/addr_mapper.cc
diff options
context:
space:
mode:
authorAli Saidi <Ali.Saidi@ARM.com>2012-09-25 11:49:40 -0500
committerAli Saidi <Ali.Saidi@ARM.com>2012-09-25 11:49:40 -0500
commit396600de107220db8c2c8f3951eeb7062ac0e81c (patch)
treec5c1d81488c543d02a3d1547213c21ddd906edc3 /src/mem/addr_mapper.cc
parent0c99d21ad748371e801508a8c3652e07e2e56f93 (diff)
downloadgem5-396600de107220db8c2c8f3951eeb7062ac0e81c.tar.xz
mem: Add a gasket that allows memory ranges to be re-mapped.
For example if DRAM is at two locations and mirrored this patch allows the mirroring to occur.
Diffstat (limited to 'src/mem/addr_mapper.cc')
-rw-r--r--src/mem/addr_mapper.cc295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/mem/addr_mapper.cc b/src/mem/addr_mapper.cc
new file mode 100644
index 000000000..53e8277cc
--- /dev/null
+++ b/src/mem/addr_mapper.cc
@@ -0,0 +1,295 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * 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: Andreas Hansson
+ */
+
+#include "mem/addr_mapper.hh"
+
+AddrMapper::AddrMapper(const AddrMapperParams* p)
+ : MemObject(p),
+ masterPort(name() + "-master", *this),
+ slavePort(name() + "-slave", *this)
+{
+}
+
+void
+AddrMapper::init()
+{
+ if (!slavePort.isConnected() || !masterPort.isConnected())
+ fatal("Address mapper is not connected on both sides.\n");
+
+ if ((slavePort.peerBlockSize() != masterPort.peerBlockSize()) &&
+ slavePort.peerBlockSize() && masterPort.peerBlockSize())
+ fatal("Slave port size %d, master port size %d \n "
+ "don't have the same block size... Not supported.\n",
+ slavePort.peerBlockSize(), masterPort.peerBlockSize());
+}
+
+MasterPort&
+AddrMapper::getMasterPort(const std::string& if_name, int idx)
+{
+ if (if_name == "master") {
+ return masterPort;
+ } else {
+ return MemObject::getMasterPort(if_name, idx);
+ }
+}
+
+SlavePort&
+AddrMapper::getSlavePort(const std::string& if_name, int idx)
+{
+ if (if_name == "slave") {
+ return slavePort;
+ } else {
+ return MemObject::getSlavePort(if_name, idx);
+ }
+}
+
+void
+AddrMapper::recvFunctional(PacketPtr pkt)
+{
+ Addr orig_addr = pkt->getAddr();
+ pkt->setAddr(remapAddr(orig_addr));
+ masterPort.sendFunctional(pkt);
+ pkt->setAddr(orig_addr);
+}
+
+void
+AddrMapper::recvFunctionalSnoop(PacketPtr pkt)
+{
+ Addr orig_addr = pkt->getAddr();
+ pkt->setAddr(remapAddr(orig_addr));
+ slavePort.sendFunctionalSnoop(pkt);
+ pkt->setAddr(orig_addr);
+}
+
+Tick
+AddrMapper::recvAtomic(PacketPtr pkt)
+{
+ Addr orig_addr = pkt->getAddr();
+ pkt->setAddr(remapAddr(orig_addr));
+ Tick ret_tick = masterPort.sendAtomic(pkt);
+ pkt->setAddr(orig_addr);
+ return ret_tick;
+}
+
+Tick
+AddrMapper::recvAtomicSnoop(PacketPtr pkt)
+{
+ Addr orig_addr = pkt->getAddr();
+ pkt->setAddr(remapAddr(orig_addr));
+ Tick ret_tick = slavePort.sendAtomicSnoop(pkt);
+ pkt->setAddr(orig_addr);
+ return ret_tick;
+}
+
+bool
+AddrMapper::recvTimingReq(PacketPtr pkt)
+{
+ Addr orig_addr = pkt->getAddr();
+ bool needsResponse = pkt->needsResponse();
+ bool memInhibitAsserted = pkt->memInhibitAsserted();
+ Packet::SenderState* senderState = pkt->senderState;
+
+ if (needsResponse && !memInhibitAsserted) {
+ pkt->senderState = new AddrMapperSenderState(senderState, orig_addr);
+ }
+
+ pkt->setAddr(remapAddr(orig_addr));
+
+ // Attempt to send the packet (always succeeds for inhibited
+ // packets)
+ bool successful = masterPort.sendTimingReq(pkt);
+
+ // If not successful, restore the sender state
+ if (!successful && needsResponse) {
+ delete pkt->senderState;
+ pkt->senderState = senderState;
+ }
+
+ return successful;
+}
+
+bool
+AddrMapper::recvTimingResp(PacketPtr pkt)
+{
+ AddrMapperSenderState* receivedState =
+ dynamic_cast<AddrMapperSenderState*>(pkt->senderState);
+
+ // Restore initial sender state
+ if (receivedState == NULL)
+ panic("AddrMapper %s got a response without sender state\n",
+ name());
+
+ Addr remapped_addr = pkt->getAddr();
+
+ // Restore the state and address
+ pkt->senderState = receivedState->origSenderState;
+ pkt->setAddr(receivedState->origAddr);
+
+ // Attempt to send the packet
+ bool successful = slavePort.sendTimingResp(pkt);
+
+ // If packet successfully sent, delete the sender state, otherwise
+ // restore state
+ if (successful) {
+ delete receivedState;
+ } else {
+ // Don't delete anything and let the packet look like we did
+ // not touch it
+ pkt->senderState = receivedState;
+ pkt->setAddr(remapped_addr);
+ }
+ return successful;
+}
+
+void
+AddrMapper::recvTimingSnoopReq(PacketPtr pkt)
+{
+ slavePort.sendTimingSnoopReq(pkt);
+}
+
+bool
+AddrMapper::recvTimingSnoopResp(PacketPtr pkt)
+{
+ return masterPort.sendTimingSnoopResp(pkt);
+}
+
+bool
+AddrMapper::isSnooping() const
+{
+ if (slavePort.getMasterPort().isSnooping())
+ fatal("AddrMapper doesn't support remapping of snooping requests\n");
+ return false;
+}
+
+unsigned
+AddrMapper::deviceBlockSizeMaster()
+{
+ return slavePort.peerBlockSize();
+}
+
+unsigned
+AddrMapper::deviceBlockSizeSlave()
+{
+ return masterPort.peerBlockSize();
+}
+
+void
+AddrMapper::recvRetryMaster()
+{
+ slavePort.sendRetry();
+}
+
+void
+AddrMapper::recvRetrySlave()
+{
+ masterPort.sendRetry();
+}
+
+void
+AddrMapper::recvRangeChange()
+{
+ slavePort.sendRangeChange();
+}
+
+RangeAddrMapper::RangeAddrMapper(const RangeAddrMapperParams* p) :
+ AddrMapper(p),
+ originalRanges(p->original_ranges),
+ remappedRanges(p->remapped_ranges)
+{
+ if (originalRanges.size() != remappedRanges.size())
+ fatal("AddrMapper: original and shadowed range list must "
+ "be same size\n");
+
+ for (size_t x = 0; x < originalRanges.size(); x++) {
+ if (originalRanges[x].size() != remappedRanges[x].size())
+ fatal("AddrMapper: original and shadowed range list elements"
+ " aren't all of the same size\n");
+ }
+}
+
+RangeAddrMapper*
+RangeAddrMapperParams::create()
+{
+ return new RangeAddrMapper(this);
+}
+
+Addr
+RangeAddrMapper::remapAddr(Addr addr) const
+{
+ for (int i = 0; i < originalRanges.size(); ++i) {
+ if (originalRanges[i] == addr) {
+ Addr offset = addr - originalRanges[i].start;
+ return offset + remappedRanges[i].start;
+ }
+ }
+
+ return addr;
+}
+
+AddrRangeList
+RangeAddrMapper::getAddrRanges() const
+{
+ AddrRangeList ranges;
+ AddrRangeList actualRanges = masterPort.getSlavePort().getAddrRanges();
+
+ for (AddrRangeIter r = actualRanges.begin(); r != actualRanges.end(); ++r) {
+ AddrRange range = *r;
+
+ for (int j = 0; j < originalRanges.size(); ++j) {
+ if ((range.start < originalRanges[j].start &&
+ range.end >= originalRanges[j].start) ||
+ (range.start < originalRanges[j].end &&
+ range.end >= originalRanges[j].end))
+ fatal("Cannot remap range that intersects the original"
+ " ranges but are not a subset.\n");
+ if (range.start >= originalRanges[j].start &&
+ range.end <= originalRanges[j].end) {
+ // range is a subset
+ Addr offset = range.start - originalRanges[j].start;
+ range.start -= offset;
+ range.end -= offset;
+ }
+ ranges.push_back(range);
+ }
+ }
+
+ return ranges;
+}
+
+