cpu: Change raw pointers to STL Containers
authorRekai Gonzalez-Alberquilla <rekai.gonzalezalberquilla@arm.com>
Wed, 1 Mar 2017 13:49:08 +0000 (13:49 +0000)
committerGiacomo Gabrielli <giacomo.gabrielli@arm.com>
Mon, 3 Dec 2018 14:23:56 +0000 (14:23 +0000)
This patch changes two members from being raw pointers to being STL
containers. The reason behind, other than cleanlyness and arguable OO
best practices is that containers have more intronspections capabilities
than naked pointers do, as the size is known.

Using STL containers adds little overhead and eases the automation of
process during debugging (gdb).

Change-Id: I4d9d3eedafa8b5e50ac512ea93b458a4200229f2
Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/13126
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Maintainer: Jason Lowe-Power <jason@lowepower.com>

src/cpu/o3/dep_graph.hh
src/cpu/o3/lsq.hh
src/cpu/o3/lsq_impl.hh
src/cpu/o3/lsq_unit.hh
src/cpu/o3/lsq_unit_impl.hh

index 212130e2b9ae86a1903add48613de9b519a18041..2e866a6c56c195a6bc9836d8caf2d1d50465526e 100644 (file)
@@ -122,7 +122,7 @@ class DependencyGraph
      *  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;
@@ -140,7 +140,6 @@ class DependencyGraph
 template <class DynInstPtr>
 DependencyGraph<DynInstPtr>::~DependencyGraph()
 {
-    delete [] dependGraph;
 }
 
 template <class DynInstPtr>
@@ -148,7 +147,7 @@ void
 DependencyGraph<DynInstPtr>::resize(int num_entries)
 {
     numEntries = num_entries;
-    dependGraph = new DepEntry[numEntries];
+    dependGraph.resize(numEntries);
 }
 
 template <class DynInstPtr>
index 175821e69fb305d555f2db9ee53b7b469521c361..0c93121e3d8cf29c93854a6a494f3d04b4d0fb0d 100644 (file)
@@ -71,9 +71,7 @@ class LSQ {
 
     /** 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;
@@ -310,8 +308,45 @@ class LSQ {
     /** 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;
@@ -327,6 +362,9 @@ class LSQ {
     /** 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;
 };
index 83de8ddff2b879285fc4143efa1da0e0a8aa83f1..36bc17bc8514c653551fb60431c99b522e2ed6cb 100644 (file)
@@ -61,8 +61,13 @@ using namespace std;
 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);
@@ -70,42 +75,19 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
     //**********************************************/
     //************ 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);
@@ -114,11 +96,10 @@ LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params)
                     "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());
     }
 }
index 813a3cac70da131f54dff2d6da77505cbb2bcb0c..48a06b386a098d02c77a9c28deb728c52ee2e0da 100644 (file)
@@ -86,12 +86,17 @@ class LSQUnit {
 
   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;
index d8f1c39c63eed48e44a5e0205c8f5f71df2b7362..5438c4d07df68a5c01d6d3fa0c74232fec29c7a7 100644 (file)
@@ -142,8 +142,10 @@ LSQUnit<Impl>::completeDataAccess(PacketPtr pkt)
 }
 
 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)
 {
@@ -152,28 +154,16 @@ LSQUnit<Impl>::LSQUnit()
 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;