timer_sp804.cc revision 8245:a9d06c894afe
16019Shines@cs.fsu.edu/* 212509Schuan.zhu@arm.com * Copyright (c) 2010 ARM Limited 37189Sgblack@eecs.umich.edu * All rights reserved 47189Sgblack@eecs.umich.edu * 57189Sgblack@eecs.umich.edu * The license below extends only to copyright in the software and shall 67189Sgblack@eecs.umich.edu * not be construed as granting a license to any other intellectual 77189Sgblack@eecs.umich.edu * property including but not limited to intellectual property relating 87189Sgblack@eecs.umich.edu * to a hardware implementation of the functionality of the software 97189Sgblack@eecs.umich.edu * licensed hereunder. You may use the software subject to the license 107189Sgblack@eecs.umich.edu * terms below provided that you ensure that this notice is replicated 117189Sgblack@eecs.umich.edu * unmodified and in its entirety in all distributions of the software, 127189Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form. 137189Sgblack@eecs.umich.edu * 146019Shines@cs.fsu.edu * Redistribution and use in source and binary forms, with or without 156019Shines@cs.fsu.edu * modification, are permitted provided that the following conditions are 166019Shines@cs.fsu.edu * met: redistributions of source code must retain the above copyright 176019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer; 186019Shines@cs.fsu.edu * redistributions in binary form must reproduce the above copyright 196019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer in the 206019Shines@cs.fsu.edu * documentation and/or other materials provided with the distribution; 216019Shines@cs.fsu.edu * neither the name of the copyright holders nor the names of its 226019Shines@cs.fsu.edu * contributors may be used to endorse or promote products derived from 236019Shines@cs.fsu.edu * this software without specific prior written permission. 246019Shines@cs.fsu.edu * 256019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 266019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 276019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 286019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 296019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 306019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 316019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 326019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 336019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 346019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 356019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 366019Shines@cs.fsu.edu * 376019Shines@cs.fsu.edu * Authors: Ali Saidi 386019Shines@cs.fsu.edu */ 396019Shines@cs.fsu.edu 406019Shines@cs.fsu.edu#include "base/intmath.hh" 416735Sgblack@eecs.umich.edu#include "base/trace.hh" 426735Sgblack@eecs.umich.edu#include "debug/Checkpoint.hh" 4310037SARM gem5 Developers#include "debug/Timer.hh" 4410037SARM gem5 Developers#include "dev/arm/gic.hh" 456019Shines@cs.fsu.edu#include "dev/arm/timer_sp804.hh" 466019Shines@cs.fsu.edu#include "mem/packet.hh" 476019Shines@cs.fsu.edu#include "mem/packet_access.hh" 486019Shines@cs.fsu.edu 496019Shines@cs.fsu.eduusing namespace AmbaDev; 507362Sgblack@eecs.umich.edu 5110037SARM gem5 DevelopersSp804::Sp804(Params *p) 526735Sgblack@eecs.umich.edu : AmbaDevice(p), gic(p->gic), timer0(name() + ".timer0", this, p->int_num0, p->clock0), 5312334Sgabeblack@google.com timer1(name() + ".timer1", this, p->int_num1, p->clock1) 546019Shines@cs.fsu.edu{ 558782Sgblack@eecs.umich.edu pioSize = 0xfff; 566019Shines@cs.fsu.edu} 576019Shines@cs.fsu.edu 586019Shines@cs.fsu.eduSp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock) 596019Shines@cs.fsu.edu : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20), 606019Shines@cs.fsu.edu rawInt(false), pendingInt(false), loadValue(0xffffffff), zeroEvent(this) 6111294Sandreas.hansson@arm.com{ 626019Shines@cs.fsu.edu} 637362Sgblack@eecs.umich.edu 646019Shines@cs.fsu.edu 656019Shines@cs.fsu.eduTick 6610037SARM gem5 DevelopersSp804::read(PacketPtr pkt) 6710037SARM gem5 Developers{ 6810037SARM gem5 Developers assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 6910037SARM gem5 Developers assert(pkt->getSize() == 4); 7010037SARM gem5 Developers Addr daddr = pkt->getAddr() - pioAddr; 7110037SARM gem5 Developers pkt->allocate(); 7210037SARM gem5 Developers DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr); 7310037SARM gem5 Developers 7412569Sgiacomo.travaglini@arm.com if (daddr < Timer::Size) 7512569Sgiacomo.travaglini@arm.com timer0.read(pkt, daddr); 7612569Sgiacomo.travaglini@arm.com else if ((daddr - Timer::Size) < Timer::Size) 7712569Sgiacomo.travaglini@arm.com timer1.read(pkt, daddr - Timer::Size); 7812569Sgiacomo.travaglini@arm.com else if (!readId(pkt, ambaId, pioAddr)) 7912569Sgiacomo.travaglini@arm.com panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr); 8012569Sgiacomo.travaglini@arm.com pkt->makeAtomicResponse(); 8110037SARM gem5 Developers return pioDelay; 8212402Sgiacomo.travaglini@arm.com} 8312402Sgiacomo.travaglini@arm.com 846735Sgblack@eecs.umich.edu 8510037SARM gem5 Developersvoid 866735Sgblack@eecs.umich.eduSp804::Timer::read(PacketPtr pkt, Addr daddr) 876019Shines@cs.fsu.edu{ 8810037SARM gem5 Developers DPRINTF(Timer, "Reading from Timer at offset: %#x\n", daddr); 8910037SARM gem5 Developers 9010037SARM gem5 Developers switch(daddr) { 9110037SARM gem5 Developers case LoadReg: 9210037SARM gem5 Developers pkt->set<uint32_t>(loadValue); 937362Sgblack@eecs.umich.edu break; 9410037SARM gem5 Developers case CurrentReg: 9510037SARM gem5 Developers DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n", 9610037SARM gem5 Developers zeroEvent.when(), clock, control.timerPrescale); 9710037SARM gem5 Developers Tick time; 9810037SARM gem5 Developers time = zeroEvent.when() - curTick(); 9910037SARM gem5 Developers time = time / clock / power(16, control.timerPrescale); 10010037SARM gem5 Developers DPRINTF(Timer, "-- returning counter at %d\n", time); 10110037SARM gem5 Developers pkt->set<uint32_t>(time); 10210037SARM gem5 Developers break; 10310037SARM gem5 Developers case ControlReg: 10410037SARM gem5 Developers pkt->set<uint32_t>(control); 10510037SARM gem5 Developers break; 10610037SARM gem5 Developers case RawISR: 10710037SARM gem5 Developers pkt->set<uint32_t>(rawInt); 10810037SARM gem5 Developers break; 1097611SGene.Wu@arm.com case MaskedISR: 11010037SARM gem5 Developers pkt->set<uint32_t>(pendingInt); 11110037SARM gem5 Developers break; 11210037SARM gem5 Developers case BGLoad: 11310037SARM gem5 Developers pkt->set<uint32_t>(loadValue); 11410037SARM gem5 Developers break; 11510037SARM gem5 Developers default: 11610037SARM gem5 Developers panic("Tried to read SP804 timer at offset %#x\n", daddr); 11710037SARM gem5 Developers break; 11810037SARM gem5 Developers } 11910037SARM gem5 Developers} 12010037SARM gem5 Developers 12110037SARM gem5 DevelopersTick 12210037SARM gem5 DevelopersSp804::write(PacketPtr pkt) 12310037SARM gem5 Developers{ 12410037SARM gem5 Developers assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 12510037SARM gem5 Developers assert(pkt->getSize() == 4); 12610037SARM gem5 Developers Addr daddr = pkt->getAddr() - pioAddr; 12710037SARM gem5 Developers pkt->allocate(); 12810037SARM gem5 Developers DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr); 12910037SARM gem5 Developers 13010037SARM gem5 Developers if (daddr < Timer::Size) 13110037SARM gem5 Developers timer0.write(pkt, daddr); 13210037SARM gem5 Developers else if ((daddr - Timer::Size) < Timer::Size) 13310037SARM gem5 Developers timer1.write(pkt, daddr - Timer::Size); 13410037SARM gem5 Developers else if (!readId(pkt, ambaId, pioAddr)) 13510037SARM gem5 Developers panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr); 13610037SARM gem5 Developers pkt->makeAtomicResponse(); 13710037SARM gem5 Developers return pioDelay; 13810037SARM gem5 Developers} 13910037SARM gem5 Developers 14010037SARM gem5 Developersvoid 14110037SARM gem5 DevelopersSp804::Timer::write(PacketPtr pkt, Addr daddr) 14210037SARM gem5 Developers{ 14310037SARM gem5 Developers DPRINTF(Timer, "Writing to Timer at offset: %#x\n", daddr); 14410037SARM gem5 Developers switch (daddr) { 14510037SARM gem5 Developers case LoadReg: 14610037SARM gem5 Developers loadValue = pkt->get<uint32_t>(); 1477362Sgblack@eecs.umich.edu restartCounter(loadValue); 1487362Sgblack@eecs.umich.edu break; 1496735Sgblack@eecs.umich.edu case CurrentReg: 1506735Sgblack@eecs.umich.edu // Spec says this value can't be written, but linux writes it anyway 1516735Sgblack@eecs.umich.edu break; 15210037SARM gem5 Developers case ControlReg: 1536735Sgblack@eecs.umich.edu bool old_enable; 15410037SARM gem5 Developers old_enable = control.timerEnable; 15510037SARM gem5 Developers control = pkt->get<uint32_t>(); 15610037SARM gem5 Developers if ((old_enable == 0) && control.timerEnable) 15710037SARM gem5 Developers restartCounter(loadValue); 15810037SARM gem5 Developers break; 15910037SARM gem5 Developers case IntClear: 16010037SARM gem5 Developers rawInt = false; 1616735Sgblack@eecs.umich.edu if (pendingInt) { 16210037SARM gem5 Developers pendingInt = false; 1636735Sgblack@eecs.umich.edu DPRINTF(Timer, "Clearing interrupt\n"); 1646735Sgblack@eecs.umich.edu parent->gic->clearInt(intNum); 16510037SARM gem5 Developers } 16610037SARM gem5 Developers break; 16710037SARM gem5 Developers case BGLoad: 16810037SARM gem5 Developers loadValue = pkt->get<uint32_t>(); 16910037SARM gem5 Developers break; 17010037SARM gem5 Developers default: 17110037SARM gem5 Developers panic("Tried to write SP804 timer at offset %#x\n", daddr); 1726735Sgblack@eecs.umich.edu break; 1736735Sgblack@eecs.umich.edu } 17410037SARM gem5 Developers} 17510037SARM gem5 Developers 17610037SARM gem5 Developersvoid 17710037SARM gem5 DevelopersSp804::Timer::restartCounter(uint32_t val) 17810037SARM gem5 Developers{ 1796735Sgblack@eecs.umich.edu DPRINTF(Timer, "Resetting counter with value %#x\n", val); 18012517Srekai.gonzalezalberquilla@arm.com if (!control.timerEnable) 18112517Srekai.gonzalezalberquilla@arm.com return; 18212517Srekai.gonzalezalberquilla@arm.com 18312517Srekai.gonzalezalberquilla@arm.com Tick time = clock * power(16, control.timerPrescale); 18412517Srekai.gonzalezalberquilla@arm.com if (control.timerSize) 18512517Srekai.gonzalezalberquilla@arm.com time *= val; 18612517Srekai.gonzalezalberquilla@arm.com else 18712517Srekai.gonzalezalberquilla@arm.com time *= bits(val,15,0); 18812517Srekai.gonzalezalberquilla@arm.com 18912517Srekai.gonzalezalberquilla@arm.com if (zeroEvent.scheduled()) { 19012517Srekai.gonzalezalberquilla@arm.com DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n"); 19112517Srekai.gonzalezalberquilla@arm.com parent->deschedule(zeroEvent); 19212517Srekai.gonzalezalberquilla@arm.com } 19312517Srekai.gonzalezalberquilla@arm.com parent->schedule(zeroEvent, curTick() + time); 19412517Srekai.gonzalezalberquilla@arm.com DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time); 19512517Srekai.gonzalezalberquilla@arm.com} 1966735Sgblack@eecs.umich.edu 1976735Sgblack@eecs.umich.eduvoid 19810037SARM gem5 DevelopersSp804::Timer::counterAtZero() 19910537Sandreas.hansson@arm.com{ 20012569Sgiacomo.travaglini@arm.com if (!control.timerEnable) 20112569Sgiacomo.travaglini@arm.com return; 20210037SARM gem5 Developers 20310037SARM gem5 Developers DPRINTF(Timer, "Counter reached zero\n"); 20410037SARM gem5 Developers 20510037SARM gem5 Developers rawInt = true; 20610037SARM gem5 Developers bool old_pending = pendingInt; 20710037SARM gem5 Developers if (control.intEnable) 20810037SARM gem5 Developers pendingInt = true; 20910037SARM gem5 Developers if (pendingInt && ~old_pending) { 21010417Sandreas.hansson@arm.com DPRINTF(Timer, "-- Causing interrupt\n"); 21112176Sandreas.sandberg@arm.com parent->gic->sendInt(intNum); 21210417Sandreas.hansson@arm.com } 21310417Sandreas.hansson@arm.com 21412569Sgiacomo.travaglini@arm.com if (control.oneShot) 21510037SARM gem5 Developers return; 2166735Sgblack@eecs.umich.edu 21710037SARM gem5 Developers // Free-running 21812511Schuan.zhu@arm.com if (control.timerMode == 0) 2196735Sgblack@eecs.umich.edu restartCounter(0xffffffff); 22010037SARM gem5 Developers else 22110037SARM gem5 Developers restartCounter(loadValue); 22210037SARM gem5 Developers} 22310037SARM gem5 Developers 22410037SARM gem5 Developersvoid 22510037SARM gem5 DevelopersSp804::Timer::serialize(std::ostream &os) 22610037SARM gem5 Developers{ 22710037SARM gem5 Developers DPRINTF(Checkpoint, "Serializing Arm Sp804\n"); 22810037SARM gem5 Developers SERIALIZE_SCALAR(intNum); 22910037SARM gem5 Developers SERIALIZE_SCALAR(clock); 23010037SARM gem5 Developers 23112570Sgiacomo.travaglini@arm.com uint32_t control_serial = control; 23210037SARM gem5 Developers SERIALIZE_SCALAR(control_serial); 2336019Shines@cs.fsu.edu 2346019Shines@cs.fsu.edu SERIALIZE_SCALAR(rawInt); 2356735Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pendingInt); 2367362Sgblack@eecs.umich.edu SERIALIZE_SCALAR(loadValue); 2376019Shines@cs.fsu.edu 2386735Sgblack@eecs.umich.edu bool is_in_event = zeroEvent.scheduled(); 2396735Sgblack@eecs.umich.edu SERIALIZE_SCALAR(is_in_event); 2406735Sgblack@eecs.umich.edu 2416019Shines@cs.fsu.edu Tick event_time; 24210037SARM gem5 Developers if (is_in_event){ 24310037SARM gem5 Developers event_time = zeroEvent.when(); 24412176Sandreas.sandberg@arm.com SERIALIZE_SCALAR(event_time); 24512176Sandreas.sandberg@arm.com } 24612176Sandreas.sandberg@arm.com} 24710037SARM gem5 Developers 24812511Schuan.zhu@arm.comvoid 24910037SARM gem5 DevelopersSp804::Timer::unserialize(Checkpoint *cp, const std::string §ion) 25012176Sandreas.sandberg@arm.com{ 25112176Sandreas.sandberg@arm.com DPRINTF(Checkpoint, "Unserializing Arm Sp804\n"); 25212176Sandreas.sandberg@arm.com 25312176Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(intNum); 25412176Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(clock); 25512176Sandreas.sandberg@arm.com 25612176Sandreas.sandberg@arm.com uint32_t control_serial; 25712176Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(control_serial); 25812176Sandreas.sandberg@arm.com control = control_serial; 25912176Sandreas.sandberg@arm.com 26012176Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(rawInt); 26112176Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(pendingInt); 26212176Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(loadValue); 26312176Sandreas.sandberg@arm.com 26412176Sandreas.sandberg@arm.com bool is_in_event; 26512176Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(is_in_event); 26612176Sandreas.sandberg@arm.com 26712176Sandreas.sandberg@arm.com Tick event_time; 2686019Shines@cs.fsu.edu if (is_in_event){ 2696019Shines@cs.fsu.edu UNSERIALIZE_SCALAR(event_time); 2707400SAli.Saidi@ARM.com parent->schedule(zeroEvent, event_time); 2717400SAli.Saidi@ARM.com } 2727400SAli.Saidi@ARM.com} 27310417Sandreas.hansson@arm.com 27412176Sandreas.sandberg@arm.com 2757400SAli.Saidi@ARM.com 2767189Sgblack@eecs.umich.eduvoid 2777362Sgblack@eecs.umich.eduSp804::serialize(std::ostream &os) 2787189Sgblack@eecs.umich.edu{ 2797189Sgblack@eecs.umich.edu nameOut(os, csprintf("%s.timer0", name())); 2807189Sgblack@eecs.umich.edu timer0.serialize(os); 2817640Sgblack@eecs.umich.edu nameOut(os, csprintf("%s.timer1", name())); 28210037SARM gem5 Developers timer1.serialize(os); 28310205SAli.Saidi@ARM.com} 2847189Sgblack@eecs.umich.edu 2857189Sgblack@eecs.umich.eduvoid 2867189Sgblack@eecs.umich.eduSp804::unserialize(Checkpoint *cp, const std::string §ion) 2877189Sgblack@eecs.umich.edu{ 2887640Sgblack@eecs.umich.edu timer0.unserialize(cp, csprintf("%s.timer0", section)); 2897640Sgblack@eecs.umich.edu timer1.unserialize(cp, csprintf("%s.timer1", section)); 29010037SARM gem5 Developers} 29110205SAli.Saidi@ARM.com 29210205SAli.Saidi@ARM.comSp804 * 29310037SARM gem5 DevelopersSp804Params::create() 29410205SAli.Saidi@ARM.com{ 29510205SAli.Saidi@ARM.com return new Sp804(this); 29610037SARM gem5 Developers} 29710205SAli.Saidi@ARM.com