generic_timer.hh revision 12086:069c529a76fd
12497SN/A/*
212241Snikos.nikoleris@arm.com * Copyright (c) 2013, 2015 ARM Limited
38711SN/A * All rights reserved.
48711SN/A *
58711SN/A * The license below extends only to copyright in the software and shall
68711SN/A * not be construed as granting a license to any other intellectual
78711SN/A * property including but not limited to intellectual property relating
88711SN/A * to a hardware implementation of the functionality of the software
98711SN/A * licensed hereunder.  You may use the software subject to the license
108711SN/A * terms below provided that you ensure that this notice is replicated
118711SN/A * unmodified and in its entirety in all distributions of the software,
128711SN/A * modified or unmodified, in source code or in binary form.
138711SN/A *
142497SN/A * Redistribution and use in source and binary forms, with or without
152497SN/A * modification, are permitted provided that the following conditions are
162497SN/A * met: redistributions of source code must retain the above copyright
172497SN/A * notice, this list of conditions and the following disclaimer;
182497SN/A * redistributions in binary form must reproduce the above copyright
192497SN/A * notice, this list of conditions and the following disclaimer in the
202497SN/A * documentation and/or other materials provided with the distribution;
212497SN/A * neither the name of the copyright holders nor the names of its
222497SN/A * contributors may be used to endorse or promote products derived from
232497SN/A * this software without specific prior written permission.
242497SN/A *
252497SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
262497SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
272497SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282497SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
292497SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302497SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312497SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322497SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332497SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342497SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
352497SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362497SN/A *
372497SN/A * Authors: Giacomo Gabrielli
382497SN/A *          Andreas Sandberg
392665SN/A */
402665SN/A
418715SN/A#ifndef __DEV_ARM_GENERIC_TIMER_HH__
428922SN/A#define __DEV_ARM_GENERIC_TIMER_HH__
4312351Snikos.nikoleris@arm.com
442497SN/A#include "arch/arm/isa_device.hh"
452497SN/A#include "base/bitunion.hh"
462497SN/A#include "dev/arm/base_gic.hh"
472982SN/A#include "sim/core.hh"
4810405Sandreas.hansson@arm.com#include "sim/sim_object.hh"
492497SN/A
502497SN/A/// @file
5111793Sbrandon.potter@amd.com/// This module implements the global system counter and the local per-CPU
5211793Sbrandon.potter@amd.com/// architected timers as specified by the ARM Generic Timer extension (ARM
5312334Sgabeblack@google.com/// ARM, Issue C, Chapter 17).
542548SN/A
5510405Sandreas.hansson@arm.comclass Checkpoint;
5610405Sandreas.hansson@arm.comclass GenericTimerParams;
579524SN/Aclass GenericTimerMemParams;
582497SN/A
5910405Sandreas.hansson@arm.com/// Global system counter.  It is shared by the architected timers.
6010719SMarco.Balboni@ARM.com/// @todo: implement memory-mapped controls
6111334Sandreas.hansson@arm.comclass SystemCounter : public Serializable
6212341Snikos.nikoleris@arm.com{
6312341Snikos.nikoleris@arm.com  protected:
647523SN/A    /// Counter frequency (as specified by CNTFRQ).
658851SN/A    uint64_t _freq;
668948SN/A    /// Cached copy of the counter period (inverse of the frequency).
678948SN/A    Tick _period;
688851SN/A    /// Tick when the counter was reset.
699095SN/A    Tick _resetTick;
7010405Sandreas.hansson@arm.com
718922SN/A    uint32_t _regCntkctl;
729715SN/A
739715SN/A  public:
7410713Sandreas.hansson@arm.com    SystemCounter();
7510713Sandreas.hansson@arm.com
768851SN/A    /// Returns the current value of the physical counter.
778851SN/A    uint64_t value() const
788948SN/A    {
798948SN/A        if (_freq == 0)
808915SN/A            return 0;  // Counter is still off.
819031SN/A        return (curTick() - _resetTick) / _period;
829095SN/A    }
8310405Sandreas.hansson@arm.com
849036SN/A    /// Returns the counter frequency.
858922SN/A    uint64_t freq() const { return _freq; }
869715SN/A    /// Sets the counter frequency.
879715SN/A    /// @param freq frequency in Hz.
8810713Sandreas.hansson@arm.com    void setFreq(uint32_t freq);
8910713Sandreas.hansson@arm.com
9010713Sandreas.hansson@arm.com    /// Returns the counter period.
918915SN/A    Tick period() const { return _period; }
928915SN/A
938948SN/A    void setKernelControl(uint32_t val) { _regCntkctl = val; }
948851SN/A    uint32_t getKernelControl() { return _regCntkctl; }
959095SN/A
9610888Sandreas.hansson@arm.com    void serialize(CheckpointOut &cp) const override;
978922SN/A    void unserialize(CheckpointIn &cp) override;
989715SN/A
999715SN/A  private:
1009716SN/A    // Disable copying
1018851SN/A    SystemCounter(const SystemCounter &c);
1028851SN/A};
1037523SN/A
1047523SN/A/// Per-CPU architected timer.
1057523SN/Aclass ArchTimer : public Serializable
10610405Sandreas.hansson@arm.com{
1079715SN/A  public:
10810405Sandreas.hansson@arm.com    class Interrupt
10910405Sandreas.hansson@arm.com    {
11010405Sandreas.hansson@arm.com      public:
11110405Sandreas.hansson@arm.com        Interrupt(BaseGic &gic, unsigned irq)
11210405Sandreas.hansson@arm.com            : _gic(gic), _ppi(false), _irq(irq), _cpu(0) {}
11310405Sandreas.hansson@arm.com
11410405Sandreas.hansson@arm.com        Interrupt(BaseGic &gic, unsigned irq, unsigned cpu)
11510405Sandreas.hansson@arm.com            : _gic(gic), _ppi(true), _irq(irq), _cpu(cpu) {}
1169715SN/A
1179715SN/A        void send();
1182568SN/A        void clear();
11910405Sandreas.hansson@arm.com
1202568SN/A      private:
12110405Sandreas.hansson@arm.com        BaseGic &_gic;
1229278SN/A        const bool _ppi;
1238948SN/A        const unsigned _irq;
1248948SN/A        const unsigned _cpu;
12510405Sandreas.hansson@arm.com    };
1269088SN/A
12710405Sandreas.hansson@arm.com  protected:
12810405Sandreas.hansson@arm.com    /// Control register.
12910405Sandreas.hansson@arm.com    BitUnion32(ArchTimerCtrl)
13010405Sandreas.hansson@arm.com    Bitfield<0> enable;
1318711SN/A    Bitfield<1> imask;
1328711SN/A    Bitfield<2> istatus;
1332568SN/A    EndBitUnion(ArchTimerCtrl)
1349036SN/A
13510405Sandreas.hansson@arm.com    /// Name of this timer.
13611133Sandreas.hansson@arm.com    const std::string _name;
13711133Sandreas.hansson@arm.com
13811133Sandreas.hansson@arm.com    /// Pointer to parent class.
13911133Sandreas.hansson@arm.com    SimObject &_parent;
14011133Sandreas.hansson@arm.com
1413244SN/A    SystemCounter &_systemCounter;
1423244SN/A
1438948SN/A    Interrupt _interrupt;
14410405Sandreas.hansson@arm.com
1453244SN/A    /// Value of the control register ({CNTP/CNTHP/CNTV}_CTL).
1468975SN/A    ArchTimerCtrl _control;
1479032SN/A    /// Programmed limit value for the upcounter ({CNTP/CNTHP/CNTV}_CVAL).
1483244SN/A    uint64_t _counterLimit;
1499091SN/A    /// Offset relative to the physical timer (CNTVOFF)
1509091SN/A    uint64_t _offset;
15111284Sandreas.hansson@arm.com
15210656Sandreas.hansson@arm.com    /**
15311284Sandreas.hansson@arm.com     * Timer settings or the offset has changed, re-evaluate
15411284Sandreas.hansson@arm.com     * trigger condition and raise interrupt if necessary.
1559091SN/A     */
1569612SN/A    void updateCounter();
1579712SN/A
1589612SN/A    /// Called when the upcounter reaches the programmed value.
15910405Sandreas.hansson@arm.com    void counterLimitReached();
1609033SN/A    EventFunctionWrapper _counterLimitReachedEvent;
1619715SN/A
16211744Snikos.nikoleris@arm.com  public:
16311744Snikos.nikoleris@arm.com    ArchTimer(const std::string &name,
1643244SN/A              SimObject &parent,
1653244SN/A              SystemCounter &sysctr,
1663244SN/A              const Interrupt &interrupt);
16711744Snikos.nikoleris@arm.com
16811744Snikos.nikoleris@arm.com    /// Returns the timer name.
1695197SN/A    std::string name() const { return _name; }
1709712SN/A
1719712SN/A    /// Returns the CompareValue view of the timer.
1729712SN/A    uint64_t compareValue() const { return _counterLimit; }
1739712SN/A    /// Sets the CompareValue view of the timer.
1749712SN/A    void setCompareValue(uint64_t val);
17510719SMarco.Balboni@ARM.com
17610719SMarco.Balboni@ARM.com    /// Returns the TimerValue view of the timer.
17710719SMarco.Balboni@ARM.com    uint32_t timerValue() const { return _counterLimit - value(); }
17810719SMarco.Balboni@ARM.com    /// Sets the TimerValue view of the timer.
17910719SMarco.Balboni@ARM.com    void setTimerValue(uint32_t val);
18010719SMarco.Balboni@ARM.com
18110719SMarco.Balboni@ARM.com    /// Sets the control register.
18210719SMarco.Balboni@ARM.com    uint32_t control() const { return _control; }
18310719SMarco.Balboni@ARM.com    void setControl(uint32_t val);
18410719SMarco.Balboni@ARM.com
18510719SMarco.Balboni@ARM.com    uint64_t offset() const { return _offset; }
1864912SN/A    void setOffset(uint64_t val);
18712346Snikos.nikoleris@arm.com
18812346Snikos.nikoleris@arm.com    /// Returns the value of the counter which this timer relies on.
18912346Snikos.nikoleris@arm.com    uint64_t value() const;
19012346Snikos.nikoleris@arm.com
19112346Snikos.nikoleris@arm.com    void serialize(CheckpointOut &cp) const override;
19212346Snikos.nikoleris@arm.com    void unserialize(CheckpointIn &cp) override;
19312345Snikos.nikoleris@arm.com
19412345Snikos.nikoleris@arm.com  private:
19512345Snikos.nikoleris@arm.com    // Disable copying
19611127Sandreas.hansson@arm.com    ArchTimer(const ArchTimer &t);
19711127Sandreas.hansson@arm.com};
19812351Snikos.nikoleris@arm.com
19912351Snikos.nikoleris@arm.comclass GenericTimer : public SimObject
20012351Snikos.nikoleris@arm.com{
20112351Snikos.nikoleris@arm.com  public:
20212351Snikos.nikoleris@arm.com    GenericTimer(GenericTimerParams *p);
20312351Snikos.nikoleris@arm.com
20412351Snikos.nikoleris@arm.com    void serialize(CheckpointOut &cp) const override;
20512351Snikos.nikoleris@arm.com    void unserialize(CheckpointIn &cp) override;
20612351Snikos.nikoleris@arm.com
20712351Snikos.nikoleris@arm.com  public:
20812351Snikos.nikoleris@arm.com    void setMiscReg(int misc_reg, unsigned cpu, ArmISA::MiscReg val);
20912351Snikos.nikoleris@arm.com    ArmISA::MiscReg readMiscReg(int misc_reg, unsigned cpu);
21012351Snikos.nikoleris@arm.com
21112351Snikos.nikoleris@arm.com  protected:
21212351Snikos.nikoleris@arm.com    struct CoreTimers {
21312351Snikos.nikoleris@arm.com        CoreTimers(GenericTimer &parent, unsigned cpu,
2148979SN/A                   unsigned _irqPhys, unsigned _irqVirt)
2158979SN/A            : irqPhys(*parent.gic, _irqPhys, cpu),
21610402SN/A              irqVirt(*parent.gic, _irqVirt, cpu),
21710402SN/A              // This should really be phys_timerN, but we are stuck with
21810402SN/A              // arch_timer for backwards compatibility.
21911126Sandreas.hansson@arm.com              phys(csprintf("%s.arch_timer%d", parent.name(), cpu),
22011126Sandreas.hansson@arm.com                   parent, parent.systemCounter,
22111126Sandreas.hansson@arm.com                   irqPhys),
22210719SMarco.Balboni@ARM.com              virt(csprintf("%s.virt_timer%d", parent.name(), cpu),
22311744Snikos.nikoleris@arm.com                   parent, parent.systemCounter,
22411744Snikos.nikoleris@arm.com                   irqVirt)
22511744Snikos.nikoleris@arm.com        {}
22611196Sali.jafri@arm.com
22711199Sandreas.hansson@arm.com        ArchTimer::Interrupt irqPhys;
22811196Sali.jafri@arm.com        ArchTimer::Interrupt irqVirt;
22911196Sali.jafri@arm.com
23011196Sali.jafri@arm.com        ArchTimer phys;
23111196Sali.jafri@arm.com        ArchTimer virt;
23211196Sali.jafri@arm.com
23311196Sali.jafri@arm.com      private:
23411196Sali.jafri@arm.com        // Disable copying
23511196Sali.jafri@arm.com        CoreTimers(const CoreTimers &c);
23611196Sali.jafri@arm.com    };
23711196Sali.jafri@arm.com
23810402SN/A    CoreTimers &getTimers(int cpu_id);
23910402SN/A    void createTimers(unsigned cpus);
24010402SN/A
24111127Sandreas.hansson@arm.com    /// System counter.
24211127Sandreas.hansson@arm.com    SystemCounter systemCounter;
24311127Sandreas.hansson@arm.com
24411127Sandreas.hansson@arm.com    /// Per-CPU physical architected timers.
2458979SN/A    std::vector<std::unique_ptr<CoreTimers>> timers;
2468948SN/A
24711334Sandreas.hansson@arm.com  protected: // Configuration
24811334Sandreas.hansson@arm.com    /// Pointer to the GIC, needed to trigger timer interrupts.
24910883Sali.jafri@arm.com    BaseGic *const gic;
25011284Sandreas.hansson@arm.com
25111284Sandreas.hansson@arm.com    /// Physical timer interrupt
25211284Sandreas.hansson@arm.com    const unsigned irqPhys;
25311284Sandreas.hansson@arm.com
25411334Sandreas.hansson@arm.com    /// Virtual timer interrupt
2558915SN/A    const unsigned irqVirt;
25611334Sandreas.hansson@arm.com};
25711334Sandreas.hansson@arm.com
25811334Sandreas.hansson@arm.comclass GenericTimerISA : public ArmISA::BaseISADevice
25911334Sandreas.hansson@arm.com{
26011544Snikos.nikoleris@arm.com  public:
26111544Snikos.nikoleris@arm.com    GenericTimerISA(GenericTimer &_parent, unsigned _cpu)
26211544Snikos.nikoleris@arm.com        : parent(_parent), cpu(_cpu) {}
26311334Sandreas.hansson@arm.com
26411744Snikos.nikoleris@arm.com    void setMiscReg(int misc_reg, ArmISA::MiscReg val) override {
26511744Snikos.nikoleris@arm.com        parent.setMiscReg(misc_reg, cpu, val);
26611334Sandreas.hansson@arm.com    }
26711334Sandreas.hansson@arm.com    ArmISA::MiscReg readMiscReg(int misc_reg) override {
26811334Sandreas.hansson@arm.com        return parent.readMiscReg(misc_reg, cpu);
26912346Snikos.nikoleris@arm.com    }
27011334Sandreas.hansson@arm.com
27111334Sandreas.hansson@arm.com  protected:
27211334Sandreas.hansson@arm.com    GenericTimer &parent;
27311334Sandreas.hansson@arm.com    unsigned cpu;
27411334Sandreas.hansson@arm.com};
27511334Sandreas.hansson@arm.com
27611334Sandreas.hansson@arm.comclass GenericTimerMem : public PioDevice
27711334Sandreas.hansson@arm.com{
27811334Sandreas.hansson@arm.com  public:
27912346Snikos.nikoleris@arm.com    GenericTimerMem(GenericTimerMemParams *p);
28012346Snikos.nikoleris@arm.com
28112346Snikos.nikoleris@arm.com    void serialize(CheckpointOut &cp) const override;
28212346Snikos.nikoleris@arm.com    void unserialize(CheckpointIn &cp) override;
28312346Snikos.nikoleris@arm.com
28412346Snikos.nikoleris@arm.com  public: // PioDevice
28512346Snikos.nikoleris@arm.com    AddrRangeList getAddrRanges() const override { return addrRanges; }
28611334Sandreas.hansson@arm.com    Tick read(PacketPtr pkt) override;
28711334Sandreas.hansson@arm.com    Tick write(PacketPtr pkt) override;
28811334Sandreas.hansson@arm.com
28911334Sandreas.hansson@arm.com  protected:
29011334Sandreas.hansson@arm.com    uint64_t ctrlRead(Addr addr, size_t size) const;
29111334Sandreas.hansson@arm.com    void ctrlWrite(Addr addr, size_t size, uint64_t value);
29211334Sandreas.hansson@arm.com
29311334Sandreas.hansson@arm.com    uint64_t timerRead(Addr addr, size_t size) const;
29411334Sandreas.hansson@arm.com    void timerWrite(Addr addr, size_t size, uint64_t value);
29511334Sandreas.hansson@arm.com
29611334Sandreas.hansson@arm.com  protected: // Registers
29711334Sandreas.hansson@arm.com    static const Addr CTRL_CNTFRQ          = 0x000;
2988948SN/A    static const Addr CTRL_CNTNSAR         = 0x004;
29912345Snikos.nikoleris@arm.com    static const Addr CTRL_CNTTIDR         = 0x008;
30010402SN/A    static const Addr CTRL_CNTACR_BASE     = 0x040;
30111605Snikos.nikoleris@arm.com    static const Addr CTRL_CNTVOFF_LO_BASE = 0x080;
30210402SN/A    static const Addr CTRL_CNTVOFF_HI_BASE = 0x084;
30310402SN/A
30410656Sandreas.hansson@arm.com    static const Addr TIMER_CNTPCT_LO    = 0x000;
30510656Sandreas.hansson@arm.com    static const Addr TIMER_CNTPCT_HI    = 0x004;
30611284Sandreas.hansson@arm.com    static const Addr TIMER_CNTVCT_LO    = 0x008;
30710656Sandreas.hansson@arm.com    static const Addr TIMER_CNTVCT_HI    = 0x00C;
30810656Sandreas.hansson@arm.com    static const Addr TIMER_CNTFRQ       = 0x010;
30910719SMarco.Balboni@ARM.com    static const Addr TIMER_CNTEL0ACR    = 0x014;
31010719SMarco.Balboni@ARM.com    static const Addr TIMER_CNTVOFF_LO   = 0x018;
31110656Sandreas.hansson@arm.com    static const Addr TIMER_CNTVOFF_HI   = 0x01C;
31211744Snikos.nikoleris@arm.com    static const Addr TIMER_CNTP_CVAL_LO = 0x020;
31311744Snikos.nikoleris@arm.com    static const Addr TIMER_CNTP_CVAL_HI = 0x024;
31410656Sandreas.hansson@arm.com    static const Addr TIMER_CNTP_TVAL    = 0x028;
31510656Sandreas.hansson@arm.com    static const Addr TIMER_CNTP_CTL     = 0x02C;
31610656Sandreas.hansson@arm.com    static const Addr TIMER_CNTV_CVAL_LO = 0x030;
31710719SMarco.Balboni@ARM.com    static const Addr TIMER_CNTV_CVAL_HI = 0x034;
3189091SN/A    static const Addr TIMER_CNTV_TVAL    = 0x038;
31910656Sandreas.hansson@arm.com    static const Addr TIMER_CNTV_CTL     = 0x03C;
32010656Sandreas.hansson@arm.com
32110656Sandreas.hansson@arm.com  protected: // Params
32210656Sandreas.hansson@arm.com    const AddrRange ctrlRange;
32310656Sandreas.hansson@arm.com    const AddrRange timerRange;
32410656Sandreas.hansson@arm.com    const AddrRangeList addrRanges;
32510656Sandreas.hansson@arm.com
32610656Sandreas.hansson@arm.com  protected:
32710656Sandreas.hansson@arm.com    /// System counter.
3288948SN/A    SystemCounter systemCounter;
32910656Sandreas.hansson@arm.com    ArchTimer physTimer;
33010656Sandreas.hansson@arm.com    ArchTimer virtTimer;
33110656Sandreas.hansson@arm.com};
33210656Sandreas.hansson@arm.com
3338948SN/A#endif // __DEV_ARM_GENERIC_TIMER_HH__
33410656Sandreas.hansson@arm.com