* instructions in flight that are dependent upon r34 will be
* in the linked list of dependGraph[34].
*/
- DepEntry *dependGraph;
+ std::vector<DepEntry> dependGraph;
/** Number of linked lists; identical to the number of registers. */
int numEntries;
template <class DynInstPtr>
DependencyGraph<DynInstPtr>::~DependencyGraph()
{
- delete [] dependGraph;
}
template <class DynInstPtr>
DependencyGraph<DynInstPtr>::resize(int num_entries)
{
numEntries = num_entries;
- dependGraph = new DepEntry[numEntries];
+ dependGraph.resize(numEntries);
}
template <class DynInstPtr>
/** Constructs an LSQ with the given parameters. */
LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params);
- ~LSQ() {
- if (thread) delete [] thread;
- }
+ ~LSQ() { }
/** Returns the name of the LSQ. */
std::string name() const;
/** The LSQ policy for SMT mode. */
LSQPolicy lsqPolicy;
- /** The LSQ units for individual threads. */
- LSQUnit *thread;
+ /** Transform a SMT sharing policy string into a LSQPolicy value. */
+ static LSQPolicy readLSQPolicy(const std::string& policy) {
+ std::string policy_ = policy;
+ std::transform(policy_.begin(), policy_.end(), policy_.begin(),
+ (int(*)(int)) tolower);
+ if (policy_ == "dynamic") {
+ return Dynamic;
+ } else if (policy_ == "partitioned") {
+ return Partitioned;
+ } else if (policy_ == "threshold") {
+ return Threshold;
+ }
+ assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic,"
+ "Partitioned, Threshold}");
+
+ // Some compilers complain if there is no return.
+ return Dynamic;
+ }
+
+ /** Auxiliary function to calculate per-thread max LSQ allocation limit.
+ * Depending on a policy, number of entries and possibly number of threads
+ * and threshold, this function calculates how many resources each thread
+ * can occupy at most.
+ */
+ static uint32_t maxLSQAllocation(const LSQPolicy& pol, uint32_t entries,
+ uint32_t numThreads, uint32_t SMTThreshold) {
+ if (pol == Dynamic) {
+ return entries;
+ } else if (pol == Partitioned) {
+ //@todo:make work if part_amt doesnt divide evenly.
+ return entries / numThreads;
+ } else if (pol == Threshold) {
+ //Divide up by threshold amount
+ //@todo: Should threads check the max and the total
+ //amount of the LSQ
+ return SMTThreshold;
+ }
+ return 0;
+ }
/** List of Active Threads in System. */
std::list<ThreadID> *activeThreads;
/** Max SQ Size - Used to Enforce Sharing Policies. */
unsigned maxSQEntries;
+ /** The LSQ units for individual threads. */
+ std::vector<LSQUnit> thread;
+
/** Number of Threads. */
ThreadID numThreads;
};
template <class Impl>
LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
: cpu(cpu_ptr), iewStage(iew_ptr),
+ lsqPolicy(readLSQPolicy(params->smtLSQPolicy)),
LQEntries(params->LQEntries),
SQEntries(params->SQEntries),
+ maxLQEntries(maxLSQAllocation(lsqPolicy, LQEntries, params->numThreads,
+ params->smtLSQThreshold)),
+ maxSQEntries(maxLSQAllocation(lsqPolicy, SQEntries, params->numThreads,
+ params->smtLSQThreshold)),
numThreads(params->numThreads)
{
assert(numThreads > 0 && numThreads <= Impl::MaxThreads);
//**********************************************/
//************ Handle SMT Parameters ***********/
//**********************************************/
- std::string policy = params->smtLSQPolicy;
-
- //Convert string to lowercase
- std::transform(policy.begin(), policy.end(), policy.begin(),
- (int(*)(int)) tolower);
//Figure out fetch policy
- if (policy == "dynamic") {
- lsqPolicy = Dynamic;
-
- maxLQEntries = LQEntries;
- maxSQEntries = SQEntries;
-
+ if (lsqPolicy == Dynamic) {
DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n");
- } else if (policy == "partitioned") {
- lsqPolicy = Partitioned;
-
- //@todo:make work if part_amt doesnt divide evenly.
- maxLQEntries = LQEntries / numThreads;
- maxSQEntries = SQEntries / numThreads;
-
+ } else if (lsqPolicy == Partitioned) {
DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: "
"%i entries per LQ | %i entries per SQ\n",
maxLQEntries,maxSQEntries);
- } else if (policy == "threshold") {
- lsqPolicy = Threshold;
+ } else if (lsqPolicy == Threshold) {
assert(params->smtLSQThreshold > LQEntries);
assert(params->smtLSQThreshold > SQEntries);
- //Divide up by threshold amount
- //@todo: Should threads check the max and the total
- //amount of the LSQ
- maxLQEntries = params->smtLSQThreshold;
- maxSQEntries = params->smtLSQThreshold;
-
DPRINTF(LSQ, "LSQ sharing policy set to Threshold: "
"%i entries per LQ | %i entries per SQ\n",
maxLQEntries,maxSQEntries);
"Partitioned, Threshold");
}
- //Initialize LSQs
- thread = new LSQUnit[numThreads];
+ thread.reserve(numThreads);
for (ThreadID tid = 0; tid < numThreads; tid++) {
- thread[tid].init(cpu, iew_ptr, params, this,
- maxLQEntries, maxSQEntries, tid);
+ thread.emplace_back(maxLQEntries, maxSQEntries);
+ thread[tid].init(cpu, iew_ptr, params, this, tid);
thread[tid].setDcachePort(&cpu_ptr->getDataPort());
}
}
public:
/** Constructs an LSQ unit. init() must be called prior to use. */
- LSQUnit();
+ LSQUnit(uint32_t lqEntries, uint32_t sqEntries);
+
+ /** We cannot copy LSQUnit because it has stats for which copy
+ * contructor is deleted explicitly. However, STL vector requires
+ * a valid copy constructor for the base type at compile time.
+ */
+ LSQUnit(const LSQUnit &l) { panic("LSQUnit is not copy-able"); }
/** Initializes the LSQ unit with the specified number of entries. */
void init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params,
- LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries,
- unsigned id);
+ LSQ *lsq_ptr, unsigned id);
/** Returns the name of the LSQ unit. */
std::string name() const;
}
template <class Impl>
-LSQUnit<Impl>::LSQUnit()
- : loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false),
+LSQUnit<Impl>::LSQUnit(uint32_t lqEntries, uint32_t sqEntries)
+ : lsqID(-1), storeQueue(sqEntries+1), loadQueue(lqEntries+1),
+ LQEntries(lqEntries+1), SQEntries(lqEntries+1),
+ loads(0), stores(0), storesToWB(0), cacheBlockMask(0), stalled(false),
isStoreBlocked(false), storeInFlight(false), hasPendingPkt(false),
pendingPkt(nullptr)
{
template<class Impl>
void
LSQUnit<Impl>::init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params,
- LSQ *lsq_ptr, unsigned maxLQEntries, unsigned maxSQEntries,
- unsigned id)
+ LSQ *lsq_ptr, unsigned id)
{
+ lsqID = id;
+
cpu = cpu_ptr;
iewStage = iew_ptr;
lsq = lsq_ptr;
- lsqID = id;
-
- DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id);
-
- // Add 1 for the sentinel entry (they are circular queues).
- LQEntries = maxLQEntries + 1;
- SQEntries = maxSQEntries + 1;
-
- //Due to uint8_t index in LSQSenderState
- assert(LQEntries <= 256);
- assert(SQEntries <= 256);
-
- loadQueue.resize(LQEntries);
- storeQueue.resize(SQEntries);
+ DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",lsqID);
depCheckShift = params->LSQDepCheckShift;
checkLoads = params->LSQCheckLoads;