summaryrefslogtreecommitdiff
path: root/cpu/beta_cpu/inst_queue.hh
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/beta_cpu/inst_queue.hh')
-rw-r--r--cpu/beta_cpu/inst_queue.hh133
1 files changed, 90 insertions, 43 deletions
diff --git a/cpu/beta_cpu/inst_queue.hh b/cpu/beta_cpu/inst_queue.hh
index 5741bfcf5..a170979cb 100644
--- a/cpu/beta_cpu/inst_queue.hh
+++ b/cpu/beta_cpu/inst_queue.hh
@@ -2,12 +2,13 @@
#define __INST_QUEUE_HH__
#include <list>
+#include <map>
#include <queue>
#include <stdint.h>
+#include <vector>
#include "base/timebuf.hh"
-
-using namespace std;
+#include "cpu/inst_seq.hh"
//Perhaps have a better separation between the data structure underlying
//and the actual algorithm.
@@ -24,48 +25,53 @@ using namespace std;
* and 96-191 are fp). This remains true even for both logical and
* physical register indices.
*/
-template<class Impl>
+template <class Impl>
class InstructionQueue
{
public:
//Typedefs from the Impl.
typedef typename Impl::FullCPU FullCPU;
- typedef typename Impl::DynInst DynInst;
+ typedef typename Impl::DynInstPtr DynInstPtr;
typedef typename Impl::Params Params;
- typedef typename Impl::IssueStruct IssueStruct;
- typedef typename Impl::TimeStruct TimeStruct;
+ typedef typename Impl::CPUPol::MemDepUnit MemDepUnit;
+ typedef typename Impl::CPUPol::IssueStruct IssueStruct;
+ typedef typename Impl::CPUPol::TimeStruct TimeStruct;
// Typedef of iterator through the list of instructions. Might be
// better to untie this from the FullCPU or pass its information to
// the stages.
- typedef typename list<DynInst *>::iterator ListIt;
+ typedef typename std::list<DynInstPtr>::iterator ListIt;
/**
- * Class for priority queue entries. Mainly made so that the < operator
- * is defined.
+ * Struct for comparing entries to be added to the priority queue. This
+ * gives reverse ordering to the instructions in terms of sequence
+ * numbers: the instructions with smaller sequence numbers (and hence
+ * are older) will be at the top of the priority queue.
*/
- struct ReadyEntry {
- DynInst *inst;
-
- ReadyEntry(DynInst *_inst)
- : inst(_inst)
- { }
-
- /** Compare(lhs,rhs) checks if rhs is "bigger" than lhs. If so, rhs
- * goes higher on the priority queue. The oldest instruction should
- * be on the top of the instruction queue, so in this case "bigger"
- * has the reverse meaning; the instruction with the lowest
- * sequence number is on the top.
- */
- bool operator <(const ReadyEntry &rhs) const
+ struct pqCompare
+ {
+ bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
{
- if (this->inst->seqNum > rhs.inst->seqNum)
- return true;
- return false;
+ return lhs->seqNum > rhs->seqNum;
}
};
+ /**
+ * Struct for comparing entries to be added to the set. This gives
+ * standard ordering in terms of sequence numbers.
+ */
+ struct setCompare
+ {
+ bool operator() (const DynInstPtr &lhs, const DynInstPtr &rhs) const
+ {
+ return lhs->seqNum < rhs->seqNum;
+ }
+ };
+
+ typedef std::priority_queue<DynInstPtr, vector<DynInstPtr>, pqCompare>
+ ReadyInstQueue;
+
InstructionQueue(Params &params);
void setCPU(FullCPU *cpu);
@@ -78,20 +84,32 @@ class InstructionQueue
bool isFull();
- void insert(DynInst *new_inst);
+ void insert(DynInstPtr &new_inst);
- void advanceTail(DynInst *inst);
+ void insertNonSpec(DynInstPtr &new_inst);
+
+ void advanceTail(DynInstPtr &inst);
void scheduleReadyInsts();
- void wakeDependents(DynInst *completed_inst);
+ void scheduleNonSpec(const InstSeqNum &inst);
- void doSquash();
+ void wakeDependents(DynInstPtr &completed_inst);
+
+ void violation(DynInstPtr &store, DynInstPtr &faulting_load);
void squash();
+ void doSquash();
+
void stopSquash();
+ /** Debugging function to dump all the list sizes, as well as print
+ * out the list of nonspeculative instructions. Should not be used
+ * in any other capacity, but it has no harmful sideaffects.
+ */
+ void dumpLists();
+
private:
/** Debugging function to count how many entries are in the IQ. It does
* a linear walk through the instructions, so do not call this function
@@ -103,6 +121,11 @@ class InstructionQueue
/** Pointer to the CPU. */
FullCPU *cpu;
+ /** The memory dependence unit, which tracks/predicts memory dependences
+ * between instructions.
+ */
+ MemDepUnit memDepUnit;
+
/** The queue to the execute stage. Issued instructions will be written
* into it.
*/
@@ -118,26 +141,46 @@ class InstructionQueue
Int,
Float,
Branch,
+ Memory,
+ Misc,
Squashed,
None
};
/** List of ready int instructions. Used to keep track of the order in
- * which */
- priority_queue<ReadyEntry> readyIntInsts;
+ * which instructions should issue.
+ */
+ ReadyInstQueue readyIntInsts;
/** List of ready floating point instructions. */
- priority_queue<ReadyEntry> readyFloatInsts;
+ ReadyInstQueue readyFloatInsts;
/** List of ready branch instructions. */
- priority_queue<ReadyEntry> readyBranchInsts;
+ ReadyInstQueue readyBranchInsts;
+
+ /** List of ready memory instructions. */
+ ReadyInstQueue readyMemInsts;
+
+ /** List of ready miscellaneous instructions. */
+ ReadyInstQueue readyMiscInsts;
/** List of squashed instructions (which are still valid and in IQ).
* Implemented using a priority queue; the entries must contain both
* the IQ index and sequence number of each instruction so that
* ordering based on sequence numbers can be used.
*/
- priority_queue<ReadyEntry> squashedInsts;
+ ReadyInstQueue squashedInsts;
+
+ /** List of non-speculative instructions that will be scheduled
+ * once the IQ gets a signal from commit. While it's redundant to
+ * have the key be a part of the value (the sequence number is stored
+ * inside of DynInst), when these instructions are woken up only
+ * the sequence number will be available. Thus it is necessary to be
+ * able to search by the sequence number alone.
+ */
+ std::map<InstSeqNum, DynInstPtr> nonSpecInsts;
+
+ typedef typename std::map<InstSeqNum, DynInstPtr>::iterator non_spec_it_t;
/** Number of free IQ entries left. */
unsigned freeEntries;
@@ -158,6 +201,9 @@ class InstructionQueue
/** The number of branches that can be issued in one cycle. */
unsigned branchWidth;
+ /** The number of memory instructions that can be issued in one cycle. */
+ unsigned memoryWidth;
+
/** The total number of instructions that can be issued in one cycle. */
unsigned totalWidth;
@@ -183,7 +229,7 @@ class InstructionQueue
InstSeqNum squashedSeqNum;
/** Iterator that points to the oldest instruction in the IQ. */
- ListIt head;
+// ListIt head;
/** Iterator that points to the youngest instruction in the IQ. */
ListIt tail;
@@ -200,7 +246,7 @@ class InstructionQueue
class DependencyEntry
{
public:
- DynInst *inst;
+ DynInstPtr inst;
//Might want to include data about what arch. register the
//dependence is waiting on.
DependencyEntry *next;
@@ -212,9 +258,9 @@ class InstructionQueue
//away. So for now it will sit here, within the IQ, until
//a better implementation is decided upon.
// This function probably shouldn't be within the entry...
- void insert(DynInst *new_inst);
+ void insert(DynInstPtr &new_inst);
- void remove(DynInst *inst_to_remove);
+ void remove(DynInstPtr &inst_to_remove);
};
/** Array of linked lists. Each linked list is a list of all the
@@ -233,11 +279,12 @@ class InstructionQueue
*/
vector<bool> regScoreboard;
- bool addToDependents(DynInst *new_inst);
- void insertDependency(DynInst *new_inst);
- void createDependency(DynInst *new_inst);
+ bool addToDependents(DynInstPtr &new_inst);
+ void insertDependency(DynInstPtr &new_inst);
+ void createDependency(DynInstPtr &new_inst);
+ void dumpDependGraph();
- void addIfReady(DynInst *inst);
+ void addIfReady(DynInstPtr &inst);
};
#endif //__INST_QUEUE_HH__