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 &section)
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 &section)
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