addr_mapper.cc revision 9405
1/*
2 * Copyright (c) 2012 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Hansson
38 */
39
40#include "mem/addr_mapper.hh"
41
42AddrMapper::AddrMapper(const AddrMapperParams* p)
43    : MemObject(p),
44      masterPort(name() + "-master", *this),
45      slavePort(name() + "-slave", *this)
46{
47}
48
49void
50AddrMapper::init()
51{
52    if (!slavePort.isConnected() || !masterPort.isConnected())
53        fatal("Address mapper is not connected on both sides.\n");
54
55    if ((slavePort.peerBlockSize() != masterPort.peerBlockSize()) &&
56        slavePort.peerBlockSize() && masterPort.peerBlockSize())
57        fatal("Slave port size %d, master port size %d \n "
58              "don't have the same block size... Not supported.\n",
59              slavePort.peerBlockSize(), masterPort.peerBlockSize());
60}
61
62BaseMasterPort&
63AddrMapper::getMasterPort(const std::string& if_name, PortID idx)
64{
65    if (if_name == "master") {
66        return masterPort;
67    } else {
68        return MemObject::getMasterPort(if_name, idx);
69    }
70}
71
72BaseSlavePort&
73AddrMapper::getSlavePort(const std::string& if_name, PortID idx)
74{
75    if (if_name == "slave") {
76        return slavePort;
77    } else {
78        return MemObject::getSlavePort(if_name, idx);
79    }
80}
81
82void
83AddrMapper::recvFunctional(PacketPtr pkt)
84{
85    Addr orig_addr = pkt->getAddr();
86    pkt->setAddr(remapAddr(orig_addr));
87    masterPort.sendFunctional(pkt);
88    pkt->setAddr(orig_addr);
89}
90
91void
92AddrMapper::recvFunctionalSnoop(PacketPtr pkt)
93{
94    Addr orig_addr = pkt->getAddr();
95    pkt->setAddr(remapAddr(orig_addr));
96    slavePort.sendFunctionalSnoop(pkt);
97    pkt->setAddr(orig_addr);
98}
99
100Tick
101AddrMapper::recvAtomic(PacketPtr pkt)
102{
103    Addr orig_addr = pkt->getAddr();
104    pkt->setAddr(remapAddr(orig_addr));
105    Tick ret_tick =  masterPort.sendAtomic(pkt);
106    pkt->setAddr(orig_addr);
107    return ret_tick;
108}
109
110Tick
111AddrMapper::recvAtomicSnoop(PacketPtr pkt)
112{
113    Addr orig_addr = pkt->getAddr();
114    pkt->setAddr(remapAddr(orig_addr));
115    Tick ret_tick = slavePort.sendAtomicSnoop(pkt);
116    pkt->setAddr(orig_addr);
117    return ret_tick;
118}
119
120bool
121AddrMapper::recvTimingReq(PacketPtr pkt)
122{
123    Addr orig_addr = pkt->getAddr();
124    bool needsResponse = pkt->needsResponse();
125    bool memInhibitAsserted = pkt->memInhibitAsserted();
126    Packet::SenderState* senderState = pkt->senderState;
127
128    if (needsResponse && !memInhibitAsserted) {
129        pkt->senderState = new AddrMapperSenderState(senderState, orig_addr);
130    }
131
132    pkt->setAddr(remapAddr(orig_addr));
133
134    // Attempt to send the packet (always succeeds for inhibited
135    // packets)
136    bool successful = masterPort.sendTimingReq(pkt);
137
138    // If not successful, restore the sender state
139    if (!successful && needsResponse) {
140        delete pkt->senderState;
141        pkt->senderState = senderState;
142    }
143
144    return successful;
145}
146
147bool
148AddrMapper::recvTimingResp(PacketPtr pkt)
149{
150    AddrMapperSenderState* receivedState =
151        dynamic_cast<AddrMapperSenderState*>(pkt->senderState);
152
153    // Restore initial sender state
154    if (receivedState == NULL)
155        panic("AddrMapper %s got a response without sender state\n",
156              name());
157
158    Addr remapped_addr = pkt->getAddr();
159
160    // Restore the state and address
161    pkt->senderState = receivedState->origSenderState;
162    pkt->setAddr(receivedState->origAddr);
163
164    // Attempt to send the packet
165    bool successful = slavePort.sendTimingResp(pkt);
166
167    // If packet successfully sent, delete the sender state, otherwise
168    // restore state
169    if (successful) {
170        delete receivedState;
171    } else {
172        // Don't delete anything and let the packet look like we did
173        // not touch it
174        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    AddrRangeList ranges;
269    AddrRangeList actualRanges = masterPort.getAddrRanges();
270
271    for (AddrRangeIter r = actualRanges.begin(); r != actualRanges.end(); ++r) {
272        AddrRange range = *r;
273
274        for (int j = 0; j < originalRanges.size(); ++j) {
275            if (range.intersects(originalRanges[j]))
276                fatal("Cannot remap range that intersects the original"
277                      " ranges but are not a subset.\n");
278            if (range.isSubset(originalRanges[j])) {
279                // range is a subset
280                Addr offset = range.start() - originalRanges[j].start();
281                Addr start = range.start() - offset;
282                ranges.push_back(AddrRange(start, start + range.size() - 1));
283            } else {
284                ranges.push_back(range);
285            }
286        }
287    }
288
289    return ranges;
290}
291
292
293