addr_mapper.cc revision 10862:c78bfcfdfb02
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
56BaseMasterPort&
57AddrMapper::getMasterPort(const std::string& if_name, PortID idx)
58{
59    if (if_name == "master") {
60        return masterPort;
61    } else {
62        return MemObject::getMasterPort(if_name, idx);
63    }
64}
65
66BaseSlavePort&
67AddrMapper::getSlavePort(const std::string& if_name, PortID idx)
68{
69    if (if_name == "slave") {
70        return slavePort;
71    } else {
72        return MemObject::getSlavePort(if_name, idx);
73    }
74}
75
76void
77AddrMapper::recvFunctional(PacketPtr pkt)
78{
79    Addr orig_addr = pkt->getAddr();
80    pkt->setAddr(remapAddr(orig_addr));
81    masterPort.sendFunctional(pkt);
82    pkt->setAddr(orig_addr);
83}
84
85void
86AddrMapper::recvFunctionalSnoop(PacketPtr pkt)
87{
88    Addr orig_addr = pkt->getAddr();
89    pkt->setAddr(remapAddr(orig_addr));
90    slavePort.sendFunctionalSnoop(pkt);
91    pkt->setAddr(orig_addr);
92}
93
94Tick
95AddrMapper::recvAtomic(PacketPtr pkt)
96{
97    Addr orig_addr = pkt->getAddr();
98    pkt->setAddr(remapAddr(orig_addr));
99    Tick ret_tick =  masterPort.sendAtomic(pkt);
100    pkt->setAddr(orig_addr);
101    return ret_tick;
102}
103
104Tick
105AddrMapper::recvAtomicSnoop(PacketPtr pkt)
106{
107    Addr orig_addr = pkt->getAddr();
108    pkt->setAddr(remapAddr(orig_addr));
109    Tick ret_tick = slavePort.sendAtomicSnoop(pkt);
110    pkt->setAddr(orig_addr);
111    return ret_tick;
112}
113
114bool
115AddrMapper::recvTimingReq(PacketPtr pkt)
116{
117    Addr orig_addr = pkt->getAddr();
118    bool needsResponse = pkt->needsResponse();
119    bool memInhibitAsserted = pkt->memInhibitAsserted();
120
121    if (needsResponse && !memInhibitAsserted) {
122        pkt->pushSenderState(new AddrMapperSenderState(orig_addr));
123    }
124
125    pkt->setAddr(remapAddr(orig_addr));
126
127    // Attempt to send the packet (always succeeds for inhibited
128    // packets)
129    bool successful = masterPort.sendTimingReq(pkt);
130
131    // If not successful, restore the address and sender state
132    if (!successful) {
133        pkt->setAddr(orig_addr);
134
135        if (needsResponse) {
136            delete pkt->popSenderState();
137        }
138    }
139
140    return successful;
141}
142
143bool
144AddrMapper::recvTimingResp(PacketPtr pkt)
145{
146    AddrMapperSenderState* receivedState =
147        dynamic_cast<AddrMapperSenderState*>(pkt->senderState);
148
149    // Restore initial sender state
150    if (receivedState == NULL)
151        panic("AddrMapper %s got a response without sender state\n",
152              name());
153
154    Addr remapped_addr = pkt->getAddr();
155
156    // Restore the state and address
157    pkt->senderState = receivedState->predecessor;
158    pkt->setAddr(receivedState->origAddr);
159
160    // Attempt to send the packet
161    bool successful = slavePort.sendTimingResp(pkt);
162
163    // If packet successfully sent, delete the sender state, otherwise
164    // restore state
165    if (successful) {
166        delete receivedState;
167    } else {
168        // Don't delete anything and let the packet look like we did
169        // not touch it
170        pkt->senderState = receivedState;
171        pkt->setAddr(remapped_addr);
172    }
173    return successful;
174}
175
176void
177AddrMapper::recvTimingSnoopReq(PacketPtr pkt)
178{
179    slavePort.sendTimingSnoopReq(pkt);
180}
181
182bool
183AddrMapper::recvTimingSnoopResp(PacketPtr pkt)
184{
185    return masterPort.sendTimingSnoopResp(pkt);
186}
187
188bool
189AddrMapper::isSnooping() const
190{
191    if (slavePort.isSnooping())
192        fatal("AddrMapper doesn't support remapping of snooping requests\n");
193    return false;
194}
195
196void
197AddrMapper::recvReqRetry()
198{
199    slavePort.sendRetryReq();
200}
201
202void
203AddrMapper::recvRespRetry()
204{
205    masterPort.sendRetryResp();
206}
207
208void
209AddrMapper::recvRangeChange()
210{
211    slavePort.sendRangeChange();
212}
213
214RangeAddrMapper::RangeAddrMapper(const RangeAddrMapperParams* p) :
215    AddrMapper(p),
216    originalRanges(p->original_ranges),
217    remappedRanges(p->remapped_ranges)
218{
219    if (originalRanges.size() != remappedRanges.size())
220        fatal("AddrMapper: original and shadowed range list must "
221              "be same size\n");
222
223    for (size_t x = 0; x < originalRanges.size(); x++) {
224        if (originalRanges[x].size() != remappedRanges[x].size())
225            fatal("AddrMapper: original and shadowed range list elements"
226                  " aren't all of the same size\n");
227    }
228}
229
230RangeAddrMapper*
231RangeAddrMapperParams::create()
232{
233    return new RangeAddrMapper(this);
234}
235
236Addr
237RangeAddrMapper::remapAddr(Addr addr) const
238{
239    for (int i = 0; i < originalRanges.size(); ++i) {
240        if (originalRanges[i].contains(addr)) {
241            Addr offset = addr - originalRanges[i].start();
242            return offset + remappedRanges[i].start();
243        }
244    }
245
246    return addr;
247}
248
249AddrRangeList
250RangeAddrMapper::getAddrRanges() const
251{
252    // Simply return the original ranges as given by the parameters
253    AddrRangeList ranges(originalRanges.begin(), originalRanges.end());
254    return ranges;
255}
256
257
258