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