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