2c2
< * Copyright (c) 2004-2006 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2005 The Regents of The University of Michigan
26a27,28
> *
> * Authors: Kevin Lim
31d32
< #include "cpu/o3/inst_queue.hh"
35,37c36,37
< MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params *params)
< : depPred(params->SSITSize, params->LFSTSize), loadBarrier(false),
< loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL)
---
> MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params &params)
> : depPred(params.SSITSize, params.LFSTSize)
39c39
< DPRINTF(MemDepUnit, "Creating MemDepUnit object.\n");
---
> DPRINTF(MemDepUnit, "MemDepUnit: Creating MemDepUnit object.\n");
43,72d42
< MemDepUnit<MemDepPred, Impl>::~MemDepUnit()
< {
< for (int tid=0; tid < Impl::MaxThreads; tid++) {
<
< ListIt inst_list_it = instList[tid].begin();
<
< MemDepHashIt hash_it;
<
< while (!instList[tid].empty()) {
< hash_it = memDepHash.find((*inst_list_it)->seqNum);
<
< assert(hash_it != memDepHash.end());
<
< memDepHash.erase(hash_it);
<
< instList[tid].erase(inst_list_it++);
< }
< }
<
< assert(MemDepEntry::memdep_count == 0);
< }
<
< template <class MemDepPred, class Impl>
< std::string
< MemDepUnit<MemDepPred, Impl>::name() const
< {
< return "memdepunit";
< }
<
< template <class MemDepPred, class Impl>
74,84d43
< MemDepUnit<MemDepPred, Impl>::init(Params *params, int tid)
< {
< DPRINTF(MemDepUnit, "Creating MemDepUnit %i object.\n",tid);
<
< id = tid;
<
< depPred.init(params->SSITSize, params->LFSTSize);
< }
<
< template <class MemDepPred, class Impl>
< void
106,132d64
< MemDepUnit<MemDepPred, Impl>::switchOut()
< {
< for (int i = 0; i < Impl::MaxThreads; ++i) {
< instList[i].clear();
< }
< instsToReplay.clear();
< memDepHash.clear();
< }
<
< template <class MemDepPred, class Impl>
< void
< MemDepUnit<MemDepPred, Impl>::takeOverFrom()
< {
< loadBarrier = storeBarrier = false;
< loadBarrierSN = storeBarrierSN = 0;
< depPred.clear();
< }
<
< template <class MemDepPred, class Impl>
< void
< MemDepUnit<MemDepPred, Impl>::setIQ(InstructionQueue<Impl> *iq_ptr)
< {
< iqPtr = iq_ptr;
< }
<
< template <class MemDepPred, class Impl>
< void
135c67
< unsigned tid = inst->threadNumber;
---
> InstSeqNum inst_seq_num = inst->seqNum;
137c69
< MemDepEntryPtr inst_entry = new MemDepEntry(inst);
---
> Dependency unresolved_dependencies(inst_seq_num);
139,142c71
< // Add the MemDepEntry to the hash.
< memDepHash.insert(
< std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
< MemDepEntry::memdep_insert++;
---
> InstSeqNum producing_store = depPred.checkInst(inst->readPC());
144c73,74
< instList[tid].push_back(inst);
---
> if (producing_store == 0 ||
> storeDependents.find(producing_store) == storeDependents.end()) {
146c76,77
< inst_entry->listIt = --(instList[tid].end());
---
> DPRINTF(MemDepUnit, "MemDepUnit: No dependency for inst PC "
> "%#x.\n", inst->readPC());
148,157c79
< // Check any barriers and the dependence predictor for any
< // producing stores.
< InstSeqNum producing_store;
< if (inst->isLoad() && loadBarrier) {
< producing_store = loadBarrierSN;
< } else if (inst->isStore() && storeBarrier) {
< producing_store = storeBarrierSN;
< } else {
< producing_store = depPred.checkInst(inst->readPC());
< }
---
> unresolved_dependencies.storeDep = storeDependents.end();
159,177d80
< MemDepEntryPtr store_entry = NULL;
<
< // If there is a producing store, try to find the entry.
< if (producing_store != 0) {
< MemDepHashIt hash_it = memDepHash.find(producing_store);
<
< if (hash_it != memDepHash.end()) {
< store_entry = (*hash_it).second;
< }
< }
<
< // If no store entry, then instruction can issue as soon as the registers
< // are ready.
< if (!store_entry) {
< DPRINTF(MemDepUnit, "No dependency for inst PC "
< "%#x [sn:%lli].\n", inst->readPC(), inst->seqNum);
<
< inst_entry->memDepReady = true;
<
179c82,84
< inst_entry->regsReady = true;
---
> readyInsts.insert(inst_seq_num);
> } else {
> unresolved_dependencies.memDepReady = true;
181c86
< moveToReady(inst_entry);
---
> waitingInsts.insert(unresolved_dependencies);
184,186c89,90
< // Otherwise make the instruction dependent on the store/barrier.
< DPRINTF(MemDepUnit, "Adding to dependency list; "
< "inst PC %#x is dependent on [sn:%lli].\n",
---
> DPRINTF(MemDepUnit, "MemDepUnit: Adding to dependency list; "
> "inst PC %#x is dependent on seq num %i.\n",
190c94
< inst_entry->regsReady = true;
---
> unresolved_dependencies.regsReady = true;
192a97,110
> // Find the store that this instruction is dependent on.
> sd_it_t store_loc = storeDependents.find(producing_store);
>
> assert(store_loc != storeDependents.end());
>
> // Record the location of the store that this instruction is
> // dependent on.
> unresolved_dependencies.storeDep = store_loc;
>
> // If it's not already ready, then add it to the renamed
> // list and the dependencies.
> dep_it_t inst_loc =
> (waitingInsts.insert(unresolved_dependencies)).first;
>
194c112
< store_entry->dependInsts.push_back(inst_entry);
---
> (*store_loc).second.push_back(inst_loc);
195a114,115
> assert(!(*store_loc).second.empty());
>
204,205c124,125
< DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
< inst->readPC(), inst->seqNum);
---
> DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
> inst->readPC());
207c127
< depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
---
> depPred.insertStore(inst->readPC(), inst_seq_num);
208a129,138
> // Make sure this store isn't already in this list.
> assert(storeDependents.find(inst_seq_num) == storeDependents.end());
>
> // Put a dependency entry in at the store's sequence number.
> // Uh, not sure how this works...I want to create an entry but
> // I don't have anything to put into the value yet.
> storeDependents[inst_seq_num];
>
> assert(storeDependents.size() != 0);
>
209a140
>
213c144
< panic("Unknown type! (most likely a barrier).");
---
> panic("MemDepUnit: Unknown type! (most likely a barrier).");
214a146,147
>
> memInsts[inst_seq_num] = inst;
221c154
< unsigned tid = inst->threadNumber;
---
> InstSeqNum inst_seq_num = inst->seqNum;
223c156
< MemDepEntryPtr inst_entry = new MemDepEntry(inst);
---
> Dependency non_spec_inst(inst_seq_num);
225,228c158
< // Insert the MemDepEntry into the hash.
< memDepHash.insert(
< std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
< MemDepEntry::memdep_insert++;
---
> non_spec_inst.storeDep = storeDependents.end();
230,231c160
< // Add the instruction to the list.
< instList[tid].push_back(inst);
---
> waitingInsts.insert(non_spec_inst);
233,234d161
< inst_entry->listIt = --(instList[tid].end());
<
238,239c165,166
< DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
< inst->readPC(), inst->seqNum);
---
> DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
> inst->readPC());
241c168
< depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
---
> depPred.insertStore(inst->readPC(), inst_seq_num);
242a170,179
> // Make sure this store isn't already in this list.
> assert(storeDependents.find(inst_seq_num) == storeDependents.end());
>
> // Put a dependency entry in at the store's sequence number.
> // Uh, not sure how this works...I want to create an entry but
> // I don't have anything to put into the value yet.
> storeDependents[inst_seq_num];
>
> assert(storeDependents.size() != 0);
>
243a181
>
247c185
< panic("Unknown type! (most likely a barrier).");
---
> panic("MemDepUnit: Unknown type! (most likely a barrier).");
248a187,188
>
> memInsts[inst_seq_num] = inst;
252,253c192,193
< void
< MemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst)
---
> typename Impl::DynInstPtr &
> MemDepUnit<MemDepPred, Impl>::top()
255,266c195
< InstSeqNum barr_sn = barr_inst->seqNum;
< if (barr_inst->isMemBarrier()) {
< loadBarrier = true;
< loadBarrierSN = barr_sn;
< storeBarrier = true;
< storeBarrierSN = barr_sn;
< DPRINTF(MemDepUnit, "Inserted a memory barrier\n");
< } else if (barr_inst->isWriteBarrier()) {
< storeBarrier = true;
< storeBarrierSN = barr_sn;
< DPRINTF(MemDepUnit, "Inserted a write barrier\n");
< }
---
> topInst = memInsts.find( (*readyInsts.begin()) );
268c197,198
< unsigned tid = barr_inst->threadNumber;
---
> DPRINTF(MemDepUnit, "MemDepUnit: Top instruction is PC %#x.\n",
> (*topInst).second->readPC());
270,280c200
< MemDepEntryPtr inst_entry = new MemDepEntry(barr_inst);
<
< // Add the MemDepEntry to the hash.
< memDepHash.insert(
< std::pair<InstSeqNum, MemDepEntryPtr>(barr_sn, inst_entry));
< MemDepEntry::memdep_insert++;
<
< // Add the instruction to the instruction list.
< instList[tid].push_back(barr_inst);
<
< inst_entry->listIt = --(instList[tid].end());
---
> return (*topInst).second;
285c205
< MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
---
> MemDepUnit<MemDepPred, Impl>::pop()
287,289c207,208
< DPRINTF(MemDepUnit, "Marking registers as ready for "
< "instruction PC %#x [sn:%lli].\n",
< inst->readPC(), inst->seqNum);
---
> DPRINTF(MemDepUnit, "MemDepUnit: Removing instruction PC %#x.\n",
> (*topInst).second->readPC());
291c210
< MemDepEntryPtr inst_entry = findInHash(inst);
---
> wakeDependents((*topInst).second);
293c212
< inst_entry->regsReady = true;
---
> issue((*topInst).second);
295,297c214
< if (inst_entry->memDepReady) {
< DPRINTF(MemDepUnit, "Instruction has its memory "
< "dependencies resolved, adding it to the ready list.\n");
---
> memInsts.erase(topInst);
299,303c216
< moveToReady(inst_entry);
< } else {
< DPRINTF(MemDepUnit, "Instruction still waiting on "
< "memory dependency.\n");
< }
---
> topInst = memInsts.end();
308c221
< MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
---
> MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
310,312c223,225
< DPRINTF(MemDepUnit, "Marking non speculative "
< "instruction PC %#x as ready [sn:%lli].\n",
< inst->readPC(), inst->seqNum);
---
> DPRINTF(MemDepUnit, "MemDepUnit: Marking registers as ready for "
> "instruction PC %#x.\n",
> inst->readPC());
314c227
< MemDepEntryPtr inst_entry = findInHash(inst);
---
> InstSeqNum inst_seq_num = inst->seqNum;
316,317c229
< moveToReady(inst_entry);
< }
---
> Dependency inst_to_find(inst_seq_num);
319,324c231
< template <class MemDepPred, class Impl>
< void
< MemDepUnit<MemDepPred, Impl>::reschedule(DynInstPtr &inst)
< {
< instsToReplay.push_back(inst);
< }
---
> dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
326,331c233
< template <class MemDepPred, class Impl>
< void
< MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
< {
< DynInstPtr temp_inst;
< bool found_inst = false;
---
> assert(waiting_inst != waitingInsts.end());
333,334c235,237
< while (!instsToReplay.empty()) {
< temp_inst = instsToReplay.front();
---
> if ((*waiting_inst).memDepReady) {
> DPRINTF(MemDepUnit, "MemDepUnit: Instruction has its memory "
> "dependencies resolved, adding it to the ready list.\n");
336c239,242
< MemDepEntryPtr inst_entry = findInHash(temp_inst);
---
> moveToReady(waiting_inst);
> } else {
> DPRINTF(MemDepUnit, "MemDepUnit: Instruction still waiting on "
> "memory dependency.\n");
338,348c244
< DPRINTF(MemDepUnit, "Replaying mem instruction PC %#x "
< "[sn:%lli].\n",
< temp_inst->readPC(), temp_inst->seqNum);
<
< moveToReady(inst_entry);
<
< if (temp_inst == inst) {
< found_inst = true;
< }
<
< instsToReplay.pop_front();
---
> (*waiting_inst).regsReady = true;
350,351d245
<
< assert(found_inst);
356c250
< MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
---
> MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
358,360c252,254
< DPRINTF(MemDepUnit, "Completed mem instruction PC %#x "
< "[sn:%lli].\n",
< inst->readPC(), inst->seqNum);
---
> DPRINTF(MemDepUnit, "MemDepUnit: Marking non speculative "
> "instruction PC %#x as ready.\n",
> inst->readPC());
362c256
< unsigned tid = inst->threadNumber;
---
> InstSeqNum inst_seq_num = inst->seqNum;
364,365c258
< // Remove the instruction from the hash and the list.
< MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
---
> Dependency inst_to_find(inst_seq_num);
367c260
< assert(hash_it != memDepHash.end());
---
> dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
369c262
< instList[tid].erase((*hash_it).second->listIt);
---
> assert(waiting_inst != waitingInsts.end());
371,374c264
< (*hash_it).second = NULL;
<
< memDepHash.erase(hash_it);
< MemDepEntry::memdep_erase++;
---
> moveToReady(waiting_inst);
379c269
< MemDepUnit<MemDepPred, Impl>::completeBarrier(DynInstPtr &inst)
---
> MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
381,382c271
< wakeDependents(inst);
< completed(inst);
---
> assert(readyInsts.find(inst->seqNum) != readyInsts.end());
384c273,274
< InstSeqNum barr_sn = inst->seqNum;
---
> DPRINTF(MemDepUnit, "MemDepUnit: Issuing instruction PC %#x.\n",
> inst->readPC());
386,396c276,279
< if (inst->isMemBarrier()) {
< assert(loadBarrier && storeBarrier);
< if (loadBarrierSN == barr_sn)
< loadBarrier = false;
< if (storeBarrierSN == barr_sn)
< storeBarrier = false;
< } else if (inst->isWriteBarrier()) {
< assert(storeBarrier);
< if (storeBarrierSN == barr_sn)
< storeBarrier = false;
< }
---
> // Remove the instruction from the ready list.
> readyInsts.erase(inst->seqNum);
>
> depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
403,404c286,287
< // Only stores and barriers have dependents.
< if (!inst->isStore() && !inst->isMemBarrier() && !inst->isWriteBarrier()) {
---
> // Only stores have dependents.
> if (!inst->isStore()) {
408c291,292
< MemDepEntryPtr inst_entry = findInHash(inst);
---
> // Wake any dependencies.
> sd_it_t sd_it = storeDependents.find(inst->seqNum);
410,411c294,299
< for (int i = 0; i < inst_entry->dependInsts.size(); ++i ) {
< MemDepEntryPtr woken_inst = inst_entry->dependInsts[i];
---
> // If there's no entry, then return. Really there should only be
> // no entry if the instruction is a load.
> if (sd_it == storeDependents.end()) {
> DPRINTF(MemDepUnit, "MemDepUnit: Instruction PC %#x, sequence "
> "number %i has no dependents.\n",
> inst->readPC(), inst->seqNum);
413,416c301,302
< if (!woken_inst->inst) {
< // Potentially removed mem dep entries could be on this list
< continue;
< }
---
> return;
> }
418,420c304,305
< DPRINTF(MemDepUnit, "Waking up a dependent inst, "
< "[sn:%lli].\n",
< woken_inst->inst->seqNum);
---
> for (int i = 0; i < (*sd_it).second.size(); ++i ) {
> dep_it_t woken_inst = (*sd_it).second[i];
422c307,322
< if (woken_inst->regsReady && !woken_inst->squashed) {
---
> DPRINTF(MemDepUnit, "MemDepUnit: Waking up a dependent inst, "
> "sequence number %i.\n",
> (*woken_inst).seqNum);
> #if 0
> // Should we have reached instructions that are actually squashed,
> // there will be no more useful instructions in this dependency
> // list. Break out early.
> if (waitingInsts.find(woken_inst) == waitingInsts.end()) {
> DPRINTF(MemDepUnit, "MemDepUnit: Dependents on inst PC %#x "
> "are squashed, starting at SN %i. Breaking early.\n",
> inst->readPC(), woken_inst);
> break;
> }
> #endif
>
> if ((*woken_inst).regsReady) {
425c325
< woken_inst->memDepReady = true;
---
> (*woken_inst).memDepReady = true;
429c329
< inst_entry->dependInsts.clear();
---
> storeDependents.erase(sd_it);
434,435c334
< MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num,
< unsigned tid)
---
> MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num)
437,447d335
< if (!instsToReplay.empty()) {
< ListIt replay_it = instsToReplay.begin();
< while (replay_it != instsToReplay.end()) {
< if ((*replay_it)->threadNumber == tid &&
< (*replay_it)->seqNum > squashed_num) {
< instsToReplay.erase(replay_it++);
< } else {
< ++replay_it;
< }
< }
< }
449,450c337,338
< ListIt squash_it = instList[tid].end();
< --squash_it;
---
> if (!waitingInsts.empty()) {
> dep_it_t waiting_it = waitingInsts.end();
452c340
< MemDepHashIt hash_it;
---
> --waiting_it;
454,455c342,349
< while (!instList[tid].empty() &&
< (*squash_it)->seqNum > squashed_num) {
---
> // Remove entries from the renamed list as long as we haven't reached
> // the end and the entries continue to be younger than the squashed.
> while (!waitingInsts.empty() &&
> (*waiting_it).seqNum > squashed_num)
> {
> if (!(*waiting_it).memDepReady &&
> (*waiting_it).storeDep != storeDependents.end()) {
> sd_it_t sd_it = (*waiting_it).storeDep;
457,458c351,353
< DPRINTF(MemDepUnit, "Squashing inst [sn:%lli]\n",
< (*squash_it)->seqNum);
---
> // Make sure the iterator that the store has pointing
> // back is actually to this instruction.
> assert((*sd_it).second.back() == waiting_it);
460c355,358
< hash_it = memDepHash.find((*squash_it)->seqNum);
---
> // Now remove this from the store's list of dependent
> // instructions.
> (*sd_it).second.pop_back();
> }
462c360,362
< assert(hash_it != memDepHash.end());
---
> waitingInsts.erase(waiting_it--);
> }
> }
464c364,365
< (*hash_it).second->squashed = true;
---
> if (!readyInsts.empty()) {
> sn_it_t ready_it = readyInsts.end();
466c367
< (*hash_it).second = NULL;
---
> --ready_it;
468,469c369,375
< memDepHash.erase(hash_it);
< MemDepEntry::memdep_erase++;
---
> // Same for the ready list.
> while (!readyInsts.empty() &&
> (*ready_it) > squashed_num)
> {
> readyInsts.erase(ready_it--);
> }
> }
471c377,390
< instList[tid].erase(squash_it--);
---
> if (!storeDependents.empty()) {
> sd_it_t dep_it = storeDependents.end();
>
> --dep_it;
>
> // Same for the dependencies list.
> while (!storeDependents.empty() &&
> (*dep_it).first > squashed_num)
> {
> // This store's list of dependent instructions should be empty.
> assert((*dep_it).second.empty());
>
> storeDependents.erase(dep_it--);
> }
475c394
< depPred.squash(squashed_num, tid);
---
> depPred.squash(squashed_num);
483c402
< DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
---
> DPRINTF(MemDepUnit, "MemDepUnit: Passing violating PCs to store sets,"
491,511d409
< void
< MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
< {
< DPRINTF(MemDepUnit, "Issuing instruction PC %#x [sn:%lli].\n",
< inst->readPC(), inst->seqNum);
<
< depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
< }
<
< template <class MemDepPred, class Impl>
< inline typename MemDepUnit<MemDepPred,Impl>::MemDepEntryPtr &
< MemDepUnit<MemDepPred, Impl>::findInHash(const DynInstPtr &inst)
< {
< MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
<
< assert(hash_it != memDepHash.end());
<
< return (*hash_it).second;
< }
<
< template <class MemDepPred, class Impl>
513c411
< MemDepUnit<MemDepPred, Impl>::moveToReady(MemDepEntryPtr &woken_inst_entry)
---
> MemDepUnit<MemDepPred, Impl>::moveToReady(dep_it_t &woken_inst)
515,516c413,414
< DPRINTF(MemDepUnit, "Adding instruction [sn:%lli] "
< "to the ready list.\n", woken_inst_entry->inst->seqNum);
---
> DPRINTF(MemDepUnit, "MemDepUnit: Adding instruction sequence number %i "
> "to the ready list.\n", (*woken_inst).seqNum);
518c416,417
< assert(!woken_inst_entry->squashed);
---
> // Add it to the ready list.
> readyInsts.insert((*woken_inst).seqNum);
520c419,420
< iqPtr->addReadyMemInst(woken_inst_entry->inst);
---
> // Remove it from the waiting instructions.
> waitingInsts.erase(woken_inst);
522,551d421
<
<
< template <class MemDepPred, class Impl>
< void
< MemDepUnit<MemDepPred, Impl>::dumpLists()
< {
< for (unsigned tid=0; tid < Impl::MaxThreads; tid++) {
< cprintf("Instruction list %i size: %i\n",
< tid, instList[tid].size());
<
< ListIt inst_list_it = instList[tid].begin();
< int num = 0;
<
< while (inst_list_it != instList[tid].end()) {
< cprintf("Instruction:%i\nPC:%#x\n[sn:%i]\n[tid:%i]\nIssued:%i\n"
< "Squashed:%i\n\n",
< num, (*inst_list_it)->readPC(),
< (*inst_list_it)->seqNum,
< (*inst_list_it)->threadNumber,
< (*inst_list_it)->isIssued(),
< (*inst_list_it)->isSquashed());
< inst_list_it++;
< ++num;
< }
< }
<
< cprintf("Memory dependence hash size: %i\n", memDepHash.size());
<
< cprintf("Memory dependence entries: %i\n", MemDepEntry::memdep_count);
< }