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