mem-cache: Make cache warmup percentage a parameter.

The warmupPercentage is the percentage of different tags (based on the
cache size) that need to be touched in order to warm up the cache.
If Warmup failed (i.e., not enough tags were touched), warmup_cycle = 0.

The warmup is not being taken into account to calculate the stats (i.e.,
stats acquisition starts before cache is warmed up). Maybe in the future
this functionality should be added.

Change-Id: I2b93a99c19fddb99a4c60e6d4293fa355744d05e
Reviewed-on: https://gem5-review.googlesource.com/8061
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com>
diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py
index dce7e5b..bac6c73 100644
--- a/src/mem/cache/Cache.py
+++ b/src/mem/cache/Cache.py
@@ -57,6 +57,9 @@
     data_latency = Param.Cycles("Data access latency")
     response_latency = Param.Cycles("Latency for the return path on a miss");
 
+    warmup_percentage = Param.Percent(0,
+        "Percentage of tags to be touched to warm up the cache")
+
     max_miss_count = Param.Counter(0,
         "Number of misses to handle before calling exit")
 
diff --git a/src/mem/cache/tags/Tags.py b/src/mem/cache/tags/Tags.py
index 6c0b850..b19010f 100644
--- a/src/mem/cache/tags/Tags.py
+++ b/src/mem/cache/tags/Tags.py
@@ -57,6 +57,10 @@
     data_latency = Param.Cycles(Parent.data_latency,
                                "The data access latency for this cache")
 
+    # Get the warmup percentage from the parent (cache)
+    warmup_percentage = Param.Percent(Parent.warmup_percentage,
+        "Percentage of tags to be touched to warm up the cache")
+
     sequential_access = Param.Bool(Parent.sequential_access,
         "Whether to access tags and data sequentially")
 
diff --git a/src/mem/cache/tags/base.cc b/src/mem/cache/tags/base.cc
index 7796cd3..aa8a34f 100644
--- a/src/mem/cache/tags/base.cc
+++ b/src/mem/cache/tags/base.cc
@@ -61,7 +61,8 @@
       accessLatency(p->sequential_access ?
                     p->tag_latency + p->data_latency :
                     std::max(p->tag_latency, p->data_latency)),
-      cache(nullptr), warmupBound(0),
+      cache(nullptr),
+      warmupBound((p->warmup_percentage/100.0) * (p->size / p->block_size)),
       warmedUp(false), numBlocks(0)
 {
 }
diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh
index 5c9f46a..2c528a9 100644
--- a/src/mem/cache/tags/base.hh
+++ b/src/mem/cache/tags/base.hh
@@ -86,7 +86,7 @@
      * The number of tags that need to be touched to meet the warmup
      * percentage.
      */
-    int warmupBound;
+    const unsigned warmupBound;
     /** Marked true when the cache is warmed up. */
     bool warmedUp;
 
@@ -95,6 +95,7 @@
 
     // Statistics
     /**
+     * TODO: It would be good if these stats were acquired after warmup.
      * @addtogroup CacheStatistics
      * @{
      */
@@ -120,7 +121,7 @@
      */
     Stats::Formula avgRefs;
 
-    /** The cycle that the warmup percentage was hit. */
+    /** The cycle that the warmup percentage was hit. 0 on failure. */
     Stats::Scalar warmupCycle;
 
     /** Average occupancy of each requestor using the cache */
diff --git a/src/mem/cache/tags/base_set_assoc.cc b/src/mem/cache/tags/base_set_assoc.cc
index ba94475..cf647ac 100644
--- a/src/mem/cache/tags/base_set_assoc.cc
+++ b/src/mem/cache/tags/base_set_assoc.cc
@@ -73,8 +73,6 @@
     setShift = floorLog2(blkSize);
     setMask = numSets - 1;
     tagShift = setShift + floorLog2(numSets);
-    /** @todo Make warmup percentage a parameter. */
-    warmupBound = numSets * assoc;
 
     sets = new SetType[numSets];
     blks = new BlkType[numSets * assoc];
diff --git a/src/mem/cache/tags/fa_lru.cc b/src/mem/cache/tags/fa_lru.cc
index 895f795..dfd4c40 100644
--- a/src/mem/cache/tags/fa_lru.cc
+++ b/src/mem/cache/tags/fa_lru.cc
@@ -73,7 +73,6 @@
         cacheMask = 0;
     }
 
-    warmupBound = size/blkSize;
     numBlocks = size/blkSize;
 
     blks = new FALRUBlk[numBlocks];