ruby: added Packet interface to makeRequest and isReady.
[gem5.git] / src / mem / cache / 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 MSHRQueue class functions.
33 */
34
35 #include "mem/cache/mshr_queue.hh"
36
37 using namespace std;
38
39 MSHRQueue::MSHRQueue(const std::string &_label,
40 int num_entries, int reserve, int _index)
41 : label(_label),
42 numEntries(num_entries + reserve - 1), numReserve(reserve),
43 index(_index)
44 {
45 allocated = 0;
46 inServiceEntries = 0;
47 registers = new MSHR[numEntries];
48 for (int i = 0; i < numEntries; ++i) {
49 registers[i].queue = this;
50 freeList.push_back(&registers[i]);
51 }
52 }
53
54 MSHRQueue::~MSHRQueue()
55 {
56 delete [] registers;
57 }
58
59 MSHR *
60 MSHRQueue::findMatch(Addr addr) const
61 {
62 MSHR::ConstIterator i = allocatedList.begin();
63 MSHR::ConstIterator end = allocatedList.end();
64 for (; i != end; ++i) {
65 MSHR *mshr = *i;
66 if (mshr->addr == addr) {
67 return mshr;
68 }
69 }
70 return NULL;
71 }
72
73 bool
74 MSHRQueue::findMatches(Addr addr, vector<MSHR*>& matches) const
75 {
76 // Need an empty vector
77 assert(matches.empty());
78 bool retval = false;
79 MSHR::ConstIterator i = allocatedList.begin();
80 MSHR::ConstIterator end = allocatedList.end();
81 for (; i != end; ++i) {
82 MSHR *mshr = *i;
83 if (mshr->addr == addr) {
84 retval = true;
85 matches.push_back(mshr);
86 }
87 }
88 return retval;
89 }
90
91
92 bool
93 MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
94 {
95 pkt->pushLabel(label);
96 MSHR::ConstIterator i = allocatedList.begin();
97 MSHR::ConstIterator end = allocatedList.end();
98 for (; i != end; ++i) {
99 MSHR *mshr = *i;
100 if (mshr->addr == blk_addr && mshr->checkFunctional(pkt)) {
101 pkt->popLabel();
102 return true;
103 }
104 }
105 pkt->popLabel();
106 return false;
107 }
108
109
110 MSHR *
111 MSHRQueue::findPending(Addr addr, int size) const
112 {
113 MSHR::ConstIterator i = readyList.begin();
114 MSHR::ConstIterator end = readyList.end();
115 for (; i != end; ++i) {
116 MSHR *mshr = *i;
117 if (mshr->addr < addr) {
118 if (mshr->addr + mshr->size > addr) {
119 return mshr;
120 }
121 } else {
122 if (addr + size > mshr->addr) {
123 return mshr;
124 }
125 }
126 }
127 return NULL;
128 }
129
130
131 MSHR::Iterator
132 MSHRQueue::addToReadyList(MSHR *mshr)
133 {
134 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
135 return readyList.insert(readyList.end(), mshr);
136 }
137
138 MSHR::Iterator i = readyList.begin();
139 MSHR::Iterator end = readyList.end();
140 for (; i != end; ++i) {
141 if ((*i)->readyTime > mshr->readyTime) {
142 return readyList.insert(i, mshr);
143 }
144 }
145 assert(false);
146 return end; // keep stupid compilers happy
147 }
148
149
150 MSHR *
151 MSHRQueue::allocate(Addr addr, int size, PacketPtr &pkt,
152 Tick when, Counter order)
153 {
154 assert(!freeList.empty());
155 MSHR *mshr = freeList.front();
156 assert(mshr->getNumTargets() == 0);
157 freeList.pop_front();
158
159 mshr->allocate(addr, size, pkt, when, order);
160 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
161 mshr->readyIter = addToReadyList(mshr);
162
163 allocated += 1;
164 return mshr;
165 }
166
167
168 void
169 MSHRQueue::deallocate(MSHR *mshr)
170 {
171 deallocateOne(mshr);
172 }
173
174 MSHR::Iterator
175 MSHRQueue::deallocateOne(MSHR *mshr)
176 {
177 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
178 freeList.push_front(mshr);
179 allocated--;
180 if (mshr->inService) {
181 inServiceEntries--;
182 } else {
183 readyList.erase(mshr->readyIter);
184 }
185 mshr->deallocate();
186 return retval;
187 }
188
189 void
190 MSHRQueue::moveToFront(MSHR *mshr)
191 {
192 if (!mshr->inService) {
193 assert(mshr == *(mshr->readyIter));
194 readyList.erase(mshr->readyIter);
195 mshr->readyIter = readyList.insert(readyList.begin(), mshr);
196 }
197 }
198
199 void
200 MSHRQueue::markInService(MSHR *mshr)
201 {
202 if (mshr->markInService()) {
203 deallocate(mshr);
204 } else {
205 readyList.erase(mshr->readyIter);
206 inServiceEntries += 1;
207 }
208 }
209
210 void
211 MSHRQueue::markPending(MSHR *mshr)
212 {
213 assert(mshr->inService);
214 mshr->inService = false;
215 --inServiceEntries;
216 /**
217 * @ todo might want to add rerequests to front of pending list for
218 * performance.
219 */
220 mshr->readyIter = addToReadyList(mshr);
221 }
222
223 void
224 MSHRQueue::squash(int threadNum)
225 {
226 MSHR::Iterator i = allocatedList.begin();
227 MSHR::Iterator end = allocatedList.end();
228 for (; i != end;) {
229 MSHR *mshr = *i;
230 if (mshr->threadNum == threadNum) {
231 while (mshr->hasTargets()) {
232 mshr->popTarget();
233 assert(0/*target->req->threadId()*/ == threadNum);
234 }
235 assert(!mshr->hasTargets());
236 assert(mshr->ntargets==0);
237 if (!mshr->inService) {
238 i = deallocateOne(mshr);
239 } else {
240 //mshr->pkt->flags &= ~CACHE_LINE_FILL;
241 ++i;
242 }
243 } else {
244 ++i;
245 }
246 }
247 }