summaryrefslogtreecommitdiff
path: root/src/dev/arm/generic_timer.hh
diff options
context:
space:
mode:
authorAndreas Sandberg <andreas.sandberg@arm.com>2015-05-23 13:46:52 +0100
committerAndreas Sandberg <andreas.sandberg@arm.com>2015-05-23 13:46:52 +0100
commit65f3f097d3c270d2f28fc7d55651afaefb56ceed (patch)
tree099c9667e246b9e8197f292c1880d9f7a3af9159 /src/dev/arm/generic_timer.hh
parent5435f25ec80ff691c4e42e06888c60a01848a31d (diff)
downloadgem5-65f3f097d3c270d2f28fc7d55651afaefb56ceed.tar.xz
dev, arm: Refactor and clean up the generic timer model
This changeset cleans up the generic timer a bit and moves most of the register juggling from the ISA code into a separate class in the same source file as the rest of the generic timer. It also removes the assumption that there is always 8 or fewer CPUs in the system. Instead of having a fixed limit, we now instantiate per-core timers as they are requested. This is all in preparation for other patches that add support for virtual timers and a memory mapped interface.
Diffstat (limited to 'src/dev/arm/generic_timer.hh')
-rw-r--r--src/dev/arm/generic_timer.hh300
1 files changed, 181 insertions, 119 deletions
diff --git a/src/dev/arm/generic_timer.hh b/src/dev/arm/generic_timer.hh
index bc43f8b3b..8dc921275 100644
--- a/src/dev/arm/generic_timer.hh
+++ b/src/dev/arm/generic_timer.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 ARM Limited
+ * Copyright (c) 2013, 2015 ARM Limited
* All rights reserved.
*
* The license below extends only to copyright in the software and shall
@@ -35,13 +35,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Giacomo Gabrielli
+ * Andreas Sandberg
*/
#ifndef __DEV_ARM_GENERIC_TIMER_HH__
#define __DEV_ARM_GENERIC_TIMER_HH__
+#include "arch/arm/isa_device.hh"
#include "base/bitunion.hh"
-#include "params/GenericTimer.hh"
+#include "dev/arm/base_gic.hh"
#include "sim/core.hh"
#include "sim/sim_object.hh"
@@ -51,149 +53,209 @@
/// ARM, Issue C, Chapter 17).
class Checkpoint;
-class BaseGic;
+class GenericTimerParams;
-/// Wrapper around the actual counters and timers of the Generic Timer
-/// extension.
-class GenericTimer : public SimObject
+/// Global system counter. It is shared by the architected timers.
+/// @todo: implement memory-mapped controls
+class SystemCounter
{
+ protected:
+ /// Counter frequency (as specified by CNTFRQ).
+ uint64_t _freq;
+ /// Cached copy of the counter period (inverse of the frequency).
+ Tick _period;
+ /// Tick when the counter was reset.
+ Tick _resetTick;
+
+ uint32_t _regCntkctl;
+
public:
+ SystemCounter();
- /// Global system counter. It is shared by the architected timers.
- /// @todo: implement memory-mapped controls
- class SystemCounter
+ /// Returns the current value of the physical counter.
+ uint64_t value() const
{
- protected:
- /// Counter frequency (as specified by CNTFRQ).
- uint64_t _freq;
- /// Cached copy of the counter period (inverse of the frequency).
- Tick _period;
- /// Tick when the counter was reset.
- Tick _resetTick;
+ if (_freq == 0)
+ return 0; // Counter is still off.
+ return (curTick() - _resetTick) / _period;
+ }
+
+ /// Returns the counter frequency.
+ uint64_t freq() const { return _freq; }
+ /// Sets the counter frequency.
+ /// @param freq frequency in Hz.
+ void setFreq(uint32_t freq);
+
+ /// Returns the counter period.
+ Tick period() const { return _period; }
+ void setKernelControl(uint32_t val) { _regCntkctl = val; }
+ uint32_t getKernelControl() { return _regCntkctl; }
+
+ void serialize(std::ostream &os) const;
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ private:
+ // Disable copying
+ SystemCounter(const SystemCounter &c);
+};
+
+/// Per-CPU architected timer.
+class ArchTimer
+{
+ public:
+ class Interrupt
+ {
public:
- /// Ctor.
- SystemCounter()
- : _freq(0), _period(0), _resetTick(0)
- {
- setFreq(0x01800000);
- }
-
- /// Returns the current value of the physical counter.
- uint64_t value() const
- {
- if (_freq == 0)
- return 0; // Counter is still off.
- return (curTick() - _resetTick) / _period;
- }
-
- /// Returns the counter frequency.
- uint64_t freq() const { return _freq; }
- /// Sets the counter frequency.
- /// @param freq frequency in Hz.
- void setFreq(uint32_t freq);
-
- /// Returns the counter period.
- Tick period() const { return _period; }
-
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
+ Interrupt(BaseGic &gic, unsigned irq)
+ : _gic(gic), _ppi(false), _irq(irq), _cpu(0) {}
+
+ Interrupt(BaseGic &gic, unsigned irq, unsigned cpu)
+ : _gic(gic), _ppi(true), _irq(irq), _cpu(cpu) {}
+
+ void send();
+ void clear();
+
+ private:
+ BaseGic &_gic;
+ const bool _ppi;
+ const unsigned _irq;
+ const unsigned _cpu;
};
- /// Per-CPU architected timer.
- class ArchTimer
- {
- protected:
- /// Control register.
- BitUnion32(ArchTimerCtrl)
- Bitfield<0> enable;
- Bitfield<1> imask;
- Bitfield<2> istatus;
- EndBitUnion(ArchTimerCtrl)
-
- /// Name of this timer.
- std::string _name;
- /// Pointer to parent class.
- GenericTimer *_parent;
- /// Pointer to the global system counter.
- SystemCounter *_counter;
- /// ID of the CPU this timer is attached to.
- int _cpuNum;
- /// ID of the interrupt to be triggered.
- int _intNum;
- /// Cached value of the control register ({CNTP/CNTHP/CNTV}_CTL).
- ArchTimerCtrl _control;
- /// Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL).
- uint64_t _counterLimit;
-
- /// Called when the upcounter reaches the programmed value.
- void counterLimitReached();
- EventWrapper<ArchTimer, &ArchTimer::counterLimitReached>
- _counterLimitReachedEvent;
-
- /// Returns the value of the counter which this timer relies on.
- uint64_t counterValue() const { return _counter->value(); }
+ protected:
+ /// Control register.
+ BitUnion32(ArchTimerCtrl)
+ Bitfield<0> enable;
+ Bitfield<1> imask;
+ Bitfield<2> istatus;
+ EndBitUnion(ArchTimerCtrl)
- public:
- /// Ctor.
- ArchTimer()
- : _control(0), _counterLimit(0), _counterLimitReachedEvent(this)
- {}
+ /// Name of this timer.
+ const std::string _name;
- /// Returns the timer name.
- std::string name() const { return _name; }
+ /// Pointer to parent class.
+ SimObject &_parent;
- /// Returns the CompareValue view of the timer.
- uint64_t compareValue() const { return _counterLimit; }
- /// Sets the CompareValue view of the timer.
- void setCompareValue(uint64_t val);
+ SystemCounter &_systemCounter;
- /// Returns the TimerValue view of the timer.
- uint32_t timerValue() const { return _counterLimit - counterValue(); }
- /// Sets the TimerValue view of the timer.
- void setTimerValue(uint32_t val);
+ Interrupt _interrupt;
- /// Sets the control register.
- uint32_t control() const { return _control; }
- void setControl(uint32_t val);
+ /// Value of the control register ({CNTP/CNTHP/CNTV}_CTL).
+ ArchTimerCtrl _control;
+ /// Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL).
+ uint64_t _counterLimit;
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
+ /**
+ * Timer settings or the offset has changed, re-evaluate
+ * trigger condition and raise interrupt if necessary.
+ */
+ void updateCounter();
- friend class GenericTimer;
- };
+ /// Called when the upcounter reaches the programmed value.
+ void counterLimitReached();
+ EventWrapper<ArchTimer, &ArchTimer::counterLimitReached>
+ _counterLimitReachedEvent;
+
+ public:
+ ArchTimer(const std::string &name,
+ SimObject &parent,
+ SystemCounter &sysctr,
+ const Interrupt &interrupt);
+
+ /// Returns the timer name.
+ std::string name() const { return _name; }
+
+ /// Returns the CompareValue view of the timer.
+ uint64_t compareValue() const { return _counterLimit; }
+ /// Sets the CompareValue view of the timer.
+ void setCompareValue(uint64_t val);
+
+ /// Returns the TimerValue view of the timer.
+ uint32_t timerValue() const { return _counterLimit - value(); }
+ /// Sets the TimerValue view of the timer.
+ void setTimerValue(uint32_t val);
+
+ /// Sets the control register.
+ uint32_t control() const { return _control; }
+ void setControl(uint32_t val);
+
+ /// Returns the value of the counter which this timer relies on.
+ uint64_t value() const;
+
+ void serialize(std::ostream &os) const;
+ void unserialize(Checkpoint *cp, const std::string &section);
+
+ private:
+ // Disable copying
+ ArchTimer(const ArchTimer &t);
+};
+
+class GenericTimer : public SimObject
+{
+ public:
+ GenericTimer(GenericTimerParams *p);
+
+ void serialize(std::ostream &os) M5_ATTR_OVERRIDE;
+ void unserialize(Checkpoint *cp, const std::string &sec) M5_ATTR_OVERRIDE;
+
+ public:
+ void setMiscReg(int misc_reg, unsigned cpu, ArmISA::MiscReg val);
+ ArmISA::MiscReg readMiscReg(int misc_reg, unsigned cpu);
protected:
+ struct CoreTimers {
+ CoreTimers(GenericTimer &parent, unsigned cpu,
+ unsigned _irqPhys)
+ : irqPhys(*parent.gic, _irqPhys, cpu),
+ // This should really be phys_timerN, but we are stuck with
+ // arch_timer for backwards compatibility.
+ phys(csprintf("%s.arch_timer%d", parent.name(), cpu),
+ parent, parent.systemCounter,
+ irqPhys)
+ {}
- static const int CPU_MAX = 8;
+ ArchTimer::Interrupt irqPhys;
+ ArchTimer phys;
+
+ private:
+ // Disable copying
+ CoreTimers(const CoreTimers &c);
+ };
+
+ CoreTimers &getTimers(int cpu_id);
+ void createTimers(unsigned cpus);
- /// Pointer to the GIC, needed to trigger timer interrupts.
- BaseGic *_gic;
/// System counter.
- SystemCounter _systemCounter;
- /// Per-CPU architected timers.
- // @todo: this would become a 2-dim. array with Security and Virt.
- ArchTimer _archTimers[CPU_MAX];
+ SystemCounter systemCounter;
- public:
- typedef GenericTimerParams Params;
- const Params *
- params() const
- {
- return dynamic_cast<const Params *>(_params);
- }
+ /// Per-CPU physical architected timers.
+ std::vector<std::unique_ptr<CoreTimers>> timers;
- /// Ctor.
- GenericTimer(Params *p);
+ protected: // Configuration
+ /// Pointer to the GIC, needed to trigger timer interrupts.
+ BaseGic *const gic;
- /// Returns a pointer to the system counter.
- SystemCounter *getSystemCounter() { return &_systemCounter; }
+ /// Physical timer interrupt
+ const unsigned irqPhys;
+};
- /// Returns a pointer to the architected timer for cpu_id.
- ArchTimer *getArchTimer(int cpu_id) { return &_archTimers[cpu_id]; }
+class GenericTimerISA : public ArmISA::BaseISADevice
+{
+ public:
+ GenericTimerISA(GenericTimer &_parent, unsigned _cpu)
+ : parent(_parent), cpu(_cpu) {}
+
+ void setMiscReg(int misc_reg, ArmISA::MiscReg val) M5_ATTR_OVERRIDE {
+ parent.setMiscReg(misc_reg, cpu, val);
+ }
+ ArmISA::MiscReg readMiscReg(int misc_reg) M5_ATTR_OVERRIDE {
+ return parent.readMiscReg(misc_reg, cpu);
+ }
- virtual void serialize(std::ostream &os);
- virtual void unserialize(Checkpoint *cp, const std::string &section);
+ protected:
+ GenericTimer &parent;
+ unsigned cpu;
};
#endif // __DEV_ARM_GENERIC_TIMER_HH__