Merge zizzer.eecs.umich.edu:/bk/newmem
[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) 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, 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 assert(!freeList.empty());
132 MSHR *mshr = freeList.front();
133 assert(mshr->getNumTargets() == 0);
134 freeList.pop_front();
135
136 if (!pkt->needsResponse()) {
137 mshr->allocateAsBuffer(pkt);
138 } else {
139 assert(size !=0);
140 mshr->allocate(pkt->cmd, aligned_addr, size, pkt);
141 allocatedTargets += 1;
142 }
143 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
144 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
145
146 allocated += 1;
147 return mshr;
148 }
149
150 MSHR*
151 MSHRQueue::allocateFetch(Addr addr, int size, Packet * &target)
152 {
153 MSHR *mshr = freeList.front();
154 assert(mshr->getNumTargets() == 0);
155 freeList.pop_front();
156 mshr->allocate(Packet::ReadReq, addr, size, target);
157 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
158 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
159
160 allocated += 1;
161 return mshr;
162 }
163
164 MSHR*
165 MSHRQueue::allocateTargetList(Addr addr, int size)
166 {
167 MSHR *mshr = freeList.front();
168 assert(mshr->getNumTargets() == 0);
169 freeList.pop_front();
170 Packet * dummy;
171 mshr->allocate(Packet::ReadReq, addr, size, dummy);
172 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
173 mshr->inService = true;
174 ++inServiceMSHRs;
175 ++allocated;
176 return mshr;
177 }
178
179
180 void
181 MSHRQueue::deallocate(MSHR* mshr)
182 {
183 deallocateOne(mshr);
184 }
185
186 MSHR::Iterator
187 MSHRQueue::deallocateOne(MSHR* mshr)
188 {
189 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
190 freeList.push_front(mshr);
191 allocated--;
192 allocatedTargets -= mshr->getNumTargets();
193 if (mshr->inService) {
194 inServiceMSHRs--;
195 } else {
196 pendingList.erase(mshr->readyIter);
197 }
198 mshr->deallocate();
199 return retval;
200 }
201
202 void
203 MSHRQueue::moveToFront(MSHR *mshr)
204 {
205 if (!mshr->inService) {
206 assert(mshr == *(mshr->readyIter));
207 pendingList.erase(mshr->readyIter);
208 mshr->readyIter = pendingList.insert(pendingList.begin(), mshr);
209 }
210 }
211
212 void
213 MSHRQueue::markInService(MSHR* mshr)
214 {
215 //assert(mshr == pendingList.front());
216 if (!(mshr->pkt->needsResponse() || mshr->pkt->cmd == Packet::UpgradeReq)) {
217 assert(mshr->getNumTargets() == 0);
218 if ((mshr->pkt->flags & SATISFIED) && (mshr->pkt->cmd == Packet::Writeback)) {
219 //Writeback hit, so delete it
220 //otherwise the consumer will delete it
221 delete mshr->pkt->req;
222 }
223 deallocate(mshr);
224 return;
225 }
226 mshr->inService = true;
227 pendingList.erase(mshr->readyIter);
228 //mshr->readyIter = NULL;
229 inServiceMSHRs += 1;
230 //pendingList.pop_front();
231 }
232
233 void
234 MSHRQueue::markPending(MSHR* mshr, Packet::Command cmd)
235 {
236 //assert(mshr->readyIter == NULL);
237 mshr->pkt->cmd = cmd;
238 mshr->pkt->flags &= ~SATISFIED;
239 mshr->inService = false;
240 --inServiceMSHRs;
241 /**
242 * @ todo might want to add rerequests to front of pending list for
243 * performance.
244 */
245 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
246 }
247
248 void
249 MSHRQueue::squash(int threadNum)
250 {
251 MSHR::Iterator i = allocatedList.begin();
252 MSHR::Iterator end = allocatedList.end();
253 for (; i != end;) {
254 MSHR *mshr = *i;
255 if (mshr->threadNum == threadNum) {
256 while (mshr->hasTargets()) {
257 Packet * target = mshr->getTarget();
258 mshr->popTarget();
259
260 assert(0/*target->req->getThreadNum()*/ == threadNum);
261 target = NULL;
262 }
263 assert(!mshr->hasTargets());
264 assert(mshr->ntargets==0);
265 if (!mshr->inService) {
266 i = deallocateOne(mshr);
267 } else {
268 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
269 ++i;
270 }
271 } else {
272 ++i;
273 }
274 }
275 }