cpu: Add TraceCPU to playback elastic traces
[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
56 BaseMasterPort&
57 AddrMapper::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
66 BaseSlavePort&
67 AddrMapper::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
76 void
77 AddrMapper::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
85 void
86 AddrMapper::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
94 Tick
95 AddrMapper::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
104 Tick
105 AddrMapper::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
114 bool
115 AddrMapper::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
143 bool
144 AddrMapper::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
176 void
177 AddrMapper::recvTimingSnoopReq(PacketPtr pkt)
178 {
179 slavePort.sendTimingSnoopReq(pkt);
180 }
181
182 bool
183 AddrMapper::recvTimingSnoopResp(PacketPtr pkt)
184 {
185 return masterPort.sendTimingSnoopResp(pkt);
186 }
187
188 bool
189 AddrMapper::isSnooping() const
190 {
191 if (slavePort.isSnooping())
192 fatal("AddrMapper doesn't support remapping of snooping requests\n");
193 return false;
194 }
195
196 void
197 AddrMapper::recvReqRetry()
198 {
199 slavePort.sendRetryReq();
200 }
201
202 void
203 AddrMapper::recvRespRetry()
204 {
205 masterPort.sendRetryResp();
206 }
207
208 void
209 AddrMapper::recvRangeChange()
210 {
211 slavePort.sendRangeChange();
212 }
213
214 RangeAddrMapper::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
230 RangeAddrMapper*
231 RangeAddrMapperParams::create()
232 {
233 return new RangeAddrMapper(this);
234 }
235
236 Addr
237 RangeAddrMapper::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
249 AddrRangeList
250 RangeAddrMapper::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