generic_timer.hh revision 10844
110037SARM gem5 Developers/*
210844Sandreas.sandberg@arm.com * Copyright (c) 2013, 2015 ARM Limited
310037SARM gem5 Developers * All rights reserved.
410037SARM gem5 Developers *
510037SARM gem5 Developers * The license below extends only to copyright in the software and shall
610037SARM gem5 Developers * not be construed as granting a license to any other intellectual
710037SARM gem5 Developers * property including but not limited to intellectual property relating
810037SARM gem5 Developers * to a hardware implementation of the functionality of the software
910037SARM gem5 Developers * licensed hereunder.  You may use the software subject to the license
1010037SARM gem5 Developers * terms below provided that you ensure that this notice is replicated
1110037SARM gem5 Developers * unmodified and in its entirety in all distributions of the software,
1210037SARM gem5 Developers * modified or unmodified, in source code or in binary form.
1310037SARM gem5 Developers *
1410037SARM gem5 Developers * Redistribution and use in source and binary forms, with or without
1510037SARM gem5 Developers * modification, are permitted provided that the following conditions are
1610037SARM gem5 Developers * met: redistributions of source code must retain the above copyright
1710037SARM gem5 Developers * notice, this list of conditions and the following disclaimer;
1810037SARM gem5 Developers * redistributions in binary form must reproduce the above copyright
1910037SARM gem5 Developers * notice, this list of conditions and the following disclaimer in the
2010037SARM gem5 Developers * documentation and/or other materials provided with the distribution;
2110037SARM gem5 Developers * neither the name of the copyright holders nor the names of its
2210037SARM gem5 Developers * contributors may be used to endorse or promote products derived from
2310037SARM gem5 Developers * this software without specific prior written permission.
2410037SARM gem5 Developers *
2510037SARM gem5 Developers * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610037SARM gem5 Developers * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710037SARM gem5 Developers * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810037SARM gem5 Developers * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910037SARM gem5 Developers * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010037SARM gem5 Developers * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110037SARM gem5 Developers * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210037SARM gem5 Developers * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310037SARM gem5 Developers * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410037SARM gem5 Developers * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510037SARM gem5 Developers * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610037SARM gem5 Developers *
3710037SARM gem5 Developers * Authors: Giacomo Gabrielli
3810844Sandreas.sandberg@arm.com *          Andreas Sandberg
3910037SARM gem5 Developers */
4010037SARM gem5 Developers
4110037SARM gem5 Developers#ifndef __DEV_ARM_GENERIC_TIMER_HH__
4210037SARM gem5 Developers#define __DEV_ARM_GENERIC_TIMER_HH__
4310037SARM gem5 Developers
4410844Sandreas.sandberg@arm.com#include "arch/arm/isa_device.hh"
4510037SARM gem5 Developers#include "base/bitunion.hh"
4610844Sandreas.sandberg@arm.com#include "dev/arm/base_gic.hh"
4710037SARM gem5 Developers#include "sim/core.hh"
4810037SARM gem5 Developers#include "sim/sim_object.hh"
4910037SARM gem5 Developers
5010037SARM gem5 Developers/// @file
5110037SARM gem5 Developers/// This module implements the global system counter and the local per-CPU
5210037SARM gem5 Developers/// architected timers as specified by the ARM Generic Timer extension (ARM
5310037SARM gem5 Developers/// ARM, Issue C, Chapter 17).
5410037SARM gem5 Developers
5510037SARM gem5 Developersclass Checkpoint;
5610844Sandreas.sandberg@arm.comclass GenericTimerParams;
5710037SARM gem5 Developers
5810844Sandreas.sandberg@arm.com/// Global system counter.  It is shared by the architected timers.
5910844Sandreas.sandberg@arm.com/// @todo: implement memory-mapped controls
6010844Sandreas.sandberg@arm.comclass SystemCounter
6110844Sandreas.sandberg@arm.com{
6210844Sandreas.sandberg@arm.com  protected:
6310844Sandreas.sandberg@arm.com    /// Counter frequency (as specified by CNTFRQ).
6410844Sandreas.sandberg@arm.com    uint64_t _freq;
6510844Sandreas.sandberg@arm.com    /// Cached copy of the counter period (inverse of the frequency).
6610844Sandreas.sandberg@arm.com    Tick _period;
6710844Sandreas.sandberg@arm.com    /// Tick when the counter was reset.
6810844Sandreas.sandberg@arm.com    Tick _resetTick;
6910844Sandreas.sandberg@arm.com
7010844Sandreas.sandberg@arm.com    uint32_t _regCntkctl;
7110844Sandreas.sandberg@arm.com
7210844Sandreas.sandberg@arm.com  public:
7310844Sandreas.sandberg@arm.com    SystemCounter();
7410844Sandreas.sandberg@arm.com
7510844Sandreas.sandberg@arm.com    /// Returns the current value of the physical counter.
7610844Sandreas.sandberg@arm.com    uint64_t value() const
7710844Sandreas.sandberg@arm.com    {
7810844Sandreas.sandberg@arm.com        if (_freq == 0)
7910844Sandreas.sandberg@arm.com            return 0;  // Counter is still off.
8010844Sandreas.sandberg@arm.com        return (curTick() - _resetTick) / _period;
8110844Sandreas.sandberg@arm.com    }
8210844Sandreas.sandberg@arm.com
8310844Sandreas.sandberg@arm.com    /// Returns the counter frequency.
8410844Sandreas.sandberg@arm.com    uint64_t freq() const { return _freq; }
8510844Sandreas.sandberg@arm.com    /// Sets the counter frequency.
8610844Sandreas.sandberg@arm.com    /// @param freq frequency in Hz.
8710844Sandreas.sandberg@arm.com    void setFreq(uint32_t freq);
8810844Sandreas.sandberg@arm.com
8910844Sandreas.sandberg@arm.com    /// Returns the counter period.
9010844Sandreas.sandberg@arm.com    Tick period() const { return _period; }
9110844Sandreas.sandberg@arm.com
9210844Sandreas.sandberg@arm.com    void setKernelControl(uint32_t val) { _regCntkctl = val; }
9310844Sandreas.sandberg@arm.com    uint32_t getKernelControl() { return _regCntkctl; }
9410844Sandreas.sandberg@arm.com
9510844Sandreas.sandberg@arm.com    void serialize(std::ostream &os) const;
9610844Sandreas.sandberg@arm.com    void unserialize(Checkpoint *cp, const std::string &section);
9710844Sandreas.sandberg@arm.com
9810844Sandreas.sandberg@arm.com  private:
9910844Sandreas.sandberg@arm.com    // Disable copying
10010844Sandreas.sandberg@arm.com    SystemCounter(const SystemCounter &c);
10110844Sandreas.sandberg@arm.com};
10210844Sandreas.sandberg@arm.com
10310844Sandreas.sandberg@arm.com/// Per-CPU architected timer.
10410844Sandreas.sandberg@arm.comclass ArchTimer
10510844Sandreas.sandberg@arm.com{
10610844Sandreas.sandberg@arm.com  public:
10710844Sandreas.sandberg@arm.com    class Interrupt
10810844Sandreas.sandberg@arm.com    {
10910844Sandreas.sandberg@arm.com      public:
11010844Sandreas.sandberg@arm.com        Interrupt(BaseGic &gic, unsigned irq)
11110844Sandreas.sandberg@arm.com            : _gic(gic), _ppi(false), _irq(irq), _cpu(0) {}
11210844Sandreas.sandberg@arm.com
11310844Sandreas.sandberg@arm.com        Interrupt(BaseGic &gic, unsigned irq, unsigned cpu)
11410844Sandreas.sandberg@arm.com            : _gic(gic), _ppi(true), _irq(irq), _cpu(cpu) {}
11510844Sandreas.sandberg@arm.com
11610844Sandreas.sandberg@arm.com        void send();
11710844Sandreas.sandberg@arm.com        void clear();
11810844Sandreas.sandberg@arm.com
11910844Sandreas.sandberg@arm.com      private:
12010844Sandreas.sandberg@arm.com        BaseGic &_gic;
12110844Sandreas.sandberg@arm.com        const bool _ppi;
12210844Sandreas.sandberg@arm.com        const unsigned _irq;
12310844Sandreas.sandberg@arm.com        const unsigned _cpu;
12410844Sandreas.sandberg@arm.com    };
12510844Sandreas.sandberg@arm.com
12610844Sandreas.sandberg@arm.com  protected:
12710844Sandreas.sandberg@arm.com    /// Control register.
12810844Sandreas.sandberg@arm.com    BitUnion32(ArchTimerCtrl)
12910844Sandreas.sandberg@arm.com    Bitfield<0> enable;
13010844Sandreas.sandberg@arm.com    Bitfield<1> imask;
13110844Sandreas.sandberg@arm.com    Bitfield<2> istatus;
13210844Sandreas.sandberg@arm.com    EndBitUnion(ArchTimerCtrl)
13310844Sandreas.sandberg@arm.com
13410844Sandreas.sandberg@arm.com    /// Name of this timer.
13510844Sandreas.sandberg@arm.com    const std::string _name;
13610844Sandreas.sandberg@arm.com
13710844Sandreas.sandberg@arm.com    /// Pointer to parent class.
13810844Sandreas.sandberg@arm.com    SimObject &_parent;
13910844Sandreas.sandberg@arm.com
14010844Sandreas.sandberg@arm.com    SystemCounter &_systemCounter;
14110844Sandreas.sandberg@arm.com
14210844Sandreas.sandberg@arm.com    Interrupt _interrupt;
14310844Sandreas.sandberg@arm.com
14410844Sandreas.sandberg@arm.com    /// Value of the control register ({CNTP/CNTHP/CNTV}_CTL).
14510844Sandreas.sandberg@arm.com    ArchTimerCtrl _control;
14610844Sandreas.sandberg@arm.com    /// Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL).
14710844Sandreas.sandberg@arm.com    uint64_t _counterLimit;
14810844Sandreas.sandberg@arm.com
14910844Sandreas.sandberg@arm.com    /**
15010844Sandreas.sandberg@arm.com     * Timer settings or the offset has changed, re-evaluate
15110844Sandreas.sandberg@arm.com     * trigger condition and raise interrupt if necessary.
15210844Sandreas.sandberg@arm.com     */
15310844Sandreas.sandberg@arm.com    void updateCounter();
15410844Sandreas.sandberg@arm.com
15510844Sandreas.sandberg@arm.com    /// Called when the upcounter reaches the programmed value.
15610844Sandreas.sandberg@arm.com    void counterLimitReached();
15710844Sandreas.sandberg@arm.com    EventWrapper<ArchTimer, &ArchTimer::counterLimitReached>
15810844Sandreas.sandberg@arm.com    _counterLimitReachedEvent;
15910844Sandreas.sandberg@arm.com
16010844Sandreas.sandberg@arm.com  public:
16110844Sandreas.sandberg@arm.com    ArchTimer(const std::string &name,
16210844Sandreas.sandberg@arm.com              SimObject &parent,
16310844Sandreas.sandberg@arm.com              SystemCounter &sysctr,
16410844Sandreas.sandberg@arm.com              const Interrupt &interrupt);
16510844Sandreas.sandberg@arm.com
16610844Sandreas.sandberg@arm.com    /// Returns the timer name.
16710844Sandreas.sandberg@arm.com    std::string name() const { return _name; }
16810844Sandreas.sandberg@arm.com
16910844Sandreas.sandberg@arm.com    /// Returns the CompareValue view of the timer.
17010844Sandreas.sandberg@arm.com    uint64_t compareValue() const { return _counterLimit; }
17110844Sandreas.sandberg@arm.com    /// Sets the CompareValue view of the timer.
17210844Sandreas.sandberg@arm.com    void setCompareValue(uint64_t val);
17310844Sandreas.sandberg@arm.com
17410844Sandreas.sandberg@arm.com    /// Returns the TimerValue view of the timer.
17510844Sandreas.sandberg@arm.com    uint32_t timerValue() const { return _counterLimit - value(); }
17610844Sandreas.sandberg@arm.com    /// Sets the TimerValue view of the timer.
17710844Sandreas.sandberg@arm.com    void setTimerValue(uint32_t val);
17810844Sandreas.sandberg@arm.com
17910844Sandreas.sandberg@arm.com    /// Sets the control register.
18010844Sandreas.sandberg@arm.com    uint32_t control() const { return _control; }
18110844Sandreas.sandberg@arm.com    void setControl(uint32_t val);
18210844Sandreas.sandberg@arm.com
18310844Sandreas.sandberg@arm.com    /// Returns the value of the counter which this timer relies on.
18410844Sandreas.sandberg@arm.com    uint64_t value() const;
18510844Sandreas.sandberg@arm.com
18610844Sandreas.sandberg@arm.com    void serialize(std::ostream &os) const;
18710844Sandreas.sandberg@arm.com    void unserialize(Checkpoint *cp, const std::string &section);
18810844Sandreas.sandberg@arm.com
18910844Sandreas.sandberg@arm.com  private:
19010844Sandreas.sandberg@arm.com    // Disable copying
19110844Sandreas.sandberg@arm.com    ArchTimer(const ArchTimer &t);
19210844Sandreas.sandberg@arm.com};
19310844Sandreas.sandberg@arm.com
19410037SARM gem5 Developersclass GenericTimer : public SimObject
19510037SARM gem5 Developers{
19610037SARM gem5 Developers  public:
19710844Sandreas.sandberg@arm.com    GenericTimer(GenericTimerParams *p);
19810037SARM gem5 Developers
19910844Sandreas.sandberg@arm.com    void serialize(std::ostream &os) M5_ATTR_OVERRIDE;
20010844Sandreas.sandberg@arm.com    void unserialize(Checkpoint *cp, const std::string &sec) M5_ATTR_OVERRIDE;
20110037SARM gem5 Developers
20210844Sandreas.sandberg@arm.com  public:
20310844Sandreas.sandberg@arm.com    void setMiscReg(int misc_reg, unsigned cpu, ArmISA::MiscReg val);
20410844Sandreas.sandberg@arm.com    ArmISA::MiscReg readMiscReg(int misc_reg, unsigned cpu);
20510037SARM gem5 Developers
20610844Sandreas.sandberg@arm.com  protected:
20710844Sandreas.sandberg@arm.com    struct CoreTimers {
20810844Sandreas.sandberg@arm.com        CoreTimers(GenericTimer &parent, unsigned cpu,
20910844Sandreas.sandberg@arm.com                   unsigned _irqPhys)
21010844Sandreas.sandberg@arm.com            : irqPhys(*parent.gic, _irqPhys, cpu),
21110844Sandreas.sandberg@arm.com              // This should really be phys_timerN, but we are stuck with
21210844Sandreas.sandberg@arm.com              // arch_timer for backwards compatibility.
21310844Sandreas.sandberg@arm.com              phys(csprintf("%s.arch_timer%d", parent.name(), cpu),
21410844Sandreas.sandberg@arm.com                   parent, parent.systemCounter,
21510844Sandreas.sandberg@arm.com                   irqPhys)
21610844Sandreas.sandberg@arm.com        {}
21710037SARM gem5 Developers
21810844Sandreas.sandberg@arm.com        ArchTimer::Interrupt irqPhys;
21910844Sandreas.sandberg@arm.com        ArchTimer phys;
22010037SARM gem5 Developers
22110844Sandreas.sandberg@arm.com      private:
22210844Sandreas.sandberg@arm.com        // Disable copying
22310844Sandreas.sandberg@arm.com        CoreTimers(const CoreTimers &c);
22410037SARM gem5 Developers    };
22510037SARM gem5 Developers
22610844Sandreas.sandberg@arm.com    CoreTimers &getTimers(int cpu_id);
22710844Sandreas.sandberg@arm.com    void createTimers(unsigned cpus);
22810037SARM gem5 Developers
22910844Sandreas.sandberg@arm.com    /// System counter.
23010844Sandreas.sandberg@arm.com    SystemCounter systemCounter;
23110037SARM gem5 Developers
23210844Sandreas.sandberg@arm.com    /// Per-CPU physical architected timers.
23310844Sandreas.sandberg@arm.com    std::vector<std::unique_ptr<CoreTimers>> timers;
23410037SARM gem5 Developers
23510844Sandreas.sandberg@arm.com  protected: // Configuration
23610844Sandreas.sandberg@arm.com    /// Pointer to the GIC, needed to trigger timer interrupts.
23710844Sandreas.sandberg@arm.com    BaseGic *const gic;
23810037SARM gem5 Developers
23910844Sandreas.sandberg@arm.com    /// Physical timer interrupt
24010844Sandreas.sandberg@arm.com    const unsigned irqPhys;
24110844Sandreas.sandberg@arm.com};
24210037SARM gem5 Developers
24310844Sandreas.sandberg@arm.comclass GenericTimerISA : public ArmISA::BaseISADevice
24410844Sandreas.sandberg@arm.com{
24510844Sandreas.sandberg@arm.com  public:
24610844Sandreas.sandberg@arm.com    GenericTimerISA(GenericTimer &_parent, unsigned _cpu)
24710844Sandreas.sandberg@arm.com        : parent(_parent), cpu(_cpu) {}
24810037SARM gem5 Developers
24910844Sandreas.sandberg@arm.com    void setMiscReg(int misc_reg, ArmISA::MiscReg val) M5_ATTR_OVERRIDE {
25010844Sandreas.sandberg@arm.com        parent.setMiscReg(misc_reg, cpu, val);
25110844Sandreas.sandberg@arm.com    }
25210844Sandreas.sandberg@arm.com    ArmISA::MiscReg readMiscReg(int misc_reg) M5_ATTR_OVERRIDE {
25310844Sandreas.sandberg@arm.com        return parent.readMiscReg(misc_reg, cpu);
25410844Sandreas.sandberg@arm.com    }
25510037SARM gem5 Developers
25610037SARM gem5 Developers  protected:
25710844Sandreas.sandberg@arm.com    GenericTimer &parent;
25810844Sandreas.sandberg@arm.com    unsigned cpu;
25910037SARM gem5 Developers};
26010037SARM gem5 Developers
26110037SARM gem5 Developers#endif // __DEV_ARM_GENERIC_TIMER_HH__
262