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
29,30c31,32
< #ifndef __CPU_O3_MEM_DEP_UNIT_HH__
< #define __CPU_O3_MEM_DEP_UNIT_HH__
---
> #ifndef __CPU_O3_CPU_MEM_DEP_UNIT_HH__
> #define __CPU_O3_CPU_MEM_DEP_UNIT_HH__
32c34
< #include <list>
---
> #include <map>
35,36d36
< #include "base/hashmap.hh"
< #include "base/refcnt.hh"
40,51d39
< 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;
<
69,70c57,58
< /** Empty constructor. Must call init() prior to using in this case. */
< MemDepUnit() {}
---
> public:
> MemDepUnit(Params &params);
72,84d59
< /** 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. */
87,94d61
< void switchOut();
<
< void takeOverFrom();
<
< /** Sets the pointer to the IQ. */
< void setIQ(InstructionQueue<Impl> *iq_ptr);
<
< /** Inserts a memory instruction. */
97d63
< /** Inserts a non-speculative memory instruction. */
100,101c66,68
< /** Inserts a barrier instruction. */
< void insertBarrier(DynInstPtr &barr_inst);
---
> // Will want to make this operation relatively fast. Right now it
> // is somewhat slow.
> DynInstPtr &top();
103c70,71
< /** Indicate that an instruction has its registers ready. */
---
> void pop();
>
106d73
< /** Indicate that a non-speculative instruction is ready. */
109,110c76
< /** Reschedules an instruction to be re-executed. */
< void reschedule(DynInstPtr &inst);
---
> void issue(DynInstPtr &inst);
112,123d77
< /** 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. */
126,129c80
< /** Squashes all instructions up until a given sequence number for a
< * specific thread.
< */
< void squash(const InstSeqNum &squashed_num, unsigned tid);
---
> void squash(const InstSeqNum &squashed_num);
131d81
< /** Indicates an ordering violation between a store and a younger load. */
134,135c84,85
< /** Issues the given instruction */
< void issue(DynInstPtr &inst);
---
> inline bool empty()
> { return readyInsts.empty(); }
137,139d86
< /** Debugging function to dump the lists of instructions. */
< void dumpLists();
<
141c88,89
< typedef typename std::list<DynInstPtr>::iterator ListIt;
---
> typedef typename std::set<InstSeqNum>::iterator sn_it_t;
> typedef typename std::map<InstSeqNum, DynInstPtr>::iterator dyn_it_t;
143c91,93
< class MemDepEntry;
---
> // Forward declarations so that the following two typedefs work.
> class Dependency;
> class ltDependency;
145c95,97
< typedef RefCountingPtr<MemDepEntry> MemDepEntryPtr;
---
> typedef typename std::set<Dependency, ltDependency>::iterator dep_it_t;
> typedef typename std::map<InstSeqNum, vector<dep_it_t> >::iterator
> sd_it_t;
147,158c99,102
< /** 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;
---
> struct Dependency {
> Dependency(const InstSeqNum &_seqNum)
> : seqNum(_seqNum), regsReady(0), memDepReady(0)
> { }
160,162c104,108
< DPRINTF(MemDepUnit, "Memory dependency entry created. "
< "memdep_count=%i\n", memdep_count);
< }
---
> Dependency(const InstSeqNum &_seqNum, bool _regsReady,
> bool _memDepReady)
> : seqNum(_seqNum), regsReady(_regsReady),
> memDepReady(_memDepReady)
> { }
164,169c110,114
< /** Frees any pointers. */
< ~MemDepEntry()
< {
< for (int i = 0; i < dependInsts.size(); ++i) {
< dependInsts[i] = NULL;
< }
---
> InstSeqNum seqNum;
> mutable bool regsReady;
> mutable bool memDepReady;
> mutable sd_it_t storeDep;
> };
171,174c116,119
< --memdep_count;
<
< DPRINTF(MemDepUnit, "Memory dependency entry deleted. "
< "memdep_count=%i\n", memdep_count);
---
> struct ltDependency {
> bool operator() (const Dependency &lhs, const Dependency &rhs)
> {
> return lhs.seqNum < rhs.seqNum;
176,201d120
<
< /** 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;
204,205c123
< /** Finds the memory dependence entry in the hash map. */
< inline MemDepEntryPtr &findInHash(const DynInstPtr &inst);
---
> inline void moveToReady(dep_it_t &woken_inst);
207,208c125,129
< /** Moves an entry to the ready list. */
< inline void moveToReady(MemDepEntryPtr &ready_inst_entry);
---
> /** 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;
210c131,134
< typedef m5::hash_map<InstSeqNum, MemDepEntryPtr, SNHash> MemDepHash;
---
> /** List of instructions that have all their predicted memory dependences
> * resolved and their source registers ready.
> */
> std::set<InstSeqNum> readyInsts;
212c136,142
< typedef typename MemDepHash::iterator MemDepHashIt;
---
> // 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;
214,215c144,147
< /** A hash map of all memory dependence entries. */
< MemDepHash memDepHash;
---
> // 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;
217,218c149,151
< /** A list of all instructions in the memory dependence unit. */
< std::list<DynInstPtr> instList[Impl::MaxThreads];
---
> // Iterator pointer to the top instruction which has is ready.
> // Is set by the top() call.
> dyn_it_t topInst;
220,222d152
< /** A list of all instructions that are going to be replayed. */
< std::list<DynInstPtr> instsToReplay;
<
230,241d159
< 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. */
243d160
< /** Stat for number of inserted stores. */
245d161
< /** Stat for number of conflicting loads that had to wait for a store. */
247d162
< /** Stat for number of conflicting stores that had to wait for a store. */
251c166
< #endif // __CPU_O3_MEM_DEP_UNIT_HH__
---
> #endif // __CPU_O3_CPU_MEM_DEP_UNIT_HH__