43 #ifndef __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
44 #define __CPU_O3_MEM_DEP_UNIT_IMPL_HH__
50 #include "debug/MemDepUnit.hh"
51 #include "params/DerivO3CPU.hh"
53 template <
class MemDepPred,
class Impl>
55 : loadBarrier(false), loadBarrierSN(0), storeBarrier(false),
56 storeBarrierSN(0), iqPtr(NULL)
60 template <
class MemDepPred,
class Impl>
62 : _name(params->
name +
".memdepunit"),
63 depPred(params->store_set_clear_period, params->SSITSize,
65 loadBarrier(false), loadBarrierSN(0), storeBarrier(false),
66 storeBarrierSN(0), iqPtr(NULL)
71 template <
class MemDepPred,
class Impl>
74 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
76 ListIt inst_list_it = instList[tid].begin();
80 while (!instList[tid].empty()) {
81 hash_it = memDepHash.find((*inst_list_it)->seqNum);
83 assert(hash_it != memDepHash.end());
85 memDepHash.erase(hash_it);
87 instList[tid].erase(inst_list_it++);
92 assert(MemDepEntry::memdep_count == 0);
96 template <
class MemDepPred,
class Impl>
102 _name =
csprintf(
"%s.memDep%d", params->name, tid);
105 depPred.init(params->store_set_clear_period, params->SSITSize,
109 template <
class MemDepPred,
class Impl>
114 .name(
name() +
".insertedLoads")
115 .desc(
"Number of loads inserted to the mem dependence unit.");
118 .name(
name() +
".insertedStores")
119 .desc(
"Number of stores inserted to the mem dependence unit.");
122 .name(
name() +
".conflictingLoads")
123 .desc(
"Number of conflicting loads.");
126 .name(
name() +
".conflictingStores")
127 .desc(
"Number of conflicting stores.");
130 template <
class MemDepPred,
class Impl>
134 bool drained = instsToReplay.empty()
135 && memDepHash.empty()
136 && instsToReplay.empty();
137 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
138 drained = drained && instList[
i].empty();
143 template <
class MemDepPred,
class Impl>
147 assert(instsToReplay.empty());
148 assert(memDepHash.empty());
149 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
150 assert(instList[
i].empty());
151 assert(instsToReplay.empty());
152 assert(memDepHash.empty());
155 template <
class MemDepPred,
class Impl>
160 loadBarrier = storeBarrier =
false;
161 loadBarrierSN = storeBarrierSN = 0;
165 template <
class MemDepPred,
class Impl>
172 template <
class MemDepPred,
class Impl>
184 MemDepEntry::memdep_insert++;
187 instList[tid].push_back(inst);
189 inst_entry->listIt = --(instList[tid].end());
194 if (inst->isLoad() && loadBarrier) {
197 producing_store = loadBarrierSN;
198 }
else if (inst->isStore() && storeBarrier) {
201 producing_store = storeBarrierSN;
203 producing_store = depPred.checkInst(inst->instAddr());
209 if (producing_store != 0) {
211 MemDepHashIt hash_it = memDepHash.find(producing_store);
213 if (hash_it != memDepHash.end()) {
214 store_entry = (*hash_it).second;
223 "%s [sn:%lli].\n", inst->pcState(), inst->seqNum);
225 inst_entry->memDepReady =
true;
227 if (inst->readyToIssue()) {
228 inst_entry->regsReady =
true;
230 moveToReady(inst_entry);
235 "inst PC %s is dependent on [sn:%lli].\n",
236 inst->pcState(), producing_store);
238 if (inst->readyToIssue()) {
239 inst_entry->regsReady =
true;
243 inst->clearCanIssue();
246 store_entry->dependInsts.push_back(inst_entry);
248 if (inst->isLoad()) {
255 if (inst->isStore()) {
257 inst->pcState(), inst->seqNum);
259 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
262 }
else if (inst->isLoad()) {
265 panic(
"Unknown type! (most likely a barrier).");
269 template <
class MemDepPred,
class Impl>
281 MemDepEntry::memdep_insert++;
285 instList[tid].push_back(inst);
287 inst_entry->listIt = --(instList[tid].end());
291 if (inst->isStore()) {
293 inst->pcState(), inst->seqNum);
295 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
298 }
else if (inst->isLoad()) {
301 panic(
"Unknown type! (most likely a barrier).");
305 template <
class MemDepPred,
class Impl>
311 if (barr_inst->isMemBarrier()) {
313 loadBarrierSN = barr_sn;
315 storeBarrierSN = barr_sn;
317 barr_inst->pcState(),barr_sn);
318 }
else if (barr_inst->isWriteBarrier()) {
320 storeBarrierSN = barr_sn;
324 ThreadID tid = barr_inst->threadNumber;
326 MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(barr_inst);
332 MemDepEntry::memdep_insert++;
336 instList[tid].push_back(barr_inst);
338 inst_entry->listIt = --(instList[tid].end());
341 template <
class MemDepPred,
class Impl>
346 "instruction PC %s [sn:%lli].\n",
347 inst->pcState(), inst->seqNum);
351 inst_entry->regsReady =
true;
353 if (inst_entry->memDepReady) {
355 "dependencies resolved, adding it to the ready list.\n");
357 moveToReady(inst_entry);
360 "memory dependency.\n");
364 template <
class MemDepPred,
class Impl>
369 "instruction PC %s as ready [sn:%lli].\n",
370 inst->pcState(), inst->seqNum);
374 moveToReady(inst_entry);
377 template <
class MemDepPred,
class Impl>
381 instsToReplay.push_back(inst);
384 template <
class MemDepPred,
class Impl>
391 while (!instsToReplay.empty()) {
392 temp_inst = instsToReplay.front();
397 temp_inst->pcState(), temp_inst->seqNum);
399 moveToReady(inst_entry);
401 instsToReplay.pop_front();
405 template <
class MemDepPred,
class Impl>
410 inst->pcState(), inst->seqNum);
417 assert(hash_it != memDepHash.end());
419 instList[tid].erase((*hash_it).second->listIt);
421 (*hash_it).second = NULL;
423 memDepHash.erase(hash_it);
425 MemDepEntry::memdep_erase++;
429 template <
class MemDepPred,
class Impl>
433 wakeDependents(inst);
439 if (inst->isMemBarrier()) {
440 if (loadBarrierSN == barr_sn)
442 if (storeBarrierSN == barr_sn)
443 storeBarrier =
false;
444 }
else if (inst->isWriteBarrier()) {
445 if (storeBarrierSN == barr_sn)
446 storeBarrier =
false;
450 template <
class MemDepPred,
class Impl>
455 if (!inst->isStore() && !inst->isMemBarrier() && !inst->isWriteBarrier()) {
461 for (
int i = 0;
i < inst_entry->dependInsts.size(); ++
i ) {
464 if (!woken_inst->inst) {
471 woken_inst->inst->seqNum);
473 if (woken_inst->regsReady && !woken_inst->squashed) {
474 moveToReady(woken_inst);
476 woken_inst->memDepReady =
true;
480 inst_entry->dependInsts.clear();
483 template <
class MemDepPred,
class Impl>
488 if (!instsToReplay.empty()) {
489 ListIt replay_it = instsToReplay.begin();
490 while (replay_it != instsToReplay.end()) {
491 if ((*replay_it)->threadNumber == tid &&
492 (*replay_it)->seqNum > squashed_num) {
493 instsToReplay.erase(replay_it++);
500 ListIt squash_it = instList[tid].end();
505 while (!instList[tid].empty() &&
506 (*squash_it)->seqNum > squashed_num) {
509 (*squash_it)->seqNum);
511 if ((*squash_it)->seqNum == loadBarrierSN)
514 if ((*squash_it)->seqNum == storeBarrierSN)
515 storeBarrier =
false;
517 hash_it = memDepHash.find((*squash_it)->seqNum);
519 assert(hash_it != memDepHash.end());
521 (*hash_it).second->squashed =
true;
523 (*hash_it).second = NULL;
525 memDepHash.erase(hash_it);
527 MemDepEntry::memdep_erase++;
530 instList[tid].erase(squash_it--);
534 depPred.squash(squashed_num, tid);
537 template <
class MemDepPred,
class Impl>
543 " load: %#x, store: %#x\n", violating_load->instAddr(),
544 store_inst->instAddr());
546 depPred.violation(store_inst->instAddr(), violating_load->instAddr());
549 template <
class MemDepPred,
class Impl>
554 inst->instAddr(), inst->seqNum);
556 depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
559 template <
class MemDepPred,
class Impl>
565 assert(hash_it != memDepHash.end());
567 return (*hash_it).second;
570 template <
class MemDepPred,
class Impl>
575 "to the ready list.\n", woken_inst_entry->inst->seqNum);
577 assert(!woken_inst_entry->squashed);
579 iqPtr->addReadyMemInst(woken_inst_entry->inst);
583 template <
class MemDepPred,
class Impl>
587 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
588 cprintf(
"Instruction list %i size: %i\n",
589 tid, instList[tid].
size());
591 ListIt inst_list_it = instList[tid].begin();
594 while (inst_list_it != instList[tid].end()) {
595 cprintf(
"Instruction:%i\nPC: %s\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
597 num, (*inst_list_it)->pcState(),
598 (*inst_list_it)->seqNum,
599 (*inst_list_it)->threadNumber,
600 (*inst_list_it)->isIssued(),
601 (*inst_list_it)->isSquashed());
607 cprintf(
"Memory dependence hash size: %i\n", memDepHash.size());
610 cprintf(
"Memory dependence entries: %i\n", MemDepEntry::memdep_count);
614 #endif//__CPU_O3_MEM_DEP_UNIT_IMPL_HH__
const std::string & name()
std::shared_ptr< MemDepEntry > MemDepEntryPtr
void violation(DynInstPtr &store_inst, DynInstPtr &violating_load)
Indicates an ordering violation between a store and a younger load.
std::list< DynInstPtr >::iterator ListIt
void regStats()
Registers statistics.
void replay()
Replays all instructions that have been rescheduled by moving them to the ready list.
void setIQ(InstructionQueue< Impl > *iq_ptr)
Sets the pointer to the IQ.
void wakeDependents(DynInstPtr &inst)
Wakes any dependents of a memory instruction.
~MemDepUnit()
Frees up any memory allocated.
void completed(DynInstPtr &inst)
Completes a memory instruction.
void takeOverFrom()
Takes over from another CPU's thread.
std::string csprintf(const char *format, const Args &...args)
Impl::DynInstPtr DynInstPtr
void nonSpecInstReady(DynInstPtr &inst)
Indicate that a non-speculative instruction is ready.
void insert(DynInstPtr &inst)
Inserts a memory instruction.
void moveToReady(MemDepEntryPtr &ready_inst_entry)
Moves an entry to the ready list.
void dumpLists()
Debugging function to dump the lists of instructions.
MemDepEntryPtr & findInHash(const DynInstPtr &inst)
Finds the memory dependence entry in the hash map.
void regsReady(DynInstPtr &inst)
Indicate that an instruction has its registers ready.
void insertNonSpec(DynInstPtr &inst)
Inserts a non-speculative memory instruction.
Memory dependency unit class.
int16_t ThreadID
Thread index/ID type.
void init(DerivO3CPUParams *params, ThreadID tid)
Initializes the unit with parameters and a thread id.
void insertBarrier(DynInstPtr &barr_inst)
Inserts a barrier instruction.
void issue(DynInstPtr &inst)
Issues the given instruction.
void squash(const InstSeqNum &squashed_num, ThreadID tid)
Squashes all instructions up until a given sequence number for a specific thread. ...
void drainSanityCheck() const
Perform sanity checks after a drain.
void reschedule(DynInstPtr &inst)
Reschedules an instruction to be re-executed.
bool isDrained() const
Determine if we are drained.
void completeBarrier(DynInstPtr &inst)
Completes a barrier instruction.
MemDepUnit()
Empty constructor.
A standard instruction queue class.
void cprintf(const char *format, const Args &...args)
MemDepHash::iterator MemDepHashIt