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>
63 depPred(params->store_set_clear_period, params->SSITSize,
71 template <
class MemDepPred,
class Impl>
74 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
81 hash_it =
memDepHash.find((*inst_list_it)->seqNum);
92 assert(MemDepEntry::memdep_count == 0);
96 template <
class MemDepPred,
class Impl>
105 depPred.init(params->store_set_clear_period, params->SSITSize,
109 template <
class MemDepPred,
class Impl>
115 .
desc(
"Number of loads inserted to the mem dependence unit.");
119 .
desc(
"Number of stores inserted to the mem dependence unit.");
123 .
desc(
"Number of conflicting loads.");
126 .
name(
name() +
".conflictingStores")
127 .
desc(
"Number of conflicting stores.");
130 template <
class MemDepPred,
class Impl>
137 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
138 drained = drained &&
instList[
i].empty();
143 template <
class MemDepPred,
class Impl>
149 for (
int i = 0;
i < Impl::MaxThreads; ++
i)
155 template <
class MemDepPred,
class Impl>
165 template <
class MemDepPred,
class Impl>
172 template <
class MemDepPred,
class Impl>
184 MemDepEntry::memdep_insert++;
189 inst_entry->listIt = --(
instList[tid].end());
194 if ((inst->isLoad() || inst->isAtomic()) &&
loadBarrier) {
198 }
else if ((inst->isStore() || inst->isAtomic()) &&
storeBarrier) {
203 producing_store =
depPred.checkInst(inst->instAddr());
209 if (producing_store != 0) {
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;
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() || inst->isAtomic()) {
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++;
287 inst_entry->listIt = --(
instList[tid].end());
291 if (inst->isStore() || inst->isAtomic()) {
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()) {
317 barr_inst->pcState(),barr_sn);
318 }
else if (barr_inst->isWriteBarrier()) {
324 ThreadID tid = barr_inst->threadNumber;
326 MemDepEntryPtr inst_entry = std::make_shared<MemDepEntry>(barr_inst);
332 MemDepEntry::memdep_insert++;
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");
360 "memory dependency.\n");
364 template <
class MemDepPred,
class Impl>
369 "instruction PC %s as ready [sn:%lli].\n",
370 inst->pcState(), inst->seqNum);
377 template <
class MemDepPred,
class Impl>
384 template <
class MemDepPred,
class Impl>
397 temp_inst->pcState(), temp_inst->seqNum);
405 template <
class MemDepPred,
class Impl>
410 inst->pcState(), inst->seqNum);
419 instList[tid].erase((*hash_it).second->listIt);
421 (*hash_it).second = NULL;
425 MemDepEntry::memdep_erase++;
429 template <
class MemDepPred,
class Impl>
439 if (inst->isMemBarrier()) {
444 }
else if (inst->isWriteBarrier()) {
450 template <
class MemDepPred,
class Impl>
455 if (!inst->isStore() && !inst->isAtomic() && !inst->isMemBarrier() &&
456 !inst->isWriteBarrier()) {
462 for (
int i = 0;
i < inst_entry->dependInsts.size(); ++
i ) {
465 if (!woken_inst->inst) {
472 woken_inst->inst->seqNum);
474 if (woken_inst->regsReady && !woken_inst->squashed) {
477 woken_inst->memDepReady =
true;
481 inst_entry->dependInsts.clear();
484 template <
class MemDepPred,
class Impl>
492 if ((*replay_it)->threadNumber == tid &&
493 (*replay_it)->seqNum > squashed_num) {
507 (*squash_it)->seqNum > squashed_num) {
510 (*squash_it)->seqNum);
518 hash_it =
memDepHash.find((*squash_it)->seqNum);
522 (*hash_it).second->squashed =
true;
524 (*hash_it).second = NULL;
528 MemDepEntry::memdep_erase++;
535 depPred.squash(squashed_num, tid);
538 template <
class MemDepPred,
class Impl>
544 " load: %#x, store: %#x\n", violating_load->instAddr(),
545 store_inst->instAddr());
547 depPred.violation(store_inst->instAddr(), violating_load->instAddr());
550 template <
class MemDepPred,
class Impl>
555 inst->instAddr(), inst->seqNum);
557 depPred.issued(inst->instAddr(), inst->seqNum, inst->isStore());
560 template <
class MemDepPred,
class Impl>
568 return (*hash_it).second;
571 template <
class MemDepPred,
class Impl>
576 "to the ready list.\n", woken_inst_entry->inst->seqNum);
578 assert(!woken_inst_entry->squashed);
580 iqPtr->addReadyMemInst(woken_inst_entry->inst);
584 template <
class MemDepPred,
class Impl>
588 for (
ThreadID tid = 0; tid < Impl::MaxThreads; tid++) {
589 cprintf(
"Instruction list %i size: %i\n",
595 while (inst_list_it !=
instList[tid].end()) {
596 cprintf(
"Instruction:%i\nPC: %s\n[sn:%llu]\n[tid:%i]\nIssued:%i\n" 598 num, (*inst_list_it)->pcState(),
599 (*inst_list_it)->seqNum,
600 (*inst_list_it)->threadNumber,
601 (*inst_list_it)->isIssued(),
602 (*inst_list_it)->isSquashed());
611 cprintf(
"Memory dependence entries: %i\n", MemDepEntry::memdep_count);
615 #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