mshr_queue.cc (11284:b3926db25371) mshr_queue.cc (11375:f98df9231cdd)
1/*
1/*
2 * Copyright (c) 2012-2013, 2015 ARM Limited
2 * Copyright (c) 2012-2013, 2015-2016 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 29 unchanged lines hidden (view full) ---

40 * Authors: Erik Hallnor
41 * Andreas Sandberg
42 */
43
44/** @file
45 * Definition of MSHRQueue class functions.
46 */
47
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated

--- 29 unchanged lines hidden (view full) ---

40 * Authors: Erik Hallnor
41 * Andreas Sandberg
42 */
43
44/** @file
45 * Definition of MSHRQueue class functions.
46 */
47
48#include "base/trace.hh"
49#include "mem/cache/mshr_queue.hh"
48#include "mem/cache/mshr_queue.hh"
50#include "debug/Drain.hh"
51
52using namespace std;
53
54MSHRQueue::MSHRQueue(const std::string &_label,
49
50using namespace std;
51
52MSHRQueue::MSHRQueue(const std::string &_label,
55 int num_entries, int reserve, int demand_reserve,
56 int _index)
57 : label(_label), numEntries(num_entries + reserve - 1),
58 numReserve(reserve), demandReserve(demand_reserve),
59 registers(numEntries), allocated(0),
60 inServiceEntries(0), index(_index)
61{
62 for (int i = 0; i < numEntries; ++i) {
63 registers[i].queue = this;
64 freeList.push_back(&registers[i]);
65 }
66}
53 int num_entries, int reserve, int demand_reserve)
54 : Queue<MSHR>(_label, num_entries, reserve),
55 demandReserve(demand_reserve)
56{}
67
68MSHR *
57
58MSHR *
69MSHRQueue::findMatch(Addr blk_addr, bool is_secure) const
70{
71 for (const auto& mshr : allocatedList) {
72 // we ignore any MSHRs allocated for uncacheable accesses and
73 // simply ignore them when matching, in the cache we never
74 // check for matches when adding new uncacheable entries, and
75 // we do not want normal cacheable accesses being added to an
76 // MSHR serving an uncacheable access
77 if (!mshr->isUncacheable() && mshr->blkAddr == blk_addr &&
78 mshr->isSecure == is_secure) {
79 return mshr;
80 }
81 }
82 return NULL;
83}
84
85bool
86MSHRQueue::findMatches(Addr blk_addr, bool is_secure,
87 vector<MSHR*>& matches) const
88{
89 // Need an empty vector
90 assert(matches.empty());
91 bool retval = false;
92 for (const auto& mshr : allocatedList) {
93 if (!mshr->isUncacheable() && mshr->blkAddr == blk_addr &&
94 mshr->isSecure == is_secure) {
95 retval = true;
96 matches.push_back(mshr);
97 }
98 }
99 return retval;
100}
101
102
103bool
104MSHRQueue::checkFunctional(PacketPtr pkt, Addr blk_addr)
105{
106 pkt->pushLabel(label);
107 for (const auto& mshr : allocatedList) {
108 if (mshr->blkAddr == blk_addr && mshr->checkFunctional(pkt)) {
109 pkt->popLabel();
110 return true;
111 }
112 }
113 pkt->popLabel();
114 return false;
115}
116
117
118MSHR *
119MSHRQueue::findPending(Addr blk_addr, bool is_secure) const
120{
121 for (const auto& mshr : readyList) {
122 if (mshr->blkAddr == blk_addr && mshr->isSecure == is_secure) {
123 return mshr;
124 }
125 }
126 return NULL;
127}
128
129
130MSHR::Iterator
131MSHRQueue::addToReadyList(MSHR *mshr)
132{
133 if (readyList.empty() || readyList.back()->readyTime <= mshr->readyTime) {
134 return readyList.insert(readyList.end(), mshr);
135 }
136
137 for (auto i = readyList.begin(); i != readyList.end(); ++i) {
138 if ((*i)->readyTime > mshr->readyTime) {
139 return readyList.insert(i, mshr);
140 }
141 }
142 assert(false);
143 return readyList.end(); // keep stupid compilers happy
144}
145
146
147MSHR *
148MSHRQueue::allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt,
149 Tick when_ready, Counter order, bool alloc_on_fill)
150{
151 assert(!freeList.empty());
152 MSHR *mshr = freeList.front();
153 assert(mshr->getNumTargets() == 0);
154 freeList.pop_front();
155
156 mshr->allocate(blk_addr, blk_size, pkt, when_ready, order, alloc_on_fill);
157 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
158 mshr->readyIter = addToReadyList(mshr);
159
160 allocated += 1;
161 return mshr;
162}
163
59MSHRQueue::allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt,
60 Tick when_ready, Counter order, bool alloc_on_fill)
61{
62 assert(!freeList.empty());
63 MSHR *mshr = freeList.front();
64 assert(mshr->getNumTargets() == 0);
65 freeList.pop_front();
66
67 mshr->allocate(blk_addr, blk_size, pkt, when_ready, order, alloc_on_fill);
68 mshr->allocIter = allocatedList.insert(allocatedList.end(), mshr);
69 mshr->readyIter = addToReadyList(mshr);
70
71 allocated += 1;
72 return mshr;
73}
74
164
165void
75void
166MSHRQueue::deallocate(MSHR *mshr)
167{
168 deallocateOne(mshr);
169}
170
171MSHR::Iterator
172MSHRQueue::deallocateOne(MSHR *mshr)
173{
174 MSHR::Iterator retval = allocatedList.erase(mshr->allocIter);
175 freeList.push_front(mshr);
176 allocated--;
177 if (mshr->inService) {
178 inServiceEntries--;
179 } else {
180 readyList.erase(mshr->readyIter);
181 }
182 mshr->deallocate();
183 if (drainState() == DrainState::Draining && allocated == 0) {
184 // Notify the drain manager that we have completed draining if
185 // there are no other outstanding requests in this MSHR queue.
186 DPRINTF(Drain, "MSHRQueue now empty, signalling drained\n");
187 signalDrainDone();
188 }
189 return retval;
190}
191
192void
193MSHRQueue::moveToFront(MSHR *mshr)
194{
195 if (!mshr->inService) {
196 assert(mshr == *(mshr->readyIter));
197 readyList.erase(mshr->readyIter);
198 mshr->readyIter = readyList.insert(readyList.begin(), mshr);
199 }
200}
201
202void
203MSHRQueue::markInService(MSHR *mshr, bool pending_modified_resp)
204{
76MSHRQueue::moveToFront(MSHR *mshr)
77{
78 if (!mshr->inService) {
79 assert(mshr == *(mshr->readyIter));
80 readyList.erase(mshr->readyIter);
81 mshr->readyIter = readyList.insert(readyList.begin(), mshr);
82 }
83}
84
85void
86MSHRQueue::markInService(MSHR *mshr, bool pending_modified_resp)
87{
205 if (mshr->markInService(pending_modified_resp)) {
206 deallocate(mshr);
207 } else {
208 readyList.erase(mshr->readyIter);
209 inServiceEntries += 1;
210 }
88 mshr->markInService(pending_modified_resp);
89 readyList.erase(mshr->readyIter);
90 _numInService += 1;
211}
212
213void
214MSHRQueue::markPending(MSHR *mshr)
215{
216 assert(mshr->inService);
217 mshr->inService = false;
91}
92
93void
94MSHRQueue::markPending(MSHR *mshr)
95{
96 assert(mshr->inService);
97 mshr->inService = false;
218 --inServiceEntries;
98 --_numInService;
219 /**
220 * @ todo might want to add rerequests to front of pending list for
221 * performance.
222 */
223 mshr->readyIter = addToReadyList(mshr);
224}
225
226bool
227MSHRQueue::forceDeallocateTarget(MSHR *mshr)
228{
229 bool was_full = isFull();
230 assert(mshr->hasTargets());
231 // Pop the prefetch off of the target list
232 mshr->popTarget();
233 // Delete mshr if no remaining targets
234 if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
99 /**
100 * @ todo might want to add rerequests to front of pending list for
101 * performance.
102 */
103 mshr->readyIter = addToReadyList(mshr);
104}
105
106bool
107MSHRQueue::forceDeallocateTarget(MSHR *mshr)
108{
109 bool was_full = isFull();
110 assert(mshr->hasTargets());
111 // Pop the prefetch off of the target list
112 mshr->popTarget();
113 // Delete mshr if no remaining targets
114 if (!mshr->hasTargets() && !mshr->promoteDeferredTargets()) {
235 deallocateOne(mshr);
115 deallocate(mshr);
236 }
237
238 // Notify if MSHR queue no longer full
239 return was_full && !isFull();
240}
116 }
117
118 // Notify if MSHR queue no longer full
119 return was_full && !isFull();
120}
241
242DrainState
243MSHRQueue::drain()
244{
245 return allocated == 0 ? DrainState::Drained : DrainState::Draining;
246}