Still missing prefetch and tags directories as well as cache builder.
[gem5.git] / src / mem / cache / miss / miss_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 * Ron Dreslinski
30 */
31
32 /**
33 * @file
34 * Miss and writeback queue definitions.
35 */
36
37 #include "cpu/smt.hh" //for maxThreadsPerCPU
38 #include "mem/cache/base_cache.hh"
39 #include "mem/cache/miss/miss_queue.hh"
40 #include "mem/cache/prefetch/base_prefetcher.hh"
41
42 using namespace std;
43
44 // simple constructor
45 /**
46 * @todo Remove the +16 from the write buffer constructor once we handle
47 * stalling on writebacks do to compression writes.
48 */
49 MissQueue::MissQueue(int numMSHRs, int numTargets, int write_buffers,
50 bool write_allocate, bool prefetch_miss)
51 : mq(numMSHRs, 4), wb(write_buffers,numMSHRs+1000), numMSHR(numMSHRs),
52 numTarget(numTargets), writeBuffers(write_buffers),
53 writeAllocate(write_allocate), order(0), prefetchMiss(prefetch_miss)
54 {
55 noTargetMSHR = NULL;
56 }
57
58 void
59 MissQueue::regStats(const string &name)
60 {
61 Request temp_req;
62 Packet::Command temp_cmd = Packet::ReadReq;
63 Packet temp_pkt(&temp_req, temp_cmd, 0); //@todo FIx command strings so this isn't neccessary
64
65 using namespace Stats;
66
67 writebacks
68 .init(maxThreadsPerCPU)
69 .name(name + ".writebacks")
70 .desc("number of writebacks")
71 .flags(total)
72 ;
73
74 // MSHR hit statistics
75 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
76 Packet::Command cmd = (Packet::Command)access_idx;
77 const string &cstr = temp_pkt.cmdIdxToString(cmd);
78
79 mshr_hits[access_idx]
80 .init(maxThreadsPerCPU)
81 .name(name + "." + cstr + "_mshr_hits")
82 .desc("number of " + cstr + " MSHR hits")
83 .flags(total | nozero | nonan)
84 ;
85 }
86
87 demandMshrHits
88 .name(name + ".demand_mshr_hits")
89 .desc("number of demand (read+write) MSHR hits")
90 .flags(total)
91 ;
92 demandMshrHits = mshr_hits[Packet::ReadReq] + mshr_hits[Packet::WriteReq];
93
94 overallMshrHits
95 .name(name + ".overall_mshr_hits")
96 .desc("number of overall MSHR hits")
97 .flags(total)
98 ;
99 overallMshrHits = demandMshrHits + mshr_hits[Packet::SoftPFReq] +
100 mshr_hits[Packet::HardPFReq];
101
102 // MSHR miss statistics
103 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
104 Packet::Command cmd = (Packet::Command)access_idx;
105 const string &cstr = temp_pkt.cmdIdxToString(cmd);
106
107 mshr_misses[access_idx]
108 .init(maxThreadsPerCPU)
109 .name(name + "." + cstr + "_mshr_misses")
110 .desc("number of " + cstr + " MSHR misses")
111 .flags(total | nozero | nonan)
112 ;
113 }
114
115 demandMshrMisses
116 .name(name + ".demand_mshr_misses")
117 .desc("number of demand (read+write) MSHR misses")
118 .flags(total)
119 ;
120 demandMshrMisses = mshr_misses[Packet::ReadReq] + mshr_misses[Packet::WriteReq];
121
122 overallMshrMisses
123 .name(name + ".overall_mshr_misses")
124 .desc("number of overall MSHR misses")
125 .flags(total)
126 ;
127 overallMshrMisses = demandMshrMisses + mshr_misses[Packet::SoftPFReq] +
128 mshr_misses[Packet::HardPFReq];
129
130 // MSHR miss latency statistics
131 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
132 Packet::Command cmd = (Packet::Command)access_idx;
133 const string &cstr = temp_pkt.cmdIdxToString(cmd);
134
135 mshr_miss_latency[access_idx]
136 .init(maxThreadsPerCPU)
137 .name(name + "." + cstr + "_mshr_miss_latency")
138 .desc("number of " + cstr + " MSHR miss cycles")
139 .flags(total | nozero | nonan)
140 ;
141 }
142
143 demandMshrMissLatency
144 .name(name + ".demand_mshr_miss_latency")
145 .desc("number of demand (read+write) MSHR miss cycles")
146 .flags(total)
147 ;
148 demandMshrMissLatency = mshr_miss_latency[Packet::ReadReq]
149 + mshr_miss_latency[Packet::WriteReq];
150
151 overallMshrMissLatency
152 .name(name + ".overall_mshr_miss_latency")
153 .desc("number of overall MSHR miss cycles")
154 .flags(total)
155 ;
156 overallMshrMissLatency = demandMshrMissLatency +
157 mshr_miss_latency[Packet::SoftPFReq] + mshr_miss_latency[Packet::HardPFReq];
158
159 // MSHR uncacheable statistics
160 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
161 Packet::Command cmd = (Packet::Command)access_idx;
162 const string &cstr = temp_pkt.cmdIdxToString(cmd);
163
164 mshr_uncacheable[access_idx]
165 .init(maxThreadsPerCPU)
166 .name(name + "." + cstr + "_mshr_uncacheable")
167 .desc("number of " + cstr + " MSHR uncacheable")
168 .flags(total | nozero | nonan)
169 ;
170 }
171
172 overallMshrUncacheable
173 .name(name + ".overall_mshr_uncacheable_misses")
174 .desc("number of overall MSHR uncacheable misses")
175 .flags(total)
176 ;
177 overallMshrUncacheable = mshr_uncacheable[Packet::ReadReq]
178 + mshr_uncacheable[Packet::WriteReq] + mshr_uncacheable[Packet::SoftPFReq]
179 + mshr_uncacheable[Packet::HardPFReq];
180
181 // MSHR miss latency statistics
182 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
183 Packet::Command cmd = (Packet::Command)access_idx;
184 const string &cstr = temp_pkt.cmdIdxToString(cmd);
185
186 mshr_uncacheable_lat[access_idx]
187 .init(maxThreadsPerCPU)
188 .name(name + "." + cstr + "_mshr_uncacheable_latency")
189 .desc("number of " + cstr + " MSHR uncacheable cycles")
190 .flags(total | nozero | nonan)
191 ;
192 }
193
194 overallMshrUncacheableLatency
195 .name(name + ".overall_mshr_uncacheable_latency")
196 .desc("number of overall MSHR uncacheable cycles")
197 .flags(total)
198 ;
199 overallMshrUncacheableLatency = mshr_uncacheable_lat[Packet::ReadReq]
200 + mshr_uncacheable_lat[Packet::WriteReq]
201 + mshr_uncacheable_lat[Packet::SoftPFReq]
202 + mshr_uncacheable_lat[Packet::HardPFReq];
203
204 #if 0
205 // MSHR access formulas
206 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
207 Packet::Command cmd = (Packet::Command)access_idx;
208 const string &cstr = temp_pkt.cmdIdxToString(cmd);
209
210 mshrAccesses[access_idx]
211 .name(name + "." + cstr + "_mshr_accesses")
212 .desc("number of " + cstr + " mshr accesses(hits+misses)")
213 .flags(total | nozero | nonan)
214 ;
215 mshrAccesses[access_idx] =
216 mshr_hits[access_idx] + mshr_misses[access_idx]
217 + mshr_uncacheable[access_idx];
218 }
219
220 demandMshrAccesses
221 .name(name + ".demand_mshr_accesses")
222 .desc("number of demand (read+write) mshr accesses")
223 .flags(total | nozero | nonan)
224 ;
225 demandMshrAccesses = demandMshrHits + demandMshrMisses;
226
227 overallMshrAccesses
228 .name(name + ".overall_mshr_accesses")
229 .desc("number of overall (read+write) mshr accesses")
230 .flags(total | nozero | nonan)
231 ;
232 overallMshrAccesses = overallMshrHits + overallMshrMisses
233 + overallMshrUncacheable;
234 #endif
235
236 // MSHR miss rate formulas
237 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
238 Packet::Command cmd = (Packet::Command)access_idx;
239 const string &cstr = temp_pkt.cmdIdxToString(cmd);
240
241 mshrMissRate[access_idx]
242 .name(name + "." + cstr + "_mshr_miss_rate")
243 .desc("mshr miss rate for " + cstr + " accesses")
244 .flags(total | nozero | nonan)
245 ;
246
247 mshrMissRate[access_idx] =
248 mshr_misses[access_idx] / cache->accesses[access_idx];
249 }
250
251 demandMshrMissRate
252 .name(name + ".demand_mshr_miss_rate")
253 .desc("mshr miss rate for demand accesses")
254 .flags(total)
255 ;
256 demandMshrMissRate = demandMshrMisses / cache->demandAccesses;
257
258 overallMshrMissRate
259 .name(name + ".overall_mshr_miss_rate")
260 .desc("mshr miss rate for overall accesses")
261 .flags(total)
262 ;
263 overallMshrMissRate = overallMshrMisses / cache->overallAccesses;
264
265 // mshrMiss latency formulas
266 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
267 Packet::Command cmd = (Packet::Command)access_idx;
268 const string &cstr = temp_pkt.cmdIdxToString(cmd);
269
270 avgMshrMissLatency[access_idx]
271 .name(name + "." + cstr + "_avg_mshr_miss_latency")
272 .desc("average " + cstr + " mshr miss latency")
273 .flags(total | nozero | nonan)
274 ;
275
276 avgMshrMissLatency[access_idx] =
277 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
278 }
279
280 demandAvgMshrMissLatency
281 .name(name + ".demand_avg_mshr_miss_latency")
282 .desc("average overall mshr miss latency")
283 .flags(total)
284 ;
285 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
286
287 overallAvgMshrMissLatency
288 .name(name + ".overall_avg_mshr_miss_latency")
289 .desc("average overall mshr miss latency")
290 .flags(total)
291 ;
292 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
293
294 // mshrUncacheable latency formulas
295 for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
296 Packet::Command cmd = (Packet::Command)access_idx;
297 const string &cstr = temp_pkt.cmdIdxToString(cmd);
298
299 avgMshrUncacheableLatency[access_idx]
300 .name(name + "." + cstr + "_avg_mshr_uncacheable_latency")
301 .desc("average " + cstr + " mshr uncacheable latency")
302 .flags(total | nozero | nonan)
303 ;
304
305 avgMshrUncacheableLatency[access_idx] =
306 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
307 }
308
309 overallAvgMshrUncacheableLatency
310 .name(name + ".overall_avg_mshr_uncacheable_latency")
311 .desc("average overall mshr uncacheable latency")
312 .flags(total)
313 ;
314 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
315
316 mshr_cap_events
317 .init(maxThreadsPerCPU)
318 .name(name + ".mshr_cap_events")
319 .desc("number of times MSHR cap was activated")
320 .flags(total)
321 ;
322
323 //software prefetching stats
324 soft_prefetch_mshr_full
325 .init(maxThreadsPerCPU)
326 .name(name + ".soft_prefetch_mshr_full")
327 .desc("number of mshr full events for SW prefetching instrutions")
328 .flags(total)
329 ;
330
331 mshr_no_allocate_misses
332 .name(name +".no_allocate_misses")
333 .desc("Number of misses that were no-allocate")
334 ;
335
336 }
337
338 void
339 MissQueue::setCache(BaseCache *_cache)
340 {
341 cache = _cache;
342 blkSize = cache->getBlockSize();
343 }
344
345 void
346 MissQueue::setPrefetcher(BasePrefetcher *_prefetcher)
347 {
348 prefetcher = _prefetcher;
349 }
350
351 MSHR*
352 MissQueue::allocateMiss(Packet * &pkt, int size, Tick time)
353 {
354 MSHR* mshr = mq.allocate(pkt, size);
355 mshr->order = order++;
356 if (!pkt->req->isUncacheable() ){//&& !pkt->isNoAllocate()) {
357 // Mark this as a cache line fill
358 mshr->pkt->flags |= CACHE_LINE_FILL;
359 }
360 if (mq.isFull()) {
361 cache->setBlocked(Blocked_NoMSHRs);
362 }
363 if (pkt->cmd != Packet::HardPFReq) {
364 //If we need to request the bus (not on HW prefetch), do so
365 cache->setMasterRequest(Request_MSHR, time);
366 }
367 return mshr;
368 }
369
370
371 MSHR*
372 MissQueue::allocateWrite(Packet * &pkt, int size, Tick time)
373 {
374 MSHR* mshr = wb.allocate(pkt,pkt->getSize());
375 mshr->order = order++;
376
377 //REMOVING COMPRESSION FOR NOW
378 #if 0
379 if (pkt->isCompressed()) {
380 mshr->pkt->deleteData();
381 mshr->pkt->actualSize = pkt->actualSize;
382 mshr->pkt->data = new uint8_t[pkt->actualSize];
383 memcpy(mshr->pkt->data, pkt->data, pkt->actualSize);
384 } else {
385 #endif
386 memcpy(mshr->pkt->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(), pkt->getSize());
387 //{
388
389 if (wb.isFull()) {
390 cache->setBlocked(Blocked_NoWBBuffers);
391 }
392
393 cache->setMasterRequest(Request_WB, time);
394
395 return mshr;
396 }
397
398
399 /**
400 * @todo Remove SW prefetches on mshr hits.
401 */
402 void
403 MissQueue::handleMiss(Packet * &pkt, int blkSize, Tick time)
404 {
405 // if (!cache->isTopLevel())
406 if (prefetchMiss) prefetcher->handleMiss(pkt, time);
407
408 int size = blkSize;
409 Addr blkAddr = pkt->getAddr() & ~(Addr)(blkSize-1);
410 MSHR* mshr = NULL;
411 if (!pkt->req->isUncacheable()) {
412 mshr = mq.findMatch(blkAddr, pkt->req->getAsid());
413 if (mshr) {
414 //@todo remove hw_pf here
415 mshr_hits[pkt->cmdToIndex()][pkt->req->getThreadNum()]++;
416 if (mshr->threadNum != pkt->req->getThreadNum()) {
417 mshr->threadNum = -1;
418 }
419 mq.allocateTarget(mshr, pkt);
420 if (mshr->pkt->isNoAllocate() && !pkt->isNoAllocate()) {
421 //We are adding an allocate after a no-allocate
422 mshr->pkt->flags &= ~NO_ALLOCATE;
423 }
424 if (mshr->getNumTargets() == numTarget) {
425 noTargetMSHR = mshr;
426 cache->setBlocked(Blocked_NoTargets);
427 mq.moveToFront(mshr);
428 }
429 return;
430 }
431 if (pkt->isNoAllocate()) {
432 //Count no-allocate requests differently
433 mshr_no_allocate_misses++;
434 }
435 else {
436 mshr_misses[pkt->cmdToIndex()][pkt->req->getThreadNum()]++;
437 }
438 } else {
439 //Count uncacheable accesses
440 mshr_uncacheable[pkt->cmdToIndex()][pkt->req->getThreadNum()]++;
441 size = pkt->getSize();
442 }
443 if (pkt->isWrite() && (pkt->req->isUncacheable() || !writeAllocate ||
444 !pkt->needsResponse())) {
445 /**
446 * @todo Add write merging here.
447 */
448 mshr = allocateWrite(pkt, pkt->getSize(), time);
449 return;
450 }
451
452 mshr = allocateMiss(pkt, size, time);
453 }
454
455 MSHR*
456 MissQueue::fetchBlock(Addr addr, int asid, int blk_size, Tick time,
457 Packet * &target)
458 {
459 Addr blkAddr = addr & ~(Addr)(blk_size - 1);
460 assert(mq.findMatch(addr, asid) == NULL);
461 MSHR *mshr = mq.allocateFetch(blkAddr, asid, blk_size, target);
462 mshr->order = order++;
463 mshr->pkt->flags |= CACHE_LINE_FILL;
464 if (mq.isFull()) {
465 cache->setBlocked(Blocked_NoMSHRs);
466 }
467 cache->setMasterRequest(Request_MSHR, time);
468 return mshr;
469 }
470
471 Packet *
472 MissQueue::getPacket()
473 {
474 Packet * pkt = mq.getReq();
475 if (((wb.isFull() && wb.inServiceMSHRs == 0) || !pkt ||
476 pkt->time > curTick) && wb.havePending()) {
477 pkt = wb.getReq();
478 // Need to search for earlier miss.
479 MSHR *mshr = mq.findPending(pkt);
480 if (mshr && mshr->order < ((MSHR*)(pkt->senderState))->order) {
481 // Service misses in order until conflict is cleared.
482 return mq.getReq();
483 }
484 }
485 if (pkt) {
486 MSHR* mshr = wb.findPending(pkt);
487 if (mshr /*&& mshr->order < pkt->senderState->order*/) {
488 // The only way this happens is if we are
489 // doing a write and we didn't have permissions
490 // then subsequently saw a writeback(owned got evicted)
491 // We need to make sure to perform the writeback first
492 // To preserve the dirty data, then we can issue the write
493 return wb.getReq();
494 }
495 }
496 else if (!mq.isFull()){
497 //If we have a miss queue slot, we can try a prefetch
498 pkt = prefetcher->getPacket();
499 if (pkt) {
500 //Update statistic on number of prefetches issued (hwpf_mshr_misses)
501 mshr_misses[pkt->cmdToIndex()][pkt->req->getThreadNum()]++;
502 //It will request the bus for the future, but should clear that immedieatley
503 allocateMiss(pkt, pkt->getSize(), curTick);
504 pkt = mq.getReq();
505 assert(pkt); //We should get back a req b/c we just put one in
506 }
507 }
508 return pkt;
509 }
510
511 void
512 MissQueue::setBusCmd(Packet * &pkt, Packet::Command cmd)
513 {
514 assert(pkt->senderState != 0);
515 MSHR * mshr = (MSHR*)pkt->senderState;
516 mshr->originalCmd = pkt->cmd;
517 if (pkt->isCacheFill() || pkt->isNoAllocate())
518 pkt->cmd = cmd;
519 }
520
521 void
522 MissQueue::restoreOrigCmd(Packet * &pkt)
523 {
524 pkt->cmd = ((MSHR*)(pkt->senderState))->originalCmd;
525 }
526
527 void
528 MissQueue::markInService(Packet * &pkt)
529 {
530 assert(pkt->senderState != 0);
531 bool unblock = false;
532 BlockedCause cause = NUM_BLOCKED_CAUSES;
533
534 /**
535 * @todo Should include MSHRQueue pointer in MSHR to select the correct
536 * one.
537 */
538 if ((!pkt->isCacheFill() && pkt->isWrite())) {
539 // Forwarding a write/ writeback, don't need to change
540 // the command
541 unblock = wb.isFull();
542 wb.markInService((MSHR*)pkt->senderState);
543 if (!wb.havePending()){
544 cache->clearMasterRequest(Request_WB);
545 }
546 if (unblock) {
547 // Do we really unblock?
548 unblock = !wb.isFull();
549 cause = Blocked_NoWBBuffers;
550 }
551 } else {
552 unblock = mq.isFull();
553 mq.markInService((MSHR*)pkt->senderState);
554 if (!mq.havePending()){
555 cache->clearMasterRequest(Request_MSHR);
556 }
557 if (((MSHR*)(pkt->senderState))->originalCmd == Packet::HardPFReq) {
558 DPRINTF(HWPrefetch, "%s:Marking a HW_PF in service\n",
559 cache->name());
560 //Also clear pending if need be
561 if (!prefetcher->havePending())
562 {
563 cache->clearMasterRequest(Request_PF);
564 }
565 }
566 if (unblock) {
567 unblock = !mq.isFull();
568 cause = Blocked_NoMSHRs;
569 }
570 }
571 if (unblock) {
572 cache->clearBlocked(cause);
573 }
574 }
575
576
577 void
578 MissQueue::handleResponse(Packet * &pkt, Tick time)
579 {
580 MSHR* mshr = (MSHR*)pkt->senderState;
581 if (((MSHR*)(pkt->senderState))->originalCmd == Packet::HardPFReq) {
582 DPRINTF(HWPrefetch, "%s:Handling the response to a HW_PF\n",
583 cache->name());
584 }
585 #ifndef NDEBUG
586 int num_targets = mshr->getNumTargets();
587 #endif
588
589 bool unblock = false;
590 bool unblock_target = false;
591 BlockedCause cause = NUM_BLOCKED_CAUSES;
592
593 if (pkt->isCacheFill() && !pkt->isNoAllocate()) {
594 mshr_miss_latency[mshr->originalCmd][pkt->req->getThreadNum()] +=
595 curTick - pkt->time;
596 // targets were handled in the cache tags
597 if (mshr == noTargetMSHR) {
598 // we always clear at least one target
599 unblock_target = true;
600 cause = Blocked_NoTargets;
601 noTargetMSHR = NULL;
602 }
603
604 if (mshr->hasTargets()) {
605 // Didn't satisfy all the targets, need to resend
606 Packet::Command cmd = mshr->getTarget()->cmd;
607 mq.markPending(mshr, cmd);
608 mshr->order = order++;
609 cache->setMasterRequest(Request_MSHR, time);
610 }
611 else {
612 unblock = mq.isFull();
613 mq.deallocate(mshr);
614 if (unblock) {
615 unblock = !mq.isFull();
616 cause = Blocked_NoMSHRs;
617 }
618 }
619 } else {
620 if (pkt->req->isUncacheable()) {
621 mshr_uncacheable_lat[pkt->cmd][pkt->req->getThreadNum()] +=
622 curTick - pkt->time;
623 }
624 if (mshr->hasTargets() && pkt->req->isUncacheable()) {
625 // Should only have 1 target if we had any
626 assert(num_targets == 1);
627 Packet * target = mshr->getTarget();
628 mshr->popTarget();
629 if (pkt->isRead()) {
630 memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(),
631 target->getSize());
632 }
633 cache->respond(target, time);
634 assert(!mshr->hasTargets());
635 }
636 else if (mshr->hasTargets()) {
637 //Must be a no_allocate with possibly more than one target
638 assert(mshr->pkt->isNoAllocate());
639 while (mshr->hasTargets()) {
640 Packet * target = mshr->getTarget();
641 mshr->popTarget();
642 if (pkt->isRead()) {
643 memcpy(target->getPtr<uint8_t>(), pkt->getPtr<uint8_t>(),
644 target->getSize());
645 }
646 cache->respond(target, time);
647 }
648 }
649
650 if (pkt->isWrite()) {
651 // If the wrtie buffer is full, we might unblock now
652 unblock = wb.isFull();
653 wb.deallocate(mshr);
654 if (unblock) {
655 // Did we really unblock?
656 unblock = !wb.isFull();
657 cause = Blocked_NoWBBuffers;
658 }
659 } else {
660 unblock = mq.isFull();
661 mq.deallocate(mshr);
662 if (unblock) {
663 unblock = !mq.isFull();
664 cause = Blocked_NoMSHRs;
665 }
666 }
667 }
668 if (unblock || unblock_target) {
669 cache->clearBlocked(cause);
670 }
671 }
672
673 void
674 MissQueue::squash(int threadNum)
675 {
676 bool unblock = false;
677 BlockedCause cause = NUM_BLOCKED_CAUSES;
678
679 if (noTargetMSHR && noTargetMSHR->threadNum == threadNum) {
680 noTargetMSHR = NULL;
681 unblock = true;
682 cause = Blocked_NoTargets;
683 }
684 if (mq.isFull()) {
685 unblock = true;
686 cause = Blocked_NoMSHRs;
687 }
688 mq.squash(threadNum);
689 if (!mq.havePending()) {
690 cache->clearMasterRequest(Request_MSHR);
691 }
692 if (unblock && !mq.isFull()) {
693 cache->clearBlocked(cause);
694 }
695
696 }
697
698 MSHR*
699 MissQueue::findMSHR(Addr addr, int asid) const
700 {
701 return mq.findMatch(addr,asid);
702 }
703
704 bool
705 MissQueue::findWrites(Addr addr, int asid, vector<MSHR*> &writes) const
706 {
707 return wb.findMatches(addr,asid,writes);
708 }
709
710 void
711 MissQueue::doWriteback(Addr addr, int asid,
712 int size, uint8_t *data, bool compressed)
713 {
714 // Generate request
715 Request * req = new Request(addr, size, 0);
716 Packet * pkt = new Packet(req, Packet::Writeback, -1);
717 uint8_t *new_data = new uint8_t[size];
718 pkt->dataDynamicArray<uint8_t>(new_data);
719 if (data) {
720 memcpy(pkt->getPtr<uint8_t>(), data, size);
721 }
722
723 if (compressed) {
724 pkt->flags |= COMPRESSED;
725 }
726
727 ///All writebacks charged to same thread @todo figure this out
728 writebacks[pkt->req->getThreadNum()]++;
729
730 allocateWrite(pkt, 0, curTick);
731 }
732
733
734 void
735 MissQueue::doWriteback(Packet * &pkt)
736 {
737 writebacks[pkt->req->getThreadNum()]++;
738 allocateWrite(pkt, 0, curTick);
739 }
740
741
742 MSHR*
743 MissQueue::allocateTargetList(Addr addr, int asid)
744 {
745 MSHR* mshr = mq.allocateTargetList(addr, asid, blkSize);
746 mshr->pkt->flags |= CACHE_LINE_FILL;
747 if (mq.isFull()) {
748 cache->setBlocked(Blocked_NoMSHRs);
749 }
750 return mshr;
751 }
752
753 bool
754 MissQueue::havePending()
755 {
756 return mq.havePending() || wb.havePending() || prefetcher->havePending();
757 }