41 #ifndef __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
42 #define __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
49 #include "debug/MemDepUnit.hh"
50 #include "params/DerivO3CPU.hh"
52 template <
class MemDepPred,
class Impl>
58 template <
class MemDepPred,
class Impl>
60 : _name(params->
name +
".memdepunit"),
61 depPred(params->store_set_clear_period, params->SSITSize,
68 template <
class MemDepPred,
class Impl>
71 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
73 ListIt inst_list_it = instList[tid].begin();
77 while (!instList[tid].empty()) {
78 hash_it = memDepHash.find((*inst_list_it)->seqNum);
80 assert(hash_it != memDepHash.end());
82 memDepHash.erase(hash_it);
84 instList[tid].erase(inst_list_it++);
89 assert(MemDepEntry::memdep_count == 0);
93 template <
class MemDepPred,
class Impl>
99 _name =
csprintf(
"%s.memDep%d", params->name, tid);
102 depPred.init(params->store_set_clear_period, params->SSITSize,
106 template <
class MemDepPred,
class Impl>
111 .name(
name() +
".insertedLoads")
112 .desc(
"Number of loads inserted to the mem dependence unit.");
115 .name(
name() +
".insertedStores")
116 .desc(
"Number of stores inserted to the mem dependence unit.");
119 .name(
name() +
".conflictingLoads")
120 .desc(
"Number of conflicting loads.");
123 .name(
name() +
".conflictingStores")
124 .desc(
"Number of conflicting stores.");
127 template <
class MemDepPred,
class Impl>
131 bool drained = instsToReplay.empty()
132 && memDepHash.empty()
133 && instsToReplay.empty();
134 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
135 drained = drained && instList[
i].empty();
140 template <
class MemDepPred,
class Impl>
144 assert(instsToReplay.empty());
145 assert(memDepHash.empty());
146 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
147 assert(instList[
i].empty());
148 assert(instsToReplay.empty());
149 assert(memDepHash.empty());
152 template <
class MemDepPred,
class Impl>
157 loadBarrierSNs.clear();
158 storeBarrierSNs.clear();
162 template <
class MemDepPred,
class Impl>
169 template <
class MemDepPred,
class Impl>
177 if (barr_inst->isMemBarrier() || barr_inst->isHtmCmd()) {
178 loadBarrierSNs.insert(barr_sn);
179 storeBarrierSNs.insert(barr_sn);
181 barr_inst->pcState(), barr_sn);
182 }
else if (barr_inst->isWriteBarrier()) {
183 storeBarrierSNs.insert(barr_sn);
185 barr_inst->pcState(), barr_sn);
188 if (loadBarrierSNs.size() || storeBarrierSNs.size()) {
190 "store barriers = %d\n",
191 loadBarrierSNs.size(), storeBarrierSNs.size());
195 template <
class MemDepPred,
class Impl>
207 MemDepEntry::memdep_insert++;
210 instList[tid].push_back(inst);
212 inst_entry->listIt = --(instList[tid].end());
217 if ((inst->isLoad() || inst->isAtomic()) && hasLoadBarrier()) {
219 loadBarrierSNs.size());
220 producing_stores.insert(std::end(producing_stores),
221 std::begin(loadBarrierSNs),
222 std::end(loadBarrierSNs));
223 }
else if ((inst->isStore() || inst->isAtomic()) && hasStoreBarrier()) {
225 storeBarrierSNs.size());
226 producing_stores.insert(std::end(producing_stores),
227 std::begin(storeBarrierSNs),
228 std::end(storeBarrierSNs));
230 InstSeqNum dep = depPred.checkInst(inst->instAddr());
232 producing_stores.push_back(dep);
238 for (
auto producing_store : producing_stores) {
241 MemDepHashIt hash_it = memDepHash.find(producing_store);
243 if (hash_it != memDepHash.end()) {
244 store_entries.push_back((*hash_it).second);
251 if (store_entries.empty()) {
253 "%s [sn:%lli].\n", inst->pcState(), inst->seqNum);
255 assert(inst_entry->memDeps == 0);
257 if (inst->readyToIssue()) {
258 inst_entry->regsReady =
true;
260 moveToReady(inst_entry);
265 for (
auto M5_VAR_USED producing_store : producing_stores)
267 inst->pcState(), producing_store);
269 if (inst->readyToIssue()) {
270 inst_entry->regsReady =
true;
274 inst->clearCanIssue();
277 for (
auto store_entry : store_entries)
278 store_entry->dependInsts.push_back(inst_entry);
280 inst_entry->memDeps = store_entries.size();
282 if (inst->isLoad()) {
290 insertBarrierSN(inst);
292 if (inst->isStore() || inst->isAtomic()) {
294 inst->pcState(), inst->seqNum);
296 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
299 }
else if (inst->isLoad()) {
302 panic(
"Unknown type! (most likely a barrier).");
306 template <
class MemDepPred,
class Impl>
314 if (inst->isStore() || inst->isAtomic()) {
316 inst->pcState(), inst->seqNum);
318 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
321 }
else if (inst->isLoad()) {
324 panic(
"Unknown type! (most likely a barrier).");
328 template <
class MemDepPred,
class Impl>
332 ThreadID tid = barr_inst->threadNumber;
334 MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(barr_inst);
340 MemDepEntry::memdep_insert++;
344 instList[tid].push_back(barr_inst);
346 inst_entry->listIt = --(instList[tid].end());
348 insertBarrierSN(barr_inst);
351 template <
class MemDepPred,
class Impl>
356 "instruction PC %s [sn:%lli].\n",
357 inst->pcState(), inst->seqNum);
361 inst_entry->regsReady =
true;
363 if (inst_entry->memDeps == 0) {
365 "dependencies resolved, adding it to the ready list.\n");
367 moveToReady(inst_entry);
370 "memory dependency.\n");
374 template <
class MemDepPred,
class Impl>
379 "instruction PC %s as ready [sn:%lli].\n",
380 inst->pcState(), inst->seqNum);
384 moveToReady(inst_entry);
387 template <
class MemDepPred,
class Impl>
391 instsToReplay.push_back(inst);
394 template <
class MemDepPred,
class Impl>
401 while (!instsToReplay.empty()) {
402 temp_inst = instsToReplay.front();
407 temp_inst->pcState(), temp_inst->seqNum);
409 moveToReady(inst_entry);
411 instsToReplay.pop_front();
415 template <
class MemDepPred,
class Impl>
420 inst->pcState(), inst->seqNum);
427 assert(hash_it != memDepHash.end());
429 instList[tid].erase((*hash_it).second->listIt);
431 (*hash_it).second = NULL;
433 memDepHash.erase(hash_it);
435 MemDepEntry::memdep_erase++;
439 template <
class MemDepPred,
class Impl>
443 wakeDependents(inst);
447 if (inst->isMemBarrier() || inst->isHtmCmd()) {
448 assert(hasLoadBarrier());
449 assert(hasStoreBarrier());
450 loadBarrierSNs.erase(barr_sn);
451 storeBarrierSNs.erase(barr_sn);
453 inst->pcState(), inst->seqNum);
454 }
else if (inst->isWriteBarrier()) {
455 assert(hasStoreBarrier());
456 storeBarrierSNs.erase(barr_sn);
458 inst->pcState(), inst->seqNum);
462 template <
class MemDepPred,
class Impl>
468 if (!inst->isStore() && !inst->isAtomic() && !inst->isMemBarrier() &&
469 !inst->isWriteBarrier() && !inst->isHtmCmd()) {
475 for (
int i = 0;
i < inst_entry->dependInsts.size(); ++
i ) {
478 if (!woken_inst->inst) {
485 woken_inst->inst->seqNum);
487 assert(woken_inst->memDeps > 0);
488 woken_inst->memDeps -= 1;
490 if ((woken_inst->memDeps == 0) &&
491 woken_inst->regsReady &&
492 !woken_inst->squashed) {
493 moveToReady(woken_inst);
497 inst_entry->dependInsts.clear();
500 template <
class MemDepPred,
class Impl>
505 if (!instsToReplay.empty()) {
506 ListIt replay_it = instsToReplay.begin();
507 while (replay_it != instsToReplay.end()) {
508 if ((*replay_it)->threadNumber == tid &&
509 (*replay_it)->seqNum > squashed_num) {
510 instsToReplay.erase(replay_it++);
517 ListIt squash_it = instList[tid].end();
522 while (!instList[tid].empty() &&
523 (*squash_it)->seqNum > squashed_num) {
526 (*squash_it)->seqNum);
528 loadBarrierSNs.erase((*squash_it)->seqNum);
530 storeBarrierSNs.erase((*squash_it)->seqNum);
532 hash_it = memDepHash.find((*squash_it)->seqNum);
534 assert(hash_it != memDepHash.end());
536 (*hash_it).second->squashed =
true;
538 (*hash_it).second = NULL;
540 memDepHash.erase(hash_it);
542 MemDepEntry::memdep_erase++;
545 instList[tid].erase(squash_it--);
549 depPred.squash(squashed_num, tid);
552 template <
class MemDepPred,
class Impl>
558 " load: %#x, store: %#x\n", violating_load->instAddr(),
559 store_inst->instAddr());
561 depPred.violation(store_inst->instAddr(), violating_load->instAddr());
564 template <
class MemDepPred,
class Impl>
569 inst->instAddr(), inst->seqNum);
571 depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
574 template <
class MemDepPred,
class Impl>
580 assert(hash_it != memDepHash.end());
582 return (*hash_it).second;
585 template <
class MemDepPred,
class Impl>
590 "to the ready list.\n", woken_inst_entry->inst->seqNum);
592 assert(!woken_inst_entry->squashed);
594 iqPtr->addReadyMemInst(woken_inst_entry->inst);
598 template <
class MemDepPred,
class Impl>
602 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
603 cprintf(
"Instruction list %i size: %i\n",
604 tid, instList[tid].size());
606 ListIt inst_list_it = instList[tid].begin();
609 while (inst_list_it != instList[tid].end()) {
610 cprintf(
"Instruction:%i\nPC: %s\n[sn:%llu]\n[tid:%i]\nIssued:%i\n"
612 num, (*inst_list_it)->pcState(),
613 (*inst_list_it)->seqNum,
614 (*inst_list_it)->threadNumber,
615 (*inst_list_it)->isIssued(),
616 (*inst_list_it)->isSquashed());
622 cprintf(
"Memory dependence hash size: %i\n", memDepHash.size());
625 cprintf(
"Memory dependence entries: %i\n", MemDepEntry::memdep_count);
629 #endif//__CPU_O3_MEM_DEP_UNIT_IMPL_HH__