addr_mapper.cc revision 9406
14120Sgblack@eecs.umich.edu/*
24120Sgblack@eecs.umich.edu * Copyright (c) 2012 ARM Limited
34120Sgblack@eecs.umich.edu * All rights reserved
44120Sgblack@eecs.umich.edu *
57087Snate@binkert.org * The license below extends only to copyright in the software and shall
67087Snate@binkert.org * not be construed as granting a license to any other intellectual
77087Snate@binkert.org * property including but not limited to intellectual property relating
87087Snate@binkert.org * to a hardware implementation of the functionality of the software
97087Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated
117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
127087Snate@binkert.org * modified or unmodified, in source code or in binary form.
134120Sgblack@eecs.umich.edu *
147087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
157087Snate@binkert.org * modification, are permitted provided that the following conditions are
167087Snate@binkert.org * met: redistributions of source code must retain the above copyright
177087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
187087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
197087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
207087Snate@binkert.org * documentation and/or other materials provided with the distribution;
217087Snate@binkert.org * neither the name of the copyright holders nor the names of its
224120Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
237087Snate@binkert.org * this software without specific prior written permission.
244120Sgblack@eecs.umich.edu *
254120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
264120Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
274120Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
284120Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
294120Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
304120Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
314120Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
324120Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
334120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
344120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
354120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
364120Sgblack@eecs.umich.edu *
374120Sgblack@eecs.umich.edu * Authors: Andreas Hansson
384120Sgblack@eecs.umich.edu */
394120Sgblack@eecs.umich.edu
404120Sgblack@eecs.umich.edu#include "mem/addr_mapper.hh"
414120Sgblack@eecs.umich.edu
424120Sgblack@eecs.umich.eduAddrMapper::AddrMapper(const AddrMapperParams* p)
435124Sgblack@eecs.umich.edu    : MemObject(p),
445237Sgblack@eecs.umich.edu      masterPort(name() + "-master", *this),
455124Sgblack@eecs.umich.edu      slavePort(name() + "-slave", *this)
4610687SAndreas.Sandberg@ARM.com{
475124Sgblack@eecs.umich.edu}
488953Sgblack@eecs.umich.edu
495086Sgblack@eecs.umich.eduvoid
506022Sgblack@eecs.umich.eduAddrMapper::init()
515086Sgblack@eecs.umich.edu{
525086Sgblack@eecs.umich.edu    if (!slavePort.isConnected() || !masterPort.isConnected())
535086Sgblack@eecs.umich.edu        fatal("Address mapper is not connected on both sides.\n");
545086Sgblack@eecs.umich.edu
555086Sgblack@eecs.umich.edu    if ((slavePort.peerBlockSize() != masterPort.peerBlockSize()) &&
565245Sgblack@eecs.umich.edu        slavePort.peerBlockSize() && masterPort.peerBlockSize())
575245Sgblack@eecs.umich.edu        fatal("Slave port size %d, master port size %d \n "
585358Sgblack@eecs.umich.edu              "don't have the same block size... Not supported.\n",
595086Sgblack@eecs.umich.edu              slavePort.peerBlockSize(), masterPort.peerBlockSize());
605124Sgblack@eecs.umich.edu}
615895Sgblack@eecs.umich.edu
625236Sgblack@eecs.umich.eduBaseMasterPort&
635360Sgblack@eecs.umich.eduAddrMapper::getMasterPort(const std::string& if_name, PortID idx)
645360Sgblack@eecs.umich.edu{
655357Sgblack@eecs.umich.edu    if (if_name == "master") {
665237Sgblack@eecs.umich.edu        return masterPort;
675124Sgblack@eecs.umich.edu    } else {
685245Sgblack@eecs.umich.edu        return MemObject::getMasterPort(if_name, idx);
695124Sgblack@eecs.umich.edu    }
705124Sgblack@eecs.umich.edu}
715086Sgblack@eecs.umich.edu
7211175Sandreas.hansson@arm.comBaseSlavePort&
7310194SGeoffrey.Blake@arm.comAddrMapper::getSlavePort(const std::string& if_name, PortID idx)
745124Sgblack@eecs.umich.edu{
755124Sgblack@eecs.umich.edu    if (if_name == "slave") {
765357Sgblack@eecs.umich.edu        return slavePort;
775357Sgblack@eecs.umich.edu    } else {
785360Sgblack@eecs.umich.edu        return MemObject::getSlavePort(if_name, idx);
795360Sgblack@eecs.umich.edu    }
805360Sgblack@eecs.umich.edu}
815360Sgblack@eecs.umich.edu
828752Sgblack@eecs.umich.eduvoid
835236Sgblack@eecs.umich.eduAddrMapper::recvFunctional(PacketPtr pkt)
847912Shestness@cs.utexas.edu{
857912Shestness@cs.utexas.edu    Addr orig_addr = pkt->getAddr();
865236Sgblack@eecs.umich.edu    pkt->setAddr(remapAddr(orig_addr));
8711175Sandreas.hansson@arm.com    masterPort.sendFunctional(pkt);
885242Sgblack@eecs.umich.edu    pkt->setAddr(orig_addr);
899423SAndreas.Sandberg@arm.com}
905242Sgblack@eecs.umich.edu
9111175Sandreas.hansson@arm.comvoid
925242Sgblack@eecs.umich.eduAddrMapper::recvFunctionalSnoop(PacketPtr pkt)
935124Sgblack@eecs.umich.edu{
949818Snilay@cs.wisc.edu    Addr orig_addr = pkt->getAddr();
955124Sgblack@eecs.umich.edu    pkt->setAddr(remapAddr(orig_addr));
9610905Sandreas.sandberg@arm.com    slavePort.sendFunctionalSnoop(pkt);
975124Sgblack@eecs.umich.edu    pkt->setAddr(orig_addr);
985124Sgblack@eecs.umich.edu}
995124Sgblack@eecs.umich.edu
1008953Sgblack@eecs.umich.eduTick
1018953Sgblack@eecs.umich.eduAddrMapper::recvAtomic(PacketPtr pkt)
1028953Sgblack@eecs.umich.edu{
10312140Sswapnilster@gmail.com    Addr orig_addr = pkt->getAddr();
10412140Sswapnilster@gmail.com    pkt->setAddr(remapAddr(orig_addr));
10512140Sswapnilster@gmail.com    Tick ret_tick =  masterPort.sendAtomic(pkt);
10612140Sswapnilster@gmail.com    pkt->setAddr(orig_addr);
10712140Sswapnilster@gmail.com    return ret_tick;
10812140Sswapnilster@gmail.com}
1096141Sgblack@eecs.umich.edu
1106141Sgblack@eecs.umich.eduTick
1115895Sgblack@eecs.umich.eduAddrMapper::recvAtomicSnoop(PacketPtr pkt)
1126023Snate@binkert.org{
1135895Sgblack@eecs.umich.edu    Addr orig_addr = pkt->getAddr();
1145140Sgblack@eecs.umich.edu    pkt->setAddr(remapAddr(orig_addr));
1155124Sgblack@eecs.umich.edu    Tick ret_tick = slavePort.sendAtomicSnoop(pkt);
1165245Sgblack@eecs.umich.edu    pkt->setAddr(orig_addr);
1178953Sgblack@eecs.umich.edu    return ret_tick;
1188953Sgblack@eecs.umich.edu}
1198953Sgblack@eecs.umich.edu
1208953Sgblack@eecs.umich.edubool
1218953Sgblack@eecs.umich.eduAddrMapper::recvTimingReq(PacketPtr pkt)
1228953Sgblack@eecs.umich.edu{
1238953Sgblack@eecs.umich.edu    Addr orig_addr = pkt->getAddr();
1248953Sgblack@eecs.umich.edu    bool needsResponse = pkt->needsResponse();
1256023Snate@binkert.org    bool memInhibitAsserted = pkt->memInhibitAsserted();
1266022Sgblack@eecs.umich.edu    Packet::SenderState* senderState = pkt->senderState;
1276023Snate@binkert.org
1288888Sgeoffrey.blake@arm.com    if (needsResponse && !memInhibitAsserted) {
1298888Sgeoffrey.blake@arm.com        pkt->senderState = new AddrMapperSenderState(senderState, orig_addr);
1308888Sgeoffrey.blake@arm.com    }
1318888Sgeoffrey.blake@arm.com
1325245Sgblack@eecs.umich.edu    pkt->setAddr(remapAddr(orig_addr));
1339738Sandreas@sandberg.pp.se
1349738Sandreas@sandberg.pp.se    // Attempt to send the packet (always succeeds for inhibited
1359738Sandreas@sandberg.pp.se    // packets)
1369738Sandreas@sandberg.pp.se    bool successful = masterPort.sendTimingReq(pkt);
1379738Sandreas@sandberg.pp.se
1389738Sandreas@sandberg.pp.se    // If not successful, restore the sender state
1399738Sandreas@sandberg.pp.se    if (!successful && needsResponse) {
1409738Sandreas@sandberg.pp.se        delete pkt->senderState;
1419738Sandreas@sandberg.pp.se        pkt->senderState = senderState;
1429738Sandreas@sandberg.pp.se    }
1439738Sandreas@sandberg.pp.se
1449738Sandreas@sandberg.pp.se    return successful;
1459738Sandreas@sandberg.pp.se}
1469738Sandreas@sandberg.pp.se
1479738Sandreas@sandberg.pp.sebool
1489738Sandreas@sandberg.pp.seAddrMapper::recvTimingResp(PacketPtr pkt)
1496022Sgblack@eecs.umich.edu{
1506022Sgblack@eecs.umich.edu    AddrMapperSenderState* receivedState =
15112140Sswapnilster@gmail.com        dynamic_cast<AddrMapperSenderState*>(pkt->senderState);
15212140Sswapnilster@gmail.com
15312140Sswapnilster@gmail.com    // Restore initial sender state
15412140Sswapnilster@gmail.com    if (receivedState == NULL)
15512140Sswapnilster@gmail.com        panic("AddrMapper %s got a response without sender state\n",
1565124Sgblack@eecs.umich.edu              name());
15711168Sandreas.hansson@arm.com
15811168Sandreas.hansson@arm.com    Addr remapped_addr = pkt->getAddr();
1598864Snilay@cs.wisc.edu
1608922Swilliam.wang@arm.com    // Restore the state and address
1618922Swilliam.wang@arm.com    pkt->senderState = receivedState->origSenderState;
1628922Swilliam.wang@arm.com    pkt->setAddr(receivedState->origAddr);
1638922Swilliam.wang@arm.com
1648922Swilliam.wang@arm.com    // Attempt to send the packet
1658922Swilliam.wang@arm.com    bool successful = slavePort.sendTimingResp(pkt);
1668922Swilliam.wang@arm.com
1678922Swilliam.wang@arm.com    // If packet successfully sent, delete the sender state, otherwise
1688922Swilliam.wang@arm.com    // restore state
1698922Swilliam.wang@arm.com    if (successful) {
17011175Sandreas.hansson@arm.com        delete receivedState;
1715124Sgblack@eecs.umich.edu    } else {
1725086Sgblack@eecs.umich.edu        // Don't delete anything and let the packet look like we did
1735086Sgblack@eecs.umich.edu        // not touch it
1744120Sgblack@eecs.umich.edu        pkt->senderState = receivedState;
175        pkt->setAddr(remapped_addr);
176    }
177    return successful;
178}
179
180void
181AddrMapper::recvTimingSnoopReq(PacketPtr pkt)
182{
183    slavePort.sendTimingSnoopReq(pkt);
184}
185
186bool
187AddrMapper::recvTimingSnoopResp(PacketPtr pkt)
188{
189    return masterPort.sendTimingSnoopResp(pkt);
190}
191
192bool
193AddrMapper::isSnooping() const
194{
195    if (slavePort.isSnooping())
196        fatal("AddrMapper doesn't support remapping of snooping requests\n");
197    return false;
198}
199
200unsigned
201AddrMapper::deviceBlockSizeMaster()
202{
203    return slavePort.peerBlockSize();
204}
205
206unsigned
207AddrMapper::deviceBlockSizeSlave()
208{
209    return masterPort.peerBlockSize();
210}
211
212void
213AddrMapper::recvRetryMaster()
214{
215    slavePort.sendRetry();
216}
217
218void
219AddrMapper::recvRetrySlave()
220{
221    masterPort.sendRetry();
222}
223
224void
225AddrMapper::recvRangeChange()
226{
227    slavePort.sendRangeChange();
228}
229
230RangeAddrMapper::RangeAddrMapper(const RangeAddrMapperParams* p) :
231    AddrMapper(p),
232    originalRanges(p->original_ranges),
233    remappedRanges(p->remapped_ranges)
234{
235    if (originalRanges.size() != remappedRanges.size())
236        fatal("AddrMapper: original and shadowed range list must "
237              "be same size\n");
238
239    for (size_t x = 0; x < originalRanges.size(); x++) {
240        if (originalRanges[x].size() != remappedRanges[x].size())
241            fatal("AddrMapper: original and shadowed range list elements"
242                  " aren't all of the same size\n");
243    }
244}
245
246RangeAddrMapper*
247RangeAddrMapperParams::create()
248{
249    return new RangeAddrMapper(this);
250}
251
252Addr
253RangeAddrMapper::remapAddr(Addr addr) const
254{
255    for (int i = 0; i < originalRanges.size(); ++i) {
256        if (originalRanges[i].contains(addr)) {
257            Addr offset = addr - originalRanges[i].start();
258            return offset + remappedRanges[i].start();
259        }
260    }
261
262    return addr;
263}
264
265AddrRangeList
266RangeAddrMapper::getAddrRanges() const
267{
268    // Simply return the original ranges as given by the parameters
269    AddrRangeList ranges(originalRanges.begin(), originalRanges.end());
270    return ranges;
271}
272
273
274