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