fixes for gcc 4.1
[gem5.git] / src / mem / cache / miss / mshr_queue.cc
1 /*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Erik Hallnor
29 */
30
31 /** @file
32 * Definition of the MSHRQueue.
33 */
34
35 #include "mem/cache/miss/mshr_queue.hh"
36 #include "sim/eventq.hh"
37
38 using namespace std;
39
40 MSHRQueue::MSHRQueue(int num_mshrs, int reserve)
41 : numMSHRs(num_mshrs + reserve - 1), numReserve(reserve)
42 {
43 allocated = 0;
44 inServiceMSHRs = 0;
45 allocatedTargets = 0;
46 registers = new MSHR[numMSHRs];
47 for (int i = 0; i < numMSHRs; ++i) {
48 freeList.push_back(&registers[i]);
49 }
50 }
51
52 MSHRQueue::~MSHRQueue()
53 {
54 delete [] registers;
55 }
56
57 MSHR*
58 MSHRQueue::findMatch(Addr addr, int asid) const
59 {
60 MSHR::ConstIterator i = allocatedList.begin();
61 MSHR::ConstIterator end = allocatedList.end();
62 for (; i != end; ++i) {
63 MSHR *mshr = *i;
64 if (mshr->addr == addr) {
65 return mshr;
66 }
67 }
68 return NULL;
69 }
70
71 bool
72 MSHRQueue::findMatches(Addr addr, int asid, vector<MSHR*>& matches) const
73 {
74 // Need an empty vector
75 assert(matches.empty());
76 bool retval = false;
77 MSHR::ConstIterator i = allocatedList.begin();
78 MSHR::ConstIterator end = allocatedList.end();
79 for (; i != end; ++i) {
80 MSHR *mshr = *i;
81 if (mshr->addr == addr) {
82 retval = true;
83 matches.push_back(mshr);
84 }
85 }
86 return retval;
87
88 }
89
90 MSHR*
91 MSHRQueue::findPending(Packet * &pkt) const
92 {
93 MSHR::ConstIterator i = pendingList.begin();
94 MSHR::ConstIterator end = pendingList.end();
95 for (; i != end; ++i) {
96 MSHR *mshr = *i;
97 if (mshr->addr < pkt->getAddr()) {
98 if (mshr->addr + mshr->pkt->getSize() > pkt->getAddr()) {
99 return mshr;
100 }
101 } else {
102 if (pkt->getAddr() + pkt->getSize() > mshr->addr) {
103 return mshr;
104 }
105 }
106
107 //need to check destination address for copies.
108 //TEMP NOT DOING COPIES
109 #if 0
110 if (mshr->pkt->cmd == Copy) {
111 Addr dest = mshr->pkt->dest;
112 if (dest < pkt->addr) {
113 if (dest + mshr->pkt->size > pkt->addr) {
114 return mshr;
115 }
116 } else {
117 if (pkt->addr + pkt->size > dest) {
118 return mshr;
119 }
120 }
121 }
122 #endif
123 }
124 return NULL;
125 }
126
127 MSHR*
128 MSHRQueue::allocate(Packet * &pkt, int size)
129 {
130 Addr aligned_addr = pkt->getAddr() & ~((Addr)size - 1);
131 MSHR *mshr = freeList.front();
132 assert(mshr->getNumTargets() == 0);
133 freeList.pop_front();
134
135 if (!pkt->needsResponse()) {
136 mshr->allocateAsBuffer(pkt);
137 } else {
138 assert(size !=0);
139 mshr->allocate(pkt->cmd, aligned_addr, pkt->req->getAsid(), size, pkt);
140 allocatedTargets += 1;
141 }
142 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
143 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
144
145 allocated += 1;
146 return mshr;
147 }
148
149 MSHR*
150 MSHRQueue::allocateFetch(Addr addr, int asid, int size, Packet * &target)
151 {
152 MSHR *mshr = freeList.front();
153 assert(mshr->getNumTargets() == 0);
154 freeList.pop_front();
155 mshr->allocate(Packet::ReadReq, addr, asid, size, target);
156 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
157 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
158
159 allocated += 1;
160 return mshr;
161 }
162
163 MSHR*
164 MSHRQueue::allocateTargetList(Addr addr, int asid, int size)
165 {
166 MSHR *mshr = freeList.front();
167 assert(mshr->getNumTargets() == 0);
168 freeList.pop_front();
169 Packet * dummy;
170 mshr->allocate(Packet::ReadReq, addr, asid, size, dummy);
171 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
172 mshr->inService = true;
173 ++inServiceMSHRs;
174 ++allocated;
175 return mshr;
176 }
177
178
179 void
180 MSHRQueue::deallocate(MSHR* mshr)
181 {
182 deallocateOne(mshr);
183 }
184
185 MSHR::Iterator
186 MSHRQueue::deallocateOne(MSHR* mshr)
187 {
188 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
189 freeList.push_front(mshr);
190 allocated--;
191 allocatedTargets -= mshr->getNumTargets();
192 if (mshr->inService) {
193 inServiceMSHRs--;
194 } else {
195 pendingList.erase(mshr->readyIter);
196 }
197 mshr->deallocate();
198 return retval;
199 }
200
201 void
202 MSHRQueue::moveToFront(MSHR *mshr)
203 {
204 if (!mshr->inService) {
205 assert(mshr == *(mshr->readyIter));
206 pendingList.erase(mshr->readyIter);
207 mshr->readyIter = pendingList.insert(pendingList.begin(), mshr);
208 }
209 }
210
211 void
212 MSHRQueue::markInService(MSHR* mshr)
213 {
214 //assert(mshr == pendingList.front());
215 if (!mshr->pkt->needsResponse()) {
216 assert(mshr->getNumTargets() == 0);
217 deallocate(mshr);
218 return;
219 }
220 mshr->inService = true;
221 pendingList.erase(mshr->readyIter);
222 //mshr->readyIter = NULL;
223 inServiceMSHRs += 1;
224 //pendingList.pop_front();
225 }
226
227 void
228 MSHRQueue::markPending(MSHR* mshr, Packet::Command cmd)
229 {
230 //assert(mshr->readyIter == NULL);
231 mshr->pkt->cmd = cmd;
232 mshr->pkt->flags &= ~SATISFIED;
233 mshr->inService = false;
234 --inServiceMSHRs;
235 /**
236 * @ todo might want to add rerequests to front of pending list for
237 * performance.
238 */
239 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
240 }
241
242 void
243 MSHRQueue::squash(int threadNum)
244 {
245 MSHR::Iterator i = allocatedList.begin();
246 MSHR::Iterator end = allocatedList.end();
247 for (; i != end;) {
248 MSHR *mshr = *i;
249 if (mshr->threadNum == threadNum) {
250 while (mshr->hasTargets()) {
251 Packet * target = mshr->getTarget();
252 mshr->popTarget();
253
254 assert(target->req->getThreadNum() == threadNum);
255 target = NULL;
256 }
257 assert(!mshr->hasTargets());
258 assert(mshr->ntargets==0);
259 if (!mshr->inService) {
260 i = deallocateOne(mshr);
261 } else {
262 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
263 ++i;
264 }
265 } else {
266 ++i;
267 }
268 }
269 }