2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
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.
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.
28 * Authors: Erik Hallnor
34 * Miss and writeback queue definitions.
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"
46 * @todo Remove the +16 from the write buffer constructor once we handle
47 * stalling on writebacks do to compression writes.
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
)
59 MissQueue::regStats(const string
&name
)
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
65 using namespace Stats
;
68 .init(maxThreadsPerCPU
)
69 .name(name
+ ".writebacks")
70 .desc("number of writebacks")
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
);
80 .init(maxThreadsPerCPU
)
81 .name(name
+ "." + cstr
+ "_mshr_hits")
82 .desc("number of " + cstr
+ " MSHR hits")
83 .flags(total
| nozero
| nonan
)
88 .name(name
+ ".demand_mshr_hits")
89 .desc("number of demand (read+write) MSHR hits")
92 demandMshrHits
= mshr_hits
[Packet::ReadReq
] + mshr_hits
[Packet::WriteReq
];
95 .name(name
+ ".overall_mshr_hits")
96 .desc("number of overall MSHR hits")
99 overallMshrHits
= demandMshrHits
+ mshr_hits
[Packet::SoftPFReq
] +
100 mshr_hits
[Packet::HardPFReq
];
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
);
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
)
116 .name(name
+ ".demand_mshr_misses")
117 .desc("number of demand (read+write) MSHR misses")
120 demandMshrMisses
= mshr_misses
[Packet::ReadReq
] + mshr_misses
[Packet::WriteReq
];
123 .name(name
+ ".overall_mshr_misses")
124 .desc("number of overall MSHR misses")
127 overallMshrMisses
= demandMshrMisses
+ mshr_misses
[Packet::SoftPFReq
] +
128 mshr_misses
[Packet::HardPFReq
];
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
);
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
)
143 demandMshrMissLatency
144 .name(name
+ ".demand_mshr_miss_latency")
145 .desc("number of demand (read+write) MSHR miss cycles")
148 demandMshrMissLatency
= mshr_miss_latency
[Packet::ReadReq
]
149 + mshr_miss_latency
[Packet::WriteReq
];
151 overallMshrMissLatency
152 .name(name
+ ".overall_mshr_miss_latency")
153 .desc("number of overall MSHR miss cycles")
156 overallMshrMissLatency
= demandMshrMissLatency
+
157 mshr_miss_latency
[Packet::SoftPFReq
] + mshr_miss_latency
[Packet::HardPFReq
];
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
);
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
)
172 overallMshrUncacheable
173 .name(name
+ ".overall_mshr_uncacheable_misses")
174 .desc("number of overall MSHR uncacheable misses")
177 overallMshrUncacheable
= mshr_uncacheable
[Packet::ReadReq
]
178 + mshr_uncacheable
[Packet::WriteReq
] + mshr_uncacheable
[Packet::SoftPFReq
]
179 + mshr_uncacheable
[Packet::HardPFReq
];
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
);
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
)
194 overallMshrUncacheableLatency
195 .name(name
+ ".overall_mshr_uncacheable_latency")
196 .desc("number of overall MSHR uncacheable cycles")
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
];
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
);
210 mshrAccesses
[access_idx
]
211 .name(name
+ "." + cstr
+ "_mshr_accesses")
212 .desc("number of " + cstr
+ " mshr accesses(hits+misses)")
213 .flags(total
| nozero
| nonan
)
215 mshrAccesses
[access_idx
] =
216 mshr_hits
[access_idx
] + mshr_misses
[access_idx
]
217 + mshr_uncacheable
[access_idx
];
221 .name(name
+ ".demand_mshr_accesses")
222 .desc("number of demand (read+write) mshr accesses")
223 .flags(total
| nozero
| nonan
)
225 demandMshrAccesses
= demandMshrHits
+ demandMshrMisses
;
228 .name(name
+ ".overall_mshr_accesses")
229 .desc("number of overall (read+write) mshr accesses")
230 .flags(total
| nozero
| nonan
)
232 overallMshrAccesses
= overallMshrHits
+ overallMshrMisses
233 + overallMshrUncacheable
;
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
);
241 mshrMissRate
[access_idx
]
242 .name(name
+ "." + cstr
+ "_mshr_miss_rate")
243 .desc("mshr miss rate for " + cstr
+ " accesses")
244 .flags(total
| nozero
| nonan
)
247 mshrMissRate
[access_idx
] =
248 mshr_misses
[access_idx
] / cache
->accesses
[access_idx
];
252 .name(name
+ ".demand_mshr_miss_rate")
253 .desc("mshr miss rate for demand accesses")
256 demandMshrMissRate
= demandMshrMisses
/ cache
->demandAccesses
;
259 .name(name
+ ".overall_mshr_miss_rate")
260 .desc("mshr miss rate for overall accesses")
263 overallMshrMissRate
= overallMshrMisses
/ cache
->overallAccesses
;
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
);
270 avgMshrMissLatency
[access_idx
]
271 .name(name
+ "." + cstr
+ "_avg_mshr_miss_latency")
272 .desc("average " + cstr
+ " mshr miss latency")
273 .flags(total
| nozero
| nonan
)
276 avgMshrMissLatency
[access_idx
] =
277 mshr_miss_latency
[access_idx
] / mshr_misses
[access_idx
];
280 demandAvgMshrMissLatency
281 .name(name
+ ".demand_avg_mshr_miss_latency")
282 .desc("average overall mshr miss latency")
285 demandAvgMshrMissLatency
= demandMshrMissLatency
/ demandMshrMisses
;
287 overallAvgMshrMissLatency
288 .name(name
+ ".overall_avg_mshr_miss_latency")
289 .desc("average overall mshr miss latency")
292 overallAvgMshrMissLatency
= overallMshrMissLatency
/ overallMshrMisses
;
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
);
299 avgMshrUncacheableLatency
[access_idx
]
300 .name(name
+ "." + cstr
+ "_avg_mshr_uncacheable_latency")
301 .desc("average " + cstr
+ " mshr uncacheable latency")
302 .flags(total
| nozero
| nonan
)
305 avgMshrUncacheableLatency
[access_idx
] =
306 mshr_uncacheable_lat
[access_idx
] / mshr_uncacheable
[access_idx
];
309 overallAvgMshrUncacheableLatency
310 .name(name
+ ".overall_avg_mshr_uncacheable_latency")
311 .desc("average overall mshr uncacheable latency")
314 overallAvgMshrUncacheableLatency
= overallMshrUncacheableLatency
/ overallMshrUncacheable
;
317 .init(maxThreadsPerCPU
)
318 .name(name
+ ".mshr_cap_events")
319 .desc("number of times MSHR cap was activated")
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")
331 mshr_no_allocate_misses
332 .name(name
+".no_allocate_misses")
333 .desc("Number of misses that were no-allocate")
339 MissQueue::setCache(BaseCache
*_cache
)
342 blkSize
= cache
->getBlockSize();
346 MissQueue::setPrefetcher(BasePrefetcher
*_prefetcher
)
348 prefetcher
= _prefetcher
;
352 MissQueue::allocateMiss(Packet
* &pkt
, int size
, Tick time
)
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
;
361 cache
->setBlocked(Blocked_NoMSHRs
);
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
);
372 MissQueue::allocateWrite(Packet
* &pkt
, int size
, Tick time
)
374 MSHR
* mshr
= wb
.allocate(pkt
,pkt
->getSize());
375 mshr
->order
= order
++;
377 //REMOVING COMPRESSION FOR NOW
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
);
386 memcpy(mshr
->pkt
->getPtr
<uint8_t>(), pkt
->getPtr
<uint8_t>(), pkt
->getSize());
390 cache
->setBlocked(Blocked_NoWBBuffers
);
393 cache
->setMasterRequest(Request_WB
, time
);
400 * @todo Remove SW prefetches on mshr hits.
403 MissQueue::handleMiss(Packet
* &pkt
, int blkSize
, Tick time
)
405 // if (!cache->isTopLevel())
406 if (prefetchMiss
) prefetcher
->handleMiss(pkt
, time
);
409 Addr blkAddr
= pkt
->getAddr() & ~(Addr
)(blkSize
-1);
411 if (!pkt
->req
->isUncacheable()) {
412 mshr
= mq
.findMatch(blkAddr
, pkt
->req
->getAsid());
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;
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
;
424 if (mshr
->getNumTargets() == numTarget
) {
426 cache
->setBlocked(Blocked_NoTargets
);
427 mq
.moveToFront(mshr
);
431 if (pkt
->isNoAllocate()) {
432 //Count no-allocate requests differently
433 mshr_no_allocate_misses
++;
436 mshr_misses
[pkt
->cmdToIndex()][pkt
->req
->getThreadNum()]++;
439 //Count uncacheable accesses
440 mshr_uncacheable
[pkt
->cmdToIndex()][pkt
->req
->getThreadNum()]++;
441 size
= pkt
->getSize();
443 if (pkt
->isWrite() && (pkt
->req
->isUncacheable() || !writeAllocate
||
444 !pkt
->needsResponse())) {
446 * @todo Add write merging here.
448 mshr
= allocateWrite(pkt
, pkt
->getSize(), time
);
452 mshr
= allocateMiss(pkt
, size
, time
);
456 MissQueue::fetchBlock(Addr addr
, int asid
, int blk_size
, Tick time
,
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
;
465 cache
->setBlocked(Blocked_NoMSHRs
);
467 cache
->setMasterRequest(Request_MSHR
, time
);
472 MissQueue::getPacket()
474 Packet
* pkt
= mq
.getReq();
475 if (((wb
.isFull() && wb
.inServiceMSHRs
== 0) || !pkt
||
476 pkt
->time
> curTick
) && wb
.havePending()) {
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.
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
496 else if (!mq
.isFull()){
497 //If we have a miss queue slot, we can try a prefetch
498 pkt
= prefetcher
->getPacket();
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
);
505 assert(pkt
); //We should get back a req b/c we just put one in
512 MissQueue::setBusCmd(Packet
* &pkt
, Packet::Command cmd
)
514 assert(pkt
->senderState
!= 0);
515 MSHR
* mshr
= (MSHR
*)pkt
->senderState
;
516 mshr
->originalCmd
= pkt
->cmd
;
517 if (pkt
->isCacheFill() || pkt
->isNoAllocate())
522 MissQueue::restoreOrigCmd(Packet
* &pkt
)
524 pkt
->cmd
= ((MSHR
*)(pkt
->senderState
))->originalCmd
;
528 MissQueue::markInService(Packet
* &pkt
)
530 assert(pkt
->senderState
!= 0);
531 bool unblock
= false;
532 BlockedCause cause
= NUM_BLOCKED_CAUSES
;
535 * @todo Should include MSHRQueue pointer in MSHR to select the correct
538 if ((!pkt
->isCacheFill() && pkt
->isWrite())) {
539 // Forwarding a write/ writeback, don't need to change
541 unblock
= wb
.isFull();
542 wb
.markInService((MSHR
*)pkt
->senderState
);
543 if (!wb
.havePending()){
544 cache
->clearMasterRequest(Request_WB
);
547 // Do we really unblock?
548 unblock
= !wb
.isFull();
549 cause
= Blocked_NoWBBuffers
;
552 unblock
= mq
.isFull();
553 mq
.markInService((MSHR
*)pkt
->senderState
);
554 if (!mq
.havePending()){
555 cache
->clearMasterRequest(Request_MSHR
);
557 if (((MSHR
*)(pkt
->senderState
))->originalCmd
== Packet::HardPFReq
) {
558 DPRINTF(HWPrefetch
, "%s:Marking a HW_PF in service\n",
560 //Also clear pending if need be
561 if (!prefetcher
->havePending())
563 cache
->clearMasterRequest(Request_PF
);
567 unblock
= !mq
.isFull();
568 cause
= Blocked_NoMSHRs
;
572 cache
->clearBlocked(cause
);
578 MissQueue::handleResponse(Packet
* &pkt
, Tick time
)
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",
586 int num_targets
= mshr
->getNumTargets();
589 bool unblock
= false;
590 bool unblock_target
= false;
591 BlockedCause cause
= NUM_BLOCKED_CAUSES
;
593 if (pkt
->isCacheFill() && !pkt
->isNoAllocate()) {
594 mshr_miss_latency
[mshr
->originalCmd
][pkt
->req
->getThreadNum()] +=
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
;
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
);
612 unblock
= mq
.isFull();
615 unblock
= !mq
.isFull();
616 cause
= Blocked_NoMSHRs
;
620 if (pkt
->req
->isUncacheable()) {
621 mshr_uncacheable_lat
[pkt
->cmd
][pkt
->req
->getThreadNum()] +=
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();
630 memcpy(target
->getPtr
<uint8_t>(), pkt
->getPtr
<uint8_t>(),
633 cache
->respond(target
, time
);
634 assert(!mshr
->hasTargets());
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();
643 memcpy(target
->getPtr
<uint8_t>(), pkt
->getPtr
<uint8_t>(),
646 cache
->respond(target
, time
);
650 if (pkt
->isWrite()) {
651 // If the wrtie buffer is full, we might unblock now
652 unblock
= wb
.isFull();
655 // Did we really unblock?
656 unblock
= !wb
.isFull();
657 cause
= Blocked_NoWBBuffers
;
660 unblock
= mq
.isFull();
663 unblock
= !mq
.isFull();
664 cause
= Blocked_NoMSHRs
;
668 if (unblock
|| unblock_target
) {
669 cache
->clearBlocked(cause
);
674 MissQueue::squash(int threadNum
)
676 bool unblock
= false;
677 BlockedCause cause
= NUM_BLOCKED_CAUSES
;
679 if (noTargetMSHR
&& noTargetMSHR
->threadNum
== threadNum
) {
682 cause
= Blocked_NoTargets
;
686 cause
= Blocked_NoMSHRs
;
688 mq
.squash(threadNum
);
689 if (!mq
.havePending()) {
690 cache
->clearMasterRequest(Request_MSHR
);
692 if (unblock
&& !mq
.isFull()) {
693 cache
->clearBlocked(cause
);
699 MissQueue::findMSHR(Addr addr
, int asid
) const
701 return mq
.findMatch(addr
,asid
);
705 MissQueue::findWrites(Addr addr
, int asid
, vector
<MSHR
*> &writes
) const
707 return wb
.findMatches(addr
,asid
,writes
);
711 MissQueue::doWriteback(Addr addr
, int asid
,
712 int size
, uint8_t *data
, bool compressed
)
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
);
720 memcpy(pkt
->getPtr
<uint8_t>(), data
, size
);
724 pkt
->flags
|= COMPRESSED
;
727 ///All writebacks charged to same thread @todo figure this out
728 writebacks
[pkt
->req
->getThreadNum()]++;
730 allocateWrite(pkt
, 0, curTick
);
735 MissQueue::doWriteback(Packet
* &pkt
)
737 writebacks
[pkt
->req
->getThreadNum()]++;
738 allocateWrite(pkt
, 0, curTick
);
743 MissQueue::allocateTargetList(Addr addr
, int asid
)
745 MSHR
* mshr
= mq
.allocateTargetList(addr
, asid
, blkSize
);
746 mshr
->pkt
->flags
|= CACHE_LINE_FILL
;
748 cache
->setBlocked(Blocked_NoMSHRs
);
754 MissQueue::havePending()
756 return mq
.havePending() || wb
.havePending() || prefetcher
->havePending();