2c2
< * Copyright (c) 2004-2005 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2006 The Regents of The University of Michigan
30a31
> #include "cpu/o3/inst_queue.hh"
34,35c35,37
< MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params &params)
< : depPred(params.SSITSize, params.LFSTSize)
---
> MemDepUnit<MemDepPred, Impl>::MemDepUnit(Params *params)
> : depPred(params->SSITSize, params->LFSTSize), loadBarrier(false),
> loadBarrierSN(0), storeBarrier(false), storeBarrierSN(0), iqPtr(NULL)
37c39
< DPRINTF(MemDepUnit, "MemDepUnit: Creating MemDepUnit object.\n");
---
> DPRINTF(MemDepUnit, "Creating MemDepUnit object.\n");
40a43,72
> 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>
41a74,84
> 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
62a106,132
> 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
65c135
< InstSeqNum inst_seq_num = inst->seqNum;
---
> unsigned tid = inst->threadNumber;
67c137
< Dependency unresolved_dependencies(inst_seq_num);
---
> MemDepEntryPtr inst_entry = new MemDepEntry(inst);
69c139,142
< InstSeqNum producing_store = depPred.checkInst(inst->readPC());
---
> // Add the MemDepEntry to the hash.
> memDepHash.insert(
> std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
> MemDepEntry::memdep_insert++;
71,72c144
< if (producing_store == 0 ||
< storeDependents.find(producing_store) == storeDependents.end()) {
---
> instList[tid].push_back(inst);
74,75c146
< DPRINTF(MemDepUnit, "MemDepUnit: No dependency for inst PC "
< "%#x.\n", inst->readPC());
---
> inst_entry->listIt = --(instList[tid].end());
77c148,157
< unresolved_dependencies.storeDep = storeDependents.end();
---
> // 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());
> }
78a159,177
> 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;
>
80,82c179
< readyInsts.insert(inst_seq_num);
< } else {
< unresolved_dependencies.memDepReady = true;
---
> inst_entry->regsReady = true;
84c181
< waitingInsts.insert(unresolved_dependencies);
---
> moveToReady(inst_entry);
87,88c184,186
< DPRINTF(MemDepUnit, "MemDepUnit: Adding to dependency list; "
< "inst PC %#x is dependent on seq num %i.\n",
---
> // Otherwise make the instruction dependent on the store/barrier.
> DPRINTF(MemDepUnit, "Adding to dependency list; "
> "inst PC %#x is dependent on [sn:%lli].\n",
92c190
< unresolved_dependencies.regsReady = true;
---
> inst_entry->regsReady = true;
95,108d192
< // 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;
<
110c194
< (*store_loc).second.push_back(inst_loc);
---
> store_entry->dependInsts.push_back(inst_entry);
112,113d195
< assert(!(*store_loc).second.empty());
<
122,123c204,205
< DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
< inst->readPC());
---
> DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
> inst->readPC(), inst->seqNum);
125c207
< depPred.insertStore(inst->readPC(), inst_seq_num);
---
> depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
127,136d208
< // 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);
<
138d209
<
142c213
< panic("MemDepUnit: Unknown type! (most likely a barrier).");
---
> panic("Unknown type! (most likely a barrier).");
144,145d214
<
< memInsts[inst_seq_num] = inst;
152c221
< InstSeqNum inst_seq_num = inst->seqNum;
---
> unsigned tid = inst->threadNumber;
154c223
< Dependency non_spec_inst(inst_seq_num);
---
> MemDepEntryPtr inst_entry = new MemDepEntry(inst);
156c225,228
< non_spec_inst.storeDep = storeDependents.end();
---
> // Insert the MemDepEntry into the hash.
> memDepHash.insert(
> std::pair<InstSeqNum, MemDepEntryPtr>(inst->seqNum, inst_entry));
> MemDepEntry::memdep_insert++;
158c230,231
< waitingInsts.insert(non_spec_inst);
---
> // Add the instruction to the list.
> instList[tid].push_back(inst);
159a233,234
> inst_entry->listIt = --(instList[tid].end());
>
163,164c238,239
< DPRINTF(MemDepUnit, "MemDepUnit: Inserting store PC %#x.\n",
< inst->readPC());
---
> DPRINTF(MemDepUnit, "Inserting store PC %#x [sn:%lli].\n",
> inst->readPC(), inst->seqNum);
166c241
< depPred.insertStore(inst->readPC(), inst_seq_num);
---
> depPred.insertStore(inst->readPC(), inst->seqNum, inst->threadNumber);
168,177d242
< // 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);
<
179d243
<
183c247
< panic("MemDepUnit: Unknown type! (most likely a barrier).");
---
> panic("Unknown type! (most likely a barrier).");
185,186d248
<
< memInsts[inst_seq_num] = inst;
190,191c252,253
< typename Impl::DynInstPtr &
< MemDepUnit<MemDepPred, Impl>::top()
---
> void
> MemDepUnit<MemDepPred, Impl>::insertBarrier(DynInstPtr &barr_inst)
193c255,266
< topInst = memInsts.find( (*readyInsts.begin()) );
---
> 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");
> }
195,196c268
< DPRINTF(MemDepUnit, "MemDepUnit: Top instruction is PC %#x.\n",
< (*topInst).second->readPC());
---
> unsigned tid = barr_inst->threadNumber;
198c270,280
< return (*topInst).second;
---
> 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());
203c285
< MemDepUnit<MemDepPred, Impl>::pop()
---
> MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
205,206c287,289
< DPRINTF(MemDepUnit, "MemDepUnit: Removing instruction PC %#x.\n",
< (*topInst).second->readPC());
---
> DPRINTF(MemDepUnit, "Marking registers as ready for "
> "instruction PC %#x [sn:%lli].\n",
> inst->readPC(), inst->seqNum);
208c291
< wakeDependents((*topInst).second);
---
> MemDepEntryPtr inst_entry = findInHash(inst);
210c293
< issue((*topInst).second);
---
> inst_entry->regsReady = true;
212c295,297
< memInsts.erase(topInst);
---
> if (inst_entry->memDepReady) {
> DPRINTF(MemDepUnit, "Instruction has its memory "
> "dependencies resolved, adding it to the ready list.\n");
214c299,303
< topInst = memInsts.end();
---
> moveToReady(inst_entry);
> } else {
> DPRINTF(MemDepUnit, "Instruction still waiting on "
> "memory dependency.\n");
> }
219c308
< MemDepUnit<MemDepPred, Impl>::regsReady(DynInstPtr &inst)
---
> MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
221,223c310,312
< DPRINTF(MemDepUnit, "MemDepUnit: Marking registers as ready for "
< "instruction PC %#x.\n",
< inst->readPC());
---
> DPRINTF(MemDepUnit, "Marking non speculative "
> "instruction PC %#x as ready [sn:%lli].\n",
> inst->readPC(), inst->seqNum);
225c314
< InstSeqNum inst_seq_num = inst->seqNum;
---
> MemDepEntryPtr inst_entry = findInHash(inst);
227c316,317
< Dependency inst_to_find(inst_seq_num);
---
> moveToReady(inst_entry);
> }
229c319,324
< dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
---
> template <class MemDepPred, class Impl>
> void
> MemDepUnit<MemDepPred, Impl>::reschedule(DynInstPtr &inst)
> {
> instsToReplay.push_back(inst);
> }
231c326,331
< assert(waiting_inst != waitingInsts.end());
---
> template <class MemDepPred, class Impl>
> void
> MemDepUnit<MemDepPred, Impl>::replay(DynInstPtr &inst)
> {
> DynInstPtr temp_inst;
> bool found_inst = false;
233,235c333,334
< if ((*waiting_inst).memDepReady) {
< DPRINTF(MemDepUnit, "MemDepUnit: Instruction has its memory "
< "dependencies resolved, adding it to the ready list.\n");
---
> while (!instsToReplay.empty()) {
> temp_inst = instsToReplay.front();
237,240c336
< moveToReady(waiting_inst);
< } else {
< DPRINTF(MemDepUnit, "MemDepUnit: Instruction still waiting on "
< "memory dependency.\n");
---
> MemDepEntryPtr inst_entry = findInHash(temp_inst);
242c338,348
< (*waiting_inst).regsReady = true;
---
> 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();
243a350,351
>
> assert(found_inst);
248c356
< MemDepUnit<MemDepPred, Impl>::nonSpecInstReady(DynInstPtr &inst)
---
> MemDepUnit<MemDepPred, Impl>::completed(DynInstPtr &inst)
250,252c358,360
< DPRINTF(MemDepUnit, "MemDepUnit: Marking non speculative "
< "instruction PC %#x as ready.\n",
< inst->readPC());
---
> DPRINTF(MemDepUnit, "Completed mem instruction PC %#x "
> "[sn:%lli].\n",
> inst->readPC(), inst->seqNum);
254c362
< InstSeqNum inst_seq_num = inst->seqNum;
---
> unsigned tid = inst->threadNumber;
256c364,365
< Dependency inst_to_find(inst_seq_num);
---
> // Remove the instruction from the hash and the list.
> MemDepHashIt hash_it = memDepHash.find(inst->seqNum);
258c367
< dep_it_t waiting_inst = waitingInsts.find(inst_to_find);
---
> assert(hash_it != memDepHash.end());
260c369
< assert(waiting_inst != waitingInsts.end());
---
> instList[tid].erase((*hash_it).second->listIt);
262c371,374
< moveToReady(waiting_inst);
---
> (*hash_it).second = NULL;
>
> memDepHash.erase(hash_it);
> MemDepEntry::memdep_erase++;
267c379
< MemDepUnit<MemDepPred, Impl>::issue(DynInstPtr &inst)
---
> MemDepUnit<MemDepPred, Impl>::completeBarrier(DynInstPtr &inst)
269c381,382
< assert(readyInsts.find(inst->seqNum) != readyInsts.end());
---
> wakeDependents(inst);
> completed(inst);
271,272c384
< DPRINTF(MemDepUnit, "MemDepUnit: Issuing instruction PC %#x.\n",
< inst->readPC());
---
> InstSeqNum barr_sn = inst->seqNum;
274,277c386,396
< // Remove the instruction from the ready list.
< readyInsts.erase(inst->seqNum);
<
< depPred.issued(inst->readPC(), inst->seqNum, inst->isStore());
---
> 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;
> }
284,285c403,404
< // Only stores have dependents.
< if (!inst->isStore()) {
---
> // Only stores and barriers have dependents.
> if (!inst->isStore() && !inst->isMemBarrier() && !inst->isWriteBarrier()) {
289,290c408
< // Wake any dependencies.
< sd_it_t sd_it = storeDependents.find(inst->seqNum);
---
> MemDepEntryPtr inst_entry = findInHash(inst);
292,297c410,411
< // 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);
---
> for (int i = 0; i < inst_entry->dependInsts.size(); ++i ) {
> MemDepEntryPtr woken_inst = inst_entry->dependInsts[i];
299,316c413,415
< return;
< }
<
< for (int i = 0; i < (*sd_it).second.size(); ++i ) {
< dep_it_t woken_inst = (*sd_it).second[i];
<
< 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;
---
> if (!woken_inst->inst) {
> // Potentially removed mem dep entries could be on this list
> continue;
318d416
< #endif
320c418,422
< if ((*woken_inst).regsReady) {
---
> DPRINTF(MemDepUnit, "Waking up a dependent inst, "
> "[sn:%lli].\n",
> woken_inst->inst->seqNum);
>
> if (woken_inst->regsReady && !woken_inst->squashed) {
323c425
< (*woken_inst).memDepReady = true;
---
> woken_inst->memDepReady = true;
327c429
< storeDependents.erase(sd_it);
---
> inst_entry->dependInsts.clear();
332c434,435
< MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num)
---
> MemDepUnit<MemDepPred, Impl>::squash(const InstSeqNum &squashed_num,
> unsigned tid)
334,355c437,444
<
< if (!waitingInsts.empty()) {
< dep_it_t waiting_it = waitingInsts.end();
<
< --waiting_it;
<
< // 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;
<
< // Make sure the iterator that the store has pointing
< // back is actually to this instruction.
< assert((*sd_it).second.back() == waiting_it);
<
< // Now remove this from the store's list of dependent
< // instructions.
< (*sd_it).second.pop_back();
---
> 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;
357,358d445
<
< waitingInsts.erase(waiting_it--);
362,363c449,450
< if (!readyInsts.empty()) {
< sn_it_t ready_it = readyInsts.end();
---
> ListIt squash_it = instList[tid].end();
> --squash_it;
365c452
< --ready_it;
---
> MemDepHashIt hash_it;
367,373c454,455
< // Same for the ready list.
< while (!readyInsts.empty() &&
< (*ready_it) > squashed_num)
< {
< readyInsts.erase(ready_it--);
< }
< }
---
> while (!instList[tid].empty() &&
> (*squash_it)->seqNum > squashed_num) {
375,376c457,458
< if (!storeDependents.empty()) {
< sd_it_t dep_it = storeDependents.end();
---
> DPRINTF(MemDepUnit, "Squashing inst [sn:%lli]\n",
> (*squash_it)->seqNum);
378c460
< --dep_it;
---
> hash_it = memDepHash.find((*squash_it)->seqNum);
380,385c462
< // 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());
---
> assert(hash_it != memDepHash.end());
387,388c464,471
< storeDependents.erase(dep_it--);
< }
---
> (*hash_it).second->squashed = true;
>
> (*hash_it).second = NULL;
>
> memDepHash.erase(hash_it);
> MemDepEntry::memdep_erase++;
>
> instList[tid].erase(squash_it--);
392c475
< depPred.squash(squashed_num);
---
> depPred.squash(squashed_num, tid);
400c483
< DPRINTF(MemDepUnit, "MemDepUnit: Passing violating PCs to store sets,"
---
> DPRINTF(MemDepUnit, "Passing violating PCs to store sets,"
407a491,511
> 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>
409c513
< MemDepUnit<MemDepPred, Impl>::moveToReady(dep_it_t &woken_inst)
---
> MemDepUnit<MemDepPred, Impl>::moveToReady(MemDepEntryPtr &woken_inst_entry)
411,412c515,516
< DPRINTF(MemDepUnit, "MemDepUnit: Adding instruction sequence number %i "
< "to the ready list.\n", (*woken_inst).seqNum);
---
> DPRINTF(MemDepUnit, "Adding instruction [sn:%lli] "
> "to the ready list.\n", woken_inst_entry->inst->seqNum);
414,415c518
< // Add it to the ready list.
< readyInsts.insert((*woken_inst).seqNum);
---
> assert(!woken_inst_entry->squashed);
417,418c520
< // Remove it from the waiting instructions.
< waitingInsts.erase(woken_inst);
---
> iqPtr->addReadyMemInst(woken_inst_entry->inst);
419a522,551
>
>
> 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);
> }