dev-arm: GenericTimer, configurable base and low freqs
authorAdrian Herrera <adrian.herrera@arm.com>
Mon, 28 Oct 2019 20:28:51 +0000 (20:28 +0000)
committerGiacomo Travaglini <giacomo.travaglini@arm.com>
Tue, 10 Dec 2019 13:12:10 +0000 (13:12 +0000)
Architecture states the system counter has a fixed base frequency
provided in the first entry of the frequency modes table. Optionally,
other lower frequencies may be specified in consecutive entries.

This patch adds configurable frequencies to the GenericTimer model.
The default base frequency is kept as the one that was previously
hardcoded for backwards compatibility.

The table is not recommended to be updated once the system is running.

Change-Id: Icba0b340a0eb1cbb47dfe7d7e03b547af4570c60
Reviewed-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/22425
Maintainer: Giacomo Travaglini <giacomo.travaglini@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/dev/arm/RealView.py
src/dev/arm/generic_timer.cc
src/dev/arm/generic_timer.hh

index 6e8630a963a570e950769c14c43e2afbffe16969..37cf72ededae5fcdb7f478245733758cc4443da0 100644 (file)
@@ -404,6 +404,10 @@ class GenericTimer(ClockedObject):
     int_virt = Param.ArmPPI("Virtual timer interrupt")
     int_hyp = Param.ArmPPI("Hypervisor timer interrupt")
 
+    freqs = VectorParam.UInt32([0x01800000], "Frequencies available for the "
+        "system counter (in Hz). First element is the base frequency, "
+        "following are alternative lower ones which must be exact divisors")
+
     def generateDeviceTree(self, state):
         node = FdtNode("timer")
 
@@ -430,6 +434,10 @@ class GenericTimerMem(PioDevice):
     int_phys = Param.ArmSPI("Physical Interrupt")
     int_virt = Param.ArmSPI("Virtual Interrupt")
 
+    freqs = VectorParam.UInt32([0x01800000], "Frequencies available for the "
+        "system counter (in Hz). First element is the base frequency, "
+        "following are alternative lower ones which must be exact divisors")
+
 class PL031(AmbaIntDevice):
     type = 'PL031'
     cxx_header = "dev/arm/rtc_pl031.hh"
index 430b4ebfaf15826ce75000e6a93622a62b946cda..7c1f09addffa24e6950b5595430a4231921c50e8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, 2017-2018 ARM Limited
+ * Copyright (c) 2013, 2015, 2017-2018, 2019 ARM Limited
  * All rights reserved.
  *
  * The license below extends only to copyright in the software and shall
@@ -36,6 +36,7 @@
  *
  * Authors: Giacomo Gabrielli
  *          Andreas Sandberg
+ *          Adrian Herrera
  */
 
 #include "dev/arm/generic_timer.hh"
 #include "params/GenericTimer.hh"
 #include "params/GenericTimerMem.hh"
 
-SystemCounter::SystemCounter()
-    : _freq(0), _period(0), _resetTick(0), _regCntkctl(0)
+SystemCounter::SystemCounter(std::vector<uint32_t> &freqs)
+    : _freqTable(freqs),
+      _resetTick(0),
+      _regCntkctl(0)
 {
-    setFreq(0x01800000);
+    fatal_if(_freqTable.empty(), "SystemCounter::SystemCounter: Base "
+        "frequency not provided\n");
+    // Store the table end marker as a 32-bit zero word
+    _freqTable.push_back(0);
+    fatal_if(_freqTable.size() > MAX_FREQ_ENTRIES,
+        "SystemCounter::SystemCounter: Architecture states a maximum of 1004 "
+        "frequency table entries, limit surpassed\n");
+    // Set the active frequency to be the base
+    _freq = freqs.front();
+    _period = (1.0 / _freq) * SimClock::Frequency;
 }
 
 void
@@ -221,6 +233,7 @@ ArchTimer::drainResume()
 
 GenericTimer::GenericTimer(GenericTimerParams *p)
     : ClockedObject(p),
+      systemCounter(p->freqs),
       system(*p->system)
 {
     fatal_if(!p->system, "No system specified, can't instantiate timer.\n");
@@ -528,7 +541,7 @@ GenericTimerMem::GenericTimerMem(GenericTimerMemParams *p)
       timerRange(RangeSize(p->base + sys->getPageBytes(),
                   sys->getPageBytes())),
       addrRanges{ctrlRange, timerRange},
-      systemCounter(),
+      systemCounter(p->freqs),
       physTimer(csprintf("%s.phys_timer0", name()),
                 *this, systemCounter,
                 p->int_phys->get()),
index 9a7f162e7b5740b159f2a1f8a9747fff0b192b38..5e1965baf10eb55c4281f7beef984783efaaa409 100644 (file)
@@ -36,6 +36,7 @@
  *
  * Authors: Giacomo Gabrielli
  *          Andreas Sandberg
+ *          Adrian Herrera
  */
 
 #ifndef __DEV_ARM_GENERIC_TIMER_HH__
@@ -64,6 +65,8 @@ class SystemCounter : public Serializable
   protected:
     /// Counter frequency (as specified by CNTFRQ).
     uint32_t _freq;
+    /// Frequency modes table with all possible frequencies for the counter
+    std::vector<uint32_t> _freqTable;
     /// Cached copy of the counter period (inverse of the frequency).
     Tick _period;
     /// Tick when the counter was reset.
@@ -74,8 +77,11 @@ class SystemCounter : public Serializable
     /// Hypervisor event stream control register
     uint32_t _regCnthctl;
 
+    /// Maximum architectural number of frequency table entries
+    static constexpr size_t MAX_FREQ_ENTRIES = 1004;
+
   public:
-    SystemCounter();
+    SystemCounter(std::vector<uint32_t> &freqs);
 
     /// Returns the current value of the physical counter.
     uint64_t value() const