mem: Skip address mapper range checks to allow more flexibility
[gem5.git] / src / mem / addr_mapper.cc
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
42 AddrMapper::AddrMapper(const AddrMapperParams* p)
43 : MemObject(p),
44 masterPort(name() + "-master", *this),
45 slavePort(name() + "-slave", *this)
46 {
47 }
48
49 void
50 AddrMapper::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
62 BaseMasterPort&
63 AddrMapper::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
72 BaseSlavePort&
73 AddrMapper::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
82 void
83 AddrMapper::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
91 void
92 AddrMapper::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
100 Tick
101 AddrMapper::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
110 Tick
111 AddrMapper::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
120 bool
121 AddrMapper::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
147 bool
148 AddrMapper::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
180 void
181 AddrMapper::recvTimingSnoopReq(PacketPtr pkt)
182 {
183 slavePort.sendTimingSnoopReq(pkt);
184 }
185
186 bool
187 AddrMapper::recvTimingSnoopResp(PacketPtr pkt)
188 {
189 return masterPort.sendTimingSnoopResp(pkt);
190 }
191
192 bool
193 AddrMapper::isSnooping() const
194 {
195 if (slavePort.isSnooping())
196 fatal("AddrMapper doesn't support remapping of snooping requests\n");
197 return false;
198 }
199
200 unsigned
201 AddrMapper::deviceBlockSizeMaster()
202 {
203 return slavePort.peerBlockSize();
204 }
205
206 unsigned
207 AddrMapper::deviceBlockSizeSlave()
208 {
209 return masterPort.peerBlockSize();
210 }
211
212 void
213 AddrMapper::recvRetryMaster()
214 {
215 slavePort.sendRetry();
216 }
217
218 void
219 AddrMapper::recvRetrySlave()
220 {
221 masterPort.sendRetry();
222 }
223
224 void
225 AddrMapper::recvRangeChange()
226 {
227 slavePort.sendRangeChange();
228 }
229
230 RangeAddrMapper::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
246 RangeAddrMapper*
247 RangeAddrMapperParams::create()
248 {
249 return new RangeAddrMapper(this);
250 }
251
252 Addr
253 RangeAddrMapper::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
265 AddrRangeList
266 RangeAddrMapper::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