2c2
< * Copyright (c) 2004-2005 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2006 The Regents of The University of Michigan
31,32c31,32
< #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__
34c34
< #include <map>
---
> #include <list>
36a37,38
> #include "base/hashmap.hh"
> #include "base/refcnt.hh"
39a42,53
> 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;
>
57,58c71,72
< public:
< MemDepUnit(Params &params);
---
> /** Empty constructor. Must call init() prior to using in this case. */
> MemDepUnit() {}
59a74,86
> /** 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. */
61a89,96
> void switchOut();
>
> void takeOverFrom();
>
> /** Sets the pointer to the IQ. */
> void setIQ(InstructionQueue<Impl> *iq_ptr);
>
> /** Inserts a memory instruction. */
63a99
> /** Inserts a non-speculative memory instruction. */
66,68c102,103
< // 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);
70,71c105
< void pop();
<
---
> /** Indicate that an instruction has its registers ready. */
73a108
> /** Indicate that a non-speculative instruction is ready. */
76c111,112
< void issue(DynInstPtr &inst);
---
> /** Reschedules an instruction to be re-executed. */
> void reschedule(DynInstPtr &inst);
77a114,125
> /** 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. */
80c128,131
< 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);
81a133
> /** Indicates an ordering violation between a store and a younger load. */
84,85c136,137
< inline bool empty()
< { return readyInsts.empty(); }
---
> /** Issues the given instruction */
> void issue(DynInstPtr &inst);
86a139,141
> /** Debugging function to dump the lists of instructions. */
> void dumpLists();
>
88,89c143
< 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;
91,93c145
< // Forward declarations so that the following two typedefs work.
< class Dependency;
< class ltDependency;
---
> class MemDepEntry;
95,97c147
< 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;
99,102c149,160
< 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;
104,108c162,164
< 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);
> }
110,117c166,167
< 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()
119c169,176
< 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);
120a178,203
>
> /** 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;
123c206,207
< inline void moveToReady(dep_it_t &woken_inst);
---
> /** Finds the memory dependence entry in the hash map. */
> inline MemDepEntryPtr &findInHash(const DynInstPtr &inst);
125,129c209,210
< /** 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);
131,134c212
< /** 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;
136,142c214
< // 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;
144,147c216,217
< // 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;
149,151c219,220
< // 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];
152a222,224
> /** A list of all instructions that are going to be replayed. */
> std::list<DynInstPtr> instsToReplay;
>
159a232,243
> 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. */
160a245
> /** Stat for number of inserted stores. */
161a247
> /** Stat for number of conflicting loads that had to wait for a store. */
162a249
> /** Stat for number of conflicting stores that had to wait for a store. */
166c253
< #endif // __CPU_O3_CPU_MEM_DEP_UNIT_HH__
---
> #endif // __CPU_O3_MEM_DEP_UNIT_HH__