dev-arm: Fix WalkCache stats

The WalkCache stats are wrongly using the legacy framework.
With this patch we are registering those to the hierarchical structure.

As we need to pass the Stats::Group parent at construction time,
we are replacing 2d arrays with Vector2d for count stats and using a flat
vector of pointers for the Formula stats

Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Change-Id: I8992bc262a376e4e81a4d608c11dff6902e0a01d
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/42984
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
diff --git a/src/dev/arm/smmu_v3_caches.cc b/src/dev/arm/smmu_v3_caches.cc
index 59f5aca..b09fb31 100644
--- a/src/dev/arm/smmu_v3_caches.cc
+++ b/src/dev/arm/smmu_v3_caches.cc
@@ -1228,68 +1228,105 @@
 
 WalkCache::
 WalkCacheStats::WalkCacheStats(Stats::Group *parent)
-    : Stats::Group(parent)
+    : Stats::Group(parent),
+      ADD_STAT(totalLookupsByStageLevel, UNIT_COUNT,
+          "Total number of lookups"),
+      ADD_STAT(totalMissesByStageLevel, UNIT_COUNT,
+          "Total number of misses"),
+      ADD_STAT(totalUpdatesByStageLevel, UNIT_COUNT,
+          "Total number of updates"),
+      ADD_STAT(insertionsByStageLevel, UNIT_COUNT,
+          "Number of insertions (not replacements)")
 {
     using namespace Stats;
 
+    totalLookupsByStageLevel
+        .init(2, WALK_CACHE_LEVELS)
+        .flags(pdf);
+    totalMissesByStageLevel
+        .init(2, WALK_CACHE_LEVELS)
+        .flags(pdf);
+    totalUpdatesByStageLevel
+        .init(2, WALK_CACHE_LEVELS)
+        .flags(pdf);
+    insertionsByStageLevel
+        .init(2, WALK_CACHE_LEVELS)
+        .flags(pdf);
+
     for (int s = 0; s < 2; s++) {
+        totalLookupsByStageLevel.subname(s, csprintf("S%d", s + 1));
+        totalMissesByStageLevel.subname(s, csprintf("S%d", s + 1));
+        totalUpdatesByStageLevel.subname(s, csprintf("S%d", s + 1));
+        insertionsByStageLevel.subname(s, csprintf("S%d", s + 1));
+
         for (int l = 0; l < WALK_CACHE_LEVELS; l++) {
-            averageLookupsByStageLevel[s][l]
-                .name(csprintf("averageLookupsS%dL%d", s+1, l))
-                .desc("Average number lookups per second")
-                .flags(pdf);
+            totalLookupsByStageLevel.ysubname(l, csprintf("L%d", l));
+            totalMissesByStageLevel.ysubname(l, csprintf("L%d", l));
+            totalUpdatesByStageLevel.ysubname(l, csprintf("L%d", l));
+            insertionsByStageLevel.ysubname(l, csprintf("L%d", l));
 
-            totalLookupsByStageLevel[s][l]
-                .name(csprintf("totalLookupsS%dL%d", s+1, l))
-                .desc("Total number of lookups")
-                .flags(pdf);
+            auto avg_lookup = new Stats::Formula(
+                this,
+                csprintf("averageLookups_S%dL%d", s+1, l).c_str(),
+                UNIT_RATE(Stats::Units::Count, Stats::Units::Second),
+                "Average number lookups per second");
+            avg_lookup->flags(pdf);
+            averageLookupsByStageLevel.push_back(avg_lookup);
 
-            averageLookupsByStageLevel[s][l] =
+            *avg_lookup =
                 totalLookupsByStageLevel[s][l] / simSeconds;
 
+            auto avg_misses = new Stats::Formula(
+                this,
+                csprintf("averageMisses_S%dL%d", s+1, l).c_str(),
+                UNIT_RATE(Stats::Units::Count, Stats::Units::Second),
+                "Average number misses per second");
+            avg_misses->flags(pdf);
+            averageMissesByStageLevel.push_back(avg_misses);
 
-            averageMissesByStageLevel[s][l]
-                .name(csprintf("averageMissesS%dL%d", s+1, l))
-                .desc("Average number misses per second")
-                .flags(pdf);
-
-            totalMissesByStageLevel[s][l]
-                .name(csprintf("totalMissesS%dL%d", s+1, l))
-                .desc("Total number of misses")
-                .flags(pdf);
-
-            averageMissesByStageLevel[s][l] =
+            *avg_misses =
                 totalMissesByStageLevel[s][l] / simSeconds;
 
+            auto avg_updates = new Stats::Formula(
+                this,
+                csprintf("averageUpdates_S%dL%d", s+1, l).c_str(),
+                UNIT_RATE(Stats::Units::Count, Stats::Units::Second),
+                "Average number updates per second");
+            avg_updates->flags(pdf);
+            averageUpdatesByStageLevel.push_back(avg_updates);
 
-            averageUpdatesByStageLevel[s][l]
-                .name(csprintf("averageUpdatesS%dL%d", s+1, l))
-                .desc("Average number updates per second")
-                .flags(pdf);
-
-            totalUpdatesByStageLevel[s][l]
-                .name(csprintf("totalUpdatesS%dL%d", s+1, l))
-                .desc("Total number of updates")
-                .flags(pdf);
-
-            averageUpdatesByStageLevel[s][l] =
+            *avg_updates =
                 totalUpdatesByStageLevel[s][l] / simSeconds;
 
+            auto avg_hitrate = new Stats::Formula(
+                this,
+                csprintf("averageHitRate_S%dL%d", s+1, l).c_str(),
+                UNIT_RATIO,
+                "Average hit rate");
+            avg_hitrate->flags(pdf);
+            averageHitRateByStageLevel.push_back(avg_hitrate);
 
-            averageHitRateByStageLevel[s][l]
-                .name(csprintf("averageHitRateS%dL%d", s+1, l))
-                .desc("Average hit rate")
-                .flags(pdf);
-
-            averageHitRateByStageLevel[s][l] =
+            *avg_hitrate =
                 (totalLookupsByStageLevel[s][l] -
                  totalMissesByStageLevel[s][l])
                 / totalLookupsByStageLevel[s][l];
 
-            insertionsByStageLevel[s][l]
-                .name(csprintf("insertionsS%dL%d", s+1, l))
-                .desc("Number of insertions (not replacements)")
-                .flags(pdf);
         }
     }
 }
+
+WalkCache::
+WalkCacheStats::~WalkCacheStats()
+{
+    for (auto avg_lookup : averageLookupsByStageLevel)
+        delete avg_lookup;
+
+    for (auto avg_miss : averageMissesByStageLevel)
+        delete avg_miss;
+
+    for (auto avg_update : averageUpdatesByStageLevel)
+        delete avg_update;
+
+    for (auto avg_hitrate : averageHitRateByStageLevel)
+        delete avg_hitrate;
+}
diff --git a/src/dev/arm/smmu_v3_caches.hh b/src/dev/arm/smmu_v3_caches.hh
index dee09f2..07c6242 100644
--- a/src/dev/arm/smmu_v3_caches.hh
+++ b/src/dev/arm/smmu_v3_caches.hh
@@ -325,22 +325,23 @@
     struct WalkCacheStats : public Stats::Group
     {
         WalkCacheStats(Stats::Group *parent);
+        ~WalkCacheStats();
 
         unsigned int lookupsByStageLevel[2][WALK_CACHE_LEVELS];
-        Stats::Formula averageLookupsByStageLevel[2][WALK_CACHE_LEVELS];
-        Stats::Scalar totalLookupsByStageLevel[2][WALK_CACHE_LEVELS];
+        std::vector<Stats::Formula*> averageLookupsByStageLevel;
+        Stats::Vector2d totalLookupsByStageLevel;
 
         unsigned int missesByStageLevel[2][WALK_CACHE_LEVELS];
-        Stats::Formula averageMissesByStageLevel[2][WALK_CACHE_LEVELS];
-        Stats::Scalar totalMissesByStageLevel[2][WALK_CACHE_LEVELS];
+        std::vector<Stats::Formula*> averageMissesByStageLevel;
+        Stats::Vector2d totalMissesByStageLevel;
 
         unsigned int updatesByStageLevel[2][WALK_CACHE_LEVELS];
-        Stats::Formula averageUpdatesByStageLevel[2][WALK_CACHE_LEVELS];
-        Stats::Scalar totalUpdatesByStageLevel[2][WALK_CACHE_LEVELS];
+        std::vector<Stats::Formula*> averageUpdatesByStageLevel;
+        Stats::Vector2d totalUpdatesByStageLevel;
 
-        Stats::Formula averageHitRateByStageLevel[2][WALK_CACHE_LEVELS];
+        std::vector<Stats::Formula*> averageHitRateByStageLevel;
 
-        Stats::Scalar insertionsByStageLevel[2][WALK_CACHE_LEVELS];
+        Stats::Vector2d insertionsByStageLevel;
     } walkCacheStats;
   private:
     typedef std::vector<Entry> Set;