Backing in more changsets, getting closer to compile
[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->addr) {
98 if (mshr->addr + mshr->pkt->size > pkt->addr) {
99 return mshr;
100 }
101 } else {
102 if (pkt->addr + pkt->size > mshr->addr) {
103 return mshr;
104 }
105 }
106
107 //need to check destination address for copies.
108 if (mshr->pkt->cmd == Copy) {
109 Addr dest = mshr->pkt->dest;
110 if (dest < pkt->addr) {
111 if (dest + mshr->pkt->size > pkt->addr) {
112 return mshr;
113 }
114 } else {
115 if (pkt->addr + pkt->size > dest) {
116 return mshr;
117 }
118 }
119 }
120 }
121 return NULL;
122 }
123
124 MSHR*
125 MSHRQueue::allocate(Packet * &pkt, int size)
126 {
127 Addr aligned_addr = pkt->addr & ~((Addr)size - 1);
128 MSHR *mshr = freeList.front();
129 assert(mshr->getNumTargets() == 0);
130 freeList.pop_front();
131
132 if (pkt->cmd.isNoResponse()) {
133 mshr->allocateAsBuffer(pkt);
134 } else {
135 assert(size !=0);
136 mshr->allocate(pkt->cmd, aligned_addr, pkt->req->req->asid, size, pkt);
137 allocatedTargets += 1;
138 }
139 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
140 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
141
142 allocated += 1;
143 return mshr;
144 }
145
146 MSHR*
147 MSHRQueue::allocateFetch(Addr addr, int asid, int size, Packet * &target)
148 {
149 MSHR *mshr = freeList.front();
150 assert(mshr->getNumTargets() == 0);
151 freeList.pop_front();
152 mshr->allocate(Read, addr, asid, size, target);
153 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
154 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
155
156 allocated += 1;
157 return mshr;
158 }
159
160 MSHR*
161 MSHRQueue::allocateTargetList(Addr addr, int asid, int size)
162 {
163 MSHR *mshr = freeList.front();
164 assert(mshr->getNumTargets() == 0);
165 freeList.pop_front();
166 Packet * dummy;
167 mshr->allocate(Read, addr, asid, size, dummy);
168 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
169 mshr->inService = true;
170 ++inServiceMSHRs;
171 ++allocated;
172 return mshr;
173 }
174
175
176 void
177 MSHRQueue::deallocate(MSHR* mshr)
178 {
179 deallocateOne(mshr);
180 }
181
182 MSHR::Iterator
183 MSHRQueue::deallocateOne(MSHR* mshr)
184 {
185 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
186 freeList.push_front(mshr);
187 allocated--;
188 allocatedTargets -= mshr->getNumTargets();
189 if (mshr->inService) {
190 inServiceMSHRs--;
191 } else {
192 pendingList.erase(mshr->readyIter);
193 }
194 mshr->deallocate();
195 return retval;
196 }
197
198 void
199 MSHRQueue::moveToFront(MSHR *mshr)
200 {
201 if (!mshr->inService) {
202 assert(mshr == *(mshr->readyIter));
203 pendingList.erase(mshr->readyIter);
204 mshr->readyIter = pendingList.insert(pendingList.begin(), mshr);
205 }
206 }
207
208 void
209 MSHRQueue::markInService(MSHR* mshr)
210 {
211 //assert(mshr == pendingList.front());
212 if (mshr->pkt->cmd.isNoResponse()) {
213 assert(mshr->getNumTargets() == 0);
214 deallocate(mshr);
215 return;
216 }
217 mshr->inService = true;
218 pendingList.erase(mshr->readyIter);
219 mshr->readyIter = NULL;
220 inServiceMSHRs += 1;
221 //pendingList.pop_front();
222 }
223
224 void
225 MSHRQueue::markPending(MSHR* mshr, Packet::Command cmd)
226 {
227 assert(mshr->readyIter == NULL);
228 mshr->pkt->cmd = cmd;
229 mshr->pkt->flags &= ~SATISFIED;
230 mshr->inService = false;
231 --inServiceMSHRs;
232 /**
233 * @ todo might want to add rerequests to front of pending list for
234 * performance.
235 */
236 mshr->readyIter = pendingList.insert(pendingList.end(), mshr);
237 }
238
239 void
240 MSHRQueue::squash(int req->getThreadNum()ber)
241 {
242 MSHR::Iterator i = allocatedList.begin();
243 MSHR::Iterator end = allocatedList.end();
244 for (; i != end;) {
245 MSHR *mshr = *i;
246 if (mshr->setThreadNum() == req->getThreadNum()ber) {
247 while (mshr->hasTargets()) {
248 Packet * target = mshr->getTarget();
249 mshr->popTarget();
250
251 assert(target->req->setThreadNum() == req->getThreadNum()ber);
252 if (target->completionEvent != NULL) {
253 delete target->completionEvent;
254 }
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 }