41 #ifndef __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
42 #define __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
51 #include "debug/MemDepUnit.hh"
52 #include "params/DerivO3CPU.hh"
54 template <
class MemDepPred,
class Impl>
61 template <
class MemDepPred,
class Impl>
63 : _name(params.
name +
".memdepunit"),
64 depPred(params.store_set_clear_period, params.SSITSize,
72 template <
class MemDepPred,
class Impl>
75 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
77 ListIt inst_list_it = instList[tid].begin();
81 while (!instList[tid].empty()) {
82 hash_it = memDepHash.find((*inst_list_it)->seqNum);
84 assert(hash_it != memDepHash.end());
86 memDepHash.erase(hash_it);
88 instList[tid].erase(inst_list_it++);
93 assert(MemDepEntry::memdep_count == 0);
97 template <
class MemDepPred,
class Impl>
104 _name =
csprintf(
"%s.memDep%d", params.name, tid);
107 depPred.init(params.store_set_clear_period, params.SSITSize,
110 std::string stats_group_name =
csprintf(
"MemDepUnit__%i", tid);
111 cpu->addStatGroup(stats_group_name.c_str(), &stats);
114 template <
class MemDepPred,
class Impl>
117 :
Stats::Group(parent),
119 "Number of loads inserted to the mem dependence unit."),
121 "Number of stores inserted to the mem dependence unit."),
127 template <
class MemDepPred,
class Impl>
134 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
135 drained = drained &&
instList[
i].empty();
140 template <
class MemDepPred,
class Impl>
146 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
152 template <
class MemDepPred,
class Impl>
162 template <
class MemDepPred,
class Impl>
169 template <
class MemDepPred,
class Impl>
175 if (barr_inst->isReadBarrier() || barr_inst->isHtmCmd())
177 if (barr_inst->isWriteBarrier() || barr_inst->isHtmCmd())
181 const char *barrier_type =
nullptr;
182 if (barr_inst->isReadBarrier() && barr_inst->isWriteBarrier())
183 barrier_type =
"memory";
184 else if (barr_inst->isReadBarrier())
185 barrier_type =
"read";
186 else if (barr_inst->isWriteBarrier())
187 barrier_type =
"write";
191 barrier_type, barr_inst->pcState(), barr_sn);
196 "store barriers = %d\n",
202 template <
class MemDepPred,
class Impl>
214 MemDepEntry::memdep_insert++;
219 inst_entry->listIt = --(
instList[tid].end());
227 producing_stores.insert(std::end(producing_stores),
230 }
else if ((inst->isStore() || inst->isAtomic()) &&
hasStoreBarrier()) {
233 producing_stores.insert(std::end(producing_stores),
239 producing_stores.push_back(dep);
245 for (
auto producing_store : producing_stores) {
251 store_entries.push_back((*hash_it).second);
258 if (store_entries.empty()) {
260 "%s [sn:%lli].\n", inst->pcState(), inst->seqNum);
262 assert(inst_entry->memDeps == 0);
264 if (inst->readyToIssue()) {
265 inst_entry->regsReady =
true;
272 for (M5_VAR_USED
auto producing_store : producing_stores)
274 inst->pcState(), producing_store);
276 if (inst->readyToIssue()) {
277 inst_entry->regsReady =
true;
281 inst->clearCanIssue();
284 for (
auto store_entry : store_entries)
285 store_entry->dependInsts.push_back(inst_entry);
287 inst_entry->memDeps = store_entries.size();
289 if (inst->isLoad()) {
299 if (inst->isStore() || inst->isAtomic()) {
301 inst->pcState(), inst->seqNum);
303 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
306 }
else if (inst->isLoad()) {
309 panic(
"Unknown type! (most likely a barrier).");
313 template <
class MemDepPred,
class Impl>
321 if (inst->isStore() || inst->isAtomic()) {
323 inst->pcState(), inst->seqNum);
325 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
328 }
else if (inst->isLoad()) {
331 panic(
"Unknown type! (most likely a barrier).");
335 template <
class MemDepPred,
class Impl>
339 ThreadID tid = barr_inst->threadNumber;
341 MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(barr_inst);
347 MemDepEntry::memdep_insert++;
353 inst_entry->listIt = --(
instList[tid].end());
358 template <
class MemDepPred,
class Impl>
363 "instruction PC %s [sn:%lli].\n",
364 inst->pcState(), inst->seqNum);
368 inst_entry->regsReady =
true;
370 if (inst_entry->memDeps == 0) {
372 "dependencies resolved, adding it to the ready list.\n");
377 "memory dependency.\n");
381 template <
class MemDepPred,
class Impl>
386 "instruction PC %s as ready [sn:%lli].\n",
387 inst->pcState(), inst->seqNum);
394 template <
class MemDepPred,
class Impl>
401 template <
class MemDepPred,
class Impl>
414 temp_inst->pcState(), temp_inst->seqNum);
422 template <
class MemDepPred,
class Impl>
427 inst->pcState(), inst->seqNum);
436 instList[tid].erase((*hash_it).second->listIt);
438 (*hash_it).second = NULL;
442 MemDepEntry::memdep_erase++;
446 template <
class MemDepPred,
class Impl>
454 if (inst->isWriteBarrier() || inst->isHtmCmd()) {
458 if (inst->isReadBarrier() || inst->isHtmCmd()) {
463 const char *barrier_type =
nullptr;
464 if (inst->isWriteBarrier() && inst->isReadBarrier())
465 barrier_type =
"Memory";
466 else if (inst->isWriteBarrier())
467 barrier_type =
"Write";
468 else if (inst->isReadBarrier())
469 barrier_type =
"Read";
473 barrier_type, inst->pcState(), inst->seqNum);
478 template <
class MemDepPred,
class Impl>
483 if (!inst->isStore() && !inst->isAtomic() && !inst->isReadBarrier() &&
484 !inst->isWriteBarrier() && !inst->isHtmCmd()) {
490 for (
int i = 0;
i < inst_entry->dependInsts.size(); ++
i ) {
493 if (!woken_inst->inst) {
500 woken_inst->inst->seqNum);
502 assert(woken_inst->memDeps > 0);
503 woken_inst->memDeps -= 1;
505 if ((woken_inst->memDeps == 0) &&
506 woken_inst->regsReady &&
507 !woken_inst->squashed) {
512 inst_entry->dependInsts.clear();
515 template <
class MemDepPred,
class Impl>
523 if ((*replay_it)->threadNumber == tid &&
524 (*replay_it)->seqNum > squashed_num) {
538 (*squash_it)->seqNum > squashed_num) {
541 (*squash_it)->seqNum);
547 hash_it =
memDepHash.find((*squash_it)->seqNum);
551 (*hash_it).second->squashed =
true;
553 (*hash_it).second = NULL;
557 MemDepEntry::memdep_erase++;
564 depPred.squash(squashed_num, tid);
567 template <
class MemDepPred,
class Impl>
573 " load: %#x, store: %#x\n", violating_load->instAddr(),
574 store_inst->instAddr());
576 depPred.violation(store_inst->instAddr(), violating_load->instAddr());
579 template <
class MemDepPred,
class Impl>
584 inst->instAddr(), inst->seqNum);
586 depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
589 template <
class MemDepPred,
class Impl>
597 return (*hash_it).second;
600 template <
class MemDepPred,
class Impl>
605 "to the ready list.\n", woken_inst_entry->inst->seqNum);
607 assert(!woken_inst_entry->squashed);
609 iqPtr->addReadyMemInst(woken_inst_entry->inst);
613 template <
class MemDepPred,
class Impl>
617 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
618 cprintf(
"Instruction list %i size: %i\n",
624 while (inst_list_it !=
instList[tid].end()) {
625 cprintf(
"Instruction:%i\nPC: %s\n[sn:%llu]\n[tid:%i]\nIssued:%i\n"
627 num, (*inst_list_it)->pcState(),
628 (*inst_list_it)->seqNum,
629 (*inst_list_it)->threadNumber,
630 (*inst_list_it)->isIssued(),
631 (*inst_list_it)->isSquashed());
640 cprintf(
"Memory dependence entries: %i\n", MemDepEntry::memdep_count);
644 #endif//__CPU_O3_MEM_DEP_UNIT_IMPL_HH__