2c2
< * Copyright (c) 2004-2005 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2006 The Regents of The University of Michigan
29,30c29,30
< #ifndef __CPU_O3_CPU_MEM_DEP_UNIT_HH__
< #define __CPU_O3_CPU_MEM_DEP_UNIT_HH__
---
> #ifndef __CPU_O3_MEM_DEP_UNIT_HH__
> #define __CPU_O3_MEM_DEP_UNIT_HH__
32c32
< #include <map>
---
> #include <list>
34a35,36
> #include "base/hashmap.hh"
> #include "base/refcnt.hh"
37a40,51
> struct SNHash {
> size_t operator() (const InstSeqNum &seq_num) const {
> unsigned a = (unsigned)seq_num;
> unsigned hash = (((a >> 14) ^ ((a >> 2) & 0xffff))) & 0x7FFFFFFF;
>
> return hash;
> }
> };
>
> template <class Impl>
> class InstructionQueue;
>
55,56c69,70
< public:
< MemDepUnit(Params &params);
---
> /** Empty constructor. Must call init() prior to using in this case. */
> MemDepUnit() {}
57a72,84
> /** Constructs a MemDepUnit with given parameters. */
> MemDepUnit(Params *params);
>
> /** Frees up any memory allocated. */
> ~MemDepUnit();
>
> /** Returns the name of the memory dependence unit. */
> std::string name() const;
>
> /** Initializes the unit with parameters and a thread id. */
> void init(Params *params, int tid);
>
> /** Registers statistics. */
59a87,94
> void switchOut();
>
> void takeOverFrom();
>
> /** Sets the pointer to the IQ. */
> void setIQ(InstructionQueue<Impl> *iq_ptr);
>
> /** Inserts a memory instruction. */
61a97
> /** Inserts a non-speculative memory instruction. */
64,66c100,101
< // Will want to make this operation relatively fast. Right now it
< // is somewhat slow.
< DynInstPtr &top();
---
> /** Inserts a barrier instruction. */
> void insertBarrier(DynInstPtr &barr_inst);
68,69c103
< void pop();
<
---
> /** Indicate that an instruction has its registers ready. */
71a106
> /** Indicate that a non-speculative instruction is ready. */
74c109,110
< void issue(DynInstPtr &inst);
---
> /** Reschedules an instruction to be re-executed. */
> void reschedule(DynInstPtr &inst);
75a112,123
> /** Replays all instructions that have been rescheduled by moving them to
> * the ready list.
> */
> void replay(DynInstPtr &inst);
>
> /** Completes a memory instruction. */
> void completed(DynInstPtr &inst);
>
> /** Completes a barrier instruction. */
> void completeBarrier(DynInstPtr &inst);
>
> /** Wakes any dependents of a memory instruction. */
78c126,129
< void squash(const InstSeqNum &squashed_num);
---
> /** Squashes all instructions up until a given sequence number for a
> * specific thread.
> */
> void squash(const InstSeqNum &squashed_num, unsigned tid);
79a131
> /** Indicates an ordering violation between a store and a younger load. */
82,83c134,135
< inline bool empty()
< { return readyInsts.empty(); }
---
> /** Issues the given instruction */
> void issue(DynInstPtr &inst);
84a137,139
> /** Debugging function to dump the lists of instructions. */
> void dumpLists();
>
86,87c141
< typedef typename std::set<InstSeqNum>::iterator sn_it_t;
< typedef typename std::map<InstSeqNum, DynInstPtr>::iterator dyn_it_t;
---
> typedef typename std::list<DynInstPtr>::iterator ListIt;
89,91c143
< // Forward declarations so that the following two typedefs work.
< class Dependency;
< class ltDependency;
---
> class MemDepEntry;
93,95c145
< typedef typename std::set<Dependency, ltDependency>::iterator dep_it_t;
< typedef typename std::map<InstSeqNum, vector<dep_it_t> >::iterator
< sd_it_t;
---
> typedef RefCountingPtr<MemDepEntry> MemDepEntryPtr;
97,100c147,158
< struct Dependency {
< Dependency(const InstSeqNum &_seqNum)
< : seqNum(_seqNum), regsReady(0), memDepReady(0)
< { }
---
> /** Memory dependence entries that track memory operations, marking
> * when the instruction is ready to execute and what instructions depend
> * upon it.
> */
> class MemDepEntry : public RefCounted {
> public:
> /** Constructs a memory dependence entry. */
> MemDepEntry(DynInstPtr &new_inst)
> : inst(new_inst), regsReady(false), memDepReady(false),
> completed(false), squashed(false)
> {
> ++memdep_count;
102,106c160,162
< Dependency(const InstSeqNum &_seqNum, bool _regsReady,
< bool _memDepReady)
< : seqNum(_seqNum), regsReady(_regsReady),
< memDepReady(_memDepReady)
< { }
---
> DPRINTF(MemDepUnit, "Memory dependency entry created. "
> "memdep_count=%i\n", memdep_count);
> }
108,115c164,165
< InstSeqNum seqNum;
< mutable bool regsReady;
< mutable bool memDepReady;
< mutable sd_it_t storeDep;
< };
<
< struct ltDependency {
< bool operator() (const Dependency &lhs, const Dependency &rhs)
---
> /** Frees any pointers. */
> ~MemDepEntry()
117c167,174
< return lhs.seqNum < rhs.seqNum;
---
> for (int i = 0; i < dependInsts.size(); ++i) {
> dependInsts[i] = NULL;
> }
>
> --memdep_count;
>
> DPRINTF(MemDepUnit, "Memory dependency entry deleted. "
> "memdep_count=%i\n", memdep_count);
118a176,201
>
> /** Returns the name of the memory dependence entry. */
> std::string name() const { return "memdepentry"; }
>
> /** The instruction being tracked. */
> DynInstPtr inst;
>
> /** The iterator to the instruction's location inside the list. */
> ListIt listIt;
>
> /** A vector of any dependent instructions. */
> std::vector<MemDepEntryPtr> dependInsts;
>
> /** If the registers are ready or not. */
> bool regsReady;
> /** If all memory dependencies have been satisfied. */
> bool memDepReady;
> /** If the instruction is completed. */
> bool completed;
> /** If the instruction is squashed. */
> bool squashed;
>
> /** For debugging. */
> static int memdep_count;
> static int memdep_insert;
> static int memdep_erase;
121c204,205
< inline void moveToReady(dep_it_t &woken_inst);
---
> /** Finds the memory dependence entry in the hash map. */
> inline MemDepEntryPtr &findInHash(const DynInstPtr &inst);
123,127c207,208
< /** List of instructions that have passed through rename, yet are still
< * waiting on either a memory dependence to resolve or source registers to
< * become available before they can issue.
< */
< std::set<Dependency, ltDependency> waitingInsts;
---
> /** Moves an entry to the ready list. */
> inline void moveToReady(MemDepEntryPtr &ready_inst_entry);
129,132c210
< /** List of instructions that have all their predicted memory dependences
< * resolved and their source registers ready.
< */
< std::set<InstSeqNum> readyInsts;
---
> typedef m5::hash_map<InstSeqNum, MemDepEntryPtr, SNHash> MemDepHash;
134,140c212
< // Change this to hold a vector of iterators, which will point to the
< // entry of the waiting instructions.
< /** List of stores' sequence numbers, each of which has a vector of
< * iterators. The iterators point to the appropriate node within
< * waitingInsts that has the depenendent instruction.
< */
< std::map<InstSeqNum, vector<dep_it_t> > storeDependents;
---
> typedef typename MemDepHash::iterator MemDepHashIt;
142,145c214,215
< // For now will implement this as a map...hash table might not be too
< // bad, or could move to something that mimics the current dependency
< // graph.
< std::map<InstSeqNum, DynInstPtr> memInsts;
---
> /** A hash map of all memory dependence entries. */
> MemDepHash memDepHash;
147,149c217,218
< // Iterator pointer to the top instruction which has is ready.
< // Is set by the top() call.
< dyn_it_t topInst;
---
> /** A list of all instructions in the memory dependence unit. */
> std::list<DynInstPtr> instList[Impl::MaxThreads];
150a220,222
> /** A list of all instructions that are going to be replayed. */
> std::list<DynInstPtr> instsToReplay;
>
157a230,241
> bool loadBarrier;
> InstSeqNum loadBarrierSN;
> bool storeBarrier;
> InstSeqNum storeBarrierSN;
>
> /** Pointer to the IQ. */
> InstructionQueue<Impl> *iqPtr;
>
> /** The thread id of this memory dependence unit. */
> int id;
>
> /** Stat for number of inserted loads. */
158a243
> /** Stat for number of inserted stores. */
159a245
> /** Stat for number of conflicting loads that had to wait for a store. */
160a247
> /** Stat for number of conflicting stores that had to wait for a store. */
164c251
< #endif // __CPU_O3_CPU_MEM_DEP_UNIT_HH__
---
> #endif // __CPU_O3_MEM_DEP_UNIT_HH__