41 #ifndef __CPU_O3_MEM_DEP_UNIT_IMPL_HH__ 42 #define __CPU_O3_MEM_DEP_UNIT_IMPL_HH__ 48 #include "debug/MemDepUnit.hh" 49 #include "params/DerivO3CPU.hh" 51 template <
class MemDepPred,
class Impl>
53 : loadBarrier(false), loadBarrierSN(0), storeBarrier(false),
54 storeBarrierSN(0), iqPtr(NULL)
58 template <
class MemDepPred,
class Impl>
61 depPred(params->store_set_clear_period, params->SSITSize,
69 template <
class MemDepPred,
class Impl>
72 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
79 hash_it =
memDepHash.find((*inst_list_it)->seqNum);
90 assert(MemDepEntry::memdep_count == 0);
94 template <
class MemDepPred,
class Impl>
103 depPred.init(params->store_set_clear_period, params->SSITSize,
107 template <
class MemDepPred,
class Impl>
113 .
desc(
"Number of loads inserted to the mem dependence unit.");
117 .
desc(
"Number of stores inserted to the mem dependence unit.");
121 .
desc(
"Number of conflicting loads.");
124 .
name(
name() +
".conflictingStores")
125 .
desc(
"Number of conflicting stores.");
128 template <
class MemDepPred,
class Impl>
135 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
136 drained = drained &&
instList[
i].empty();
141 template <
class MemDepPred,
class Impl>
147 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
153 template <
class MemDepPred,
class Impl>
163 template <
class MemDepPred,
class Impl>
170 template <
class MemDepPred,
class Impl>
182 MemDepEntry::memdep_insert++;
187 inst_entry->listIt = --(
instList[tid].end());
192 if ((inst->isLoad() || inst->isAtomic()) &&
loadBarrier) {
196 }
else if ((inst->isStore() || inst->isAtomic()) &&
storeBarrier) {
201 producing_store =
depPred.checkInst(inst->instAddr());
207 if (producing_store != 0) {
212 store_entry = (*hash_it).second;
221 "%s [sn:%lli].\n", inst->pcState(), inst->seqNum);
223 inst_entry->memDepReady =
true;
225 if (inst->readyToIssue()) {
226 inst_entry->regsReady =
true;
233 "inst PC %s is dependent on [sn:%lli].\n",
234 inst->pcState(), producing_store);
236 if (inst->readyToIssue()) {
237 inst_entry->regsReady =
true;
241 inst->clearCanIssue();
244 store_entry->dependInsts.push_back(inst_entry);
246 if (inst->isLoad()) {
253 if (inst->isStore() || inst->isAtomic()) {
255 inst->pcState(), inst->seqNum);
257 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
260 }
else if (inst->isLoad()) {
263 panic(
"Unknown type! (most likely a barrier).");
267 template <
class MemDepPred,
class Impl>
279 MemDepEntry::memdep_insert++;
285 inst_entry->listIt = --(
instList[tid].end());
289 if (inst->isStore() || inst->isAtomic()) {
291 inst->pcState(), inst->seqNum);
293 depPred.insertStore(inst->instAddr(), inst->seqNum, inst->threadNumber);
296 }
else if (inst->isLoad()) {
299 panic(
"Unknown type! (most likely a barrier).");
303 template <
class MemDepPred,
class Impl>
309 if (barr_inst->isMemBarrier()) {
315 barr_inst->pcState(),barr_sn);
316 }
else if (barr_inst->isWriteBarrier()) {
322 ThreadID tid = barr_inst->threadNumber;
324 MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(barr_inst);
330 MemDepEntry::memdep_insert++;
336 inst_entry->listIt = --(
instList[tid].end());
339 template <
class MemDepPred,
class Impl>
344 "instruction PC %s [sn:%lli].\n",
345 inst->pcState(), inst->seqNum);
349 inst_entry->regsReady =
true;
351 if (inst_entry->memDepReady) {
353 "dependencies resolved, adding it to the ready list.\n");
358 "memory dependency.\n");
362 template <
class MemDepPred,
class Impl>
367 "instruction PC %s as ready [sn:%lli].\n",
368 inst->pcState(), inst->seqNum);
375 template <
class MemDepPred,
class Impl>
382 template <
class MemDepPred,
class Impl>
395 temp_inst->pcState(), temp_inst->seqNum);
403 template <
class MemDepPred,
class Impl>
408 inst->pcState(), inst->seqNum);
417 instList[tid].erase((*hash_it).second->listIt);
419 (*hash_it).second = NULL;
423 MemDepEntry::memdep_erase++;
427 template <
class MemDepPred,
class Impl>
437 if (inst->isMemBarrier()) {
442 }
else if (inst->isWriteBarrier()) {
448 template <
class MemDepPred,
class Impl>
453 if (!inst->isStore() && !inst->isAtomic() && !inst->isMemBarrier() &&
454 !inst->isWriteBarrier()) {
460 for (
int i = 0;
i < inst_entry->dependInsts.size(); ++
i ) {
463 if (!woken_inst->inst) {
470 woken_inst->inst->seqNum);
472 if (woken_inst->regsReady && !woken_inst->squashed) {
475 woken_inst->memDepReady =
true;
479 inst_entry->dependInsts.clear();
482 template <
class MemDepPred,
class Impl>
490 if ((*replay_it)->threadNumber == tid &&
491 (*replay_it)->seqNum > squashed_num) {
505 (*squash_it)->seqNum > squashed_num) {
508 (*squash_it)->seqNum);
516 hash_it =
memDepHash.find((*squash_it)->seqNum);
520 (*hash_it).second->squashed =
true;
522 (*hash_it).second = NULL;
526 MemDepEntry::memdep_erase++;
533 depPred.squash(squashed_num, tid);
536 template <
class MemDepPred,
class Impl>
542 " load: %#x, store: %#x\n", violating_load->instAddr(),
543 store_inst->instAddr());
545 depPred.violation(store_inst->instAddr(), violating_load->instAddr());
548 template <
class MemDepPred,
class Impl>
553 inst->instAddr(), inst->seqNum);
555 depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
558 template <
class MemDepPred,
class Impl>
566 return (*hash_it).second;
569 template <
class MemDepPred,
class Impl>
574 "to the ready list.\n", woken_inst_entry->inst->seqNum);
576 assert(!woken_inst_entry->squashed);
578 iqPtr->addReadyMemInst(woken_inst_entry->inst);
582 template <
class MemDepPred,
class Impl>
586 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
587 cprintf(
"Instruction list %i size: %i\n",
593 while (inst_list_it !=
instList[tid].end()) {
594 cprintf(
"Instruction:%i\nPC: %s\n[sn:%llu]\n[tid:%i]\nIssued:%i\n" 596 num, (*inst_list_it)->pcState(),
597 (*inst_list_it)->seqNum,
598 (*inst_list_it)->threadNumber,
599 (*inst_list_it)->isIssued(),
600 (*inst_list_it)->isSquashed());
609 cprintf(
"Memory dependence entries: %i\n", MemDepEntry::memdep_count);
613 #endif//__CPU_O3_MEM_DEP_UNIT_IMPL_HH__ #define panic(...)
This implements a cprintf based panic() function.
MemDepHash memDepHash
A hash map of all memory dependence entries.
void completed(const DynInstPtr &inst)
Completes a memory instruction.
bool loadBarrier
Is there an outstanding load barrier that loads must wait on.
std::shared_ptr< MemDepEntry > MemDepEntryPtr
void violation(const DynInstPtr &store_inst, const DynInstPtr &violating_load)
Indicates an ordering violation between a store and a younger load.
InstSeqNum storeBarrierSN
The sequence number of the store barrier.
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.
bool storeBarrier
Is there an outstanding store barrier that loads must wait on.
void setIQ(InstructionQueue< Impl > *iq_ptr)
Sets the pointer to the IQ.
Impl::DynInstConstPtr DynInstConstPtr
void wakeDependents(const DynInstPtr &inst)
Wakes any dependents of a memory instruction.
~MemDepUnit()
Frees up any memory allocated.
bool isDrained() const
Determine if we are drained.
Stats::Scalar insertedLoads
Stat for number of inserted loads.
void nonSpecInstReady(const DynInstPtr &inst)
Indicate that a non-speculative instruction is ready.
InstructionQueue< Impl > * iqPtr
Pointer to the IQ.
void takeOverFrom()
Takes over from another CPU's thread.
std::string csprintf(const char *format, const Args &...args)
Impl::DynInstPtr DynInstPtr
void insertNonSpec(const DynInstPtr &inst)
Inserts a non-speculative memory instruction.
Stats::Scalar conflictingStores
Stat for number of conflicting stores that had to wait for a store.
void issue(const DynInstPtr &inst)
Issues the given instruction.
Stats::Scalar conflictingLoads
Stat for number of conflicting loads that had to wait for a store.
void moveToReady(MemDepEntryPtr &ready_inst_entry)
Moves an entry to the ready list.
void regsReady(const DynInstPtr &inst)
Indicate that an instruction has its registers ready.
void dumpLists()
Debugging function to dump the lists of instructions.
Stats::Scalar insertedStores
Stat for number of inserted stores.
std::list< DynInstPtr > instList[Impl::MaxThreads]
A list of all instructions in the memory dependence unit.
void reschedule(const DynInstPtr &inst)
Reschedules an instruction to be re-executed.
MemDepEntryPtr & findInHash(const DynInstConstPtr &inst)
Finds the memory dependence entry in the hash map.
MemDepPred depPred
The memory dependence predictor.
void insert(const DynInstPtr &inst)
Inserts a memory instruction.
Memory dependency unit class.
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
int16_t ThreadID
Thread index/ID type.
void init(DerivO3CPUParams *params, ThreadID tid)
Initializes the unit with parameters and a thread id.
InstSeqNum loadBarrierSN
The sequence number of the load barrier.
void squash(const InstSeqNum &squashed_num, ThreadID tid)
Squashes all instructions up until a given sequence number for a specific thread. ...
std::list< DynInstPtr > instsToReplay
A list of all instructions that are going to be replayed.
void drainSanityCheck() const
Perform sanity checks after a drain.
std::string name() const
Returns the name of the memory dependence unit.
void completeBarrier(const DynInstPtr &inst)
Completes a barrier instruction.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
MemDepUnit()
Empty constructor.
void insertBarrier(const DynInstPtr &barr_inst)
Inserts a barrier instruction.
A standard instruction queue class.
void cprintf(const char *format, const Args &...args)
MemDepHash::iterator MemDepHashIt