1/* |
2 * Copyright (c) 2010-2013,2018 ARM Limited |
3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated --- 24 unchanged lines hidden (view full) --- 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Ali Saidi 38 * Geoffrey Blake 39 */ 40 41#include "dev/arm/timer_cpulocal.hh" 42 |
43#include "arch/arm/system.hh" |
44#include "base/intmath.hh" 45#include "base/trace.hh" 46#include "debug/Checkpoint.hh" 47#include "debug/Timer.hh" 48#include "dev/arm/base_gic.hh" 49#include "mem/packet.hh" 50#include "mem/packet_access.hh" 51 52CpuLocalTimer::CpuLocalTimer(Params *p) |
53 : BasicPioDevice(p, 0x38) |
54{ |
55} 56 57void 58CpuLocalTimer::init() 59{ 60 auto p = params(); |
61 // Initialize the timer registers for each per cpu timer |
62 for (int i = 0; i < sys->numContexts(); i++) { 63 ThreadContext* tc = sys->getThreadContext(i); |
64 std::stringstream oss; 65 oss << name() << ".timer" << i; |
66 67 localTimer.emplace_back( 68 new Timer(oss.str(), this, 69 p->int_timer->get(tc), 70 p->int_watchdog->get(tc))); |
71 } |
72 73 BasicPioDevice::init(); |
74} 75 |
76CpuLocalTimer::Timer::Timer(const std::string &timer_name, 77 CpuLocalTimer* _parent, 78 ArmInterruptPin* int_timer, 79 ArmInterruptPin* int_watchdog) 80 : _name(timer_name), parent(_parent), intTimer(int_timer), 81 intWatchdog(int_watchdog), timerControl(0x0), watchdogControl(0x0), 82 rawIntTimer(false), rawIntWatchdog(false), 83 rawResetWatchdog(false), watchdogDisableReg(0x0), 84 pendingIntTimer(false), pendingIntWatchdog(false), |
85 timerLoadValue(0x0), watchdogLoadValue(0x0), 86 timerZeroEvent([this]{ timerAtZero(); }, name()), 87 watchdogZeroEvent([this]{ watchdogAtZero(); }, name()) 88{ 89} 90 91Tick 92CpuLocalTimer::read(PacketPtr pkt) 93{ 94 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 95 assert(pkt->getSize() == 4); 96 Addr daddr = pkt->getAddr() - pioAddr; 97 ContextID cpu_id = pkt->req->contextId(); 98 DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr); 99 assert(cpu_id >= 0); |
100 assert(cpu_id < localTimer.size()); |
101 102 if (daddr < Timer::Size) |
103 localTimer[cpu_id]->read(pkt, daddr); |
104 else 105 panic("Tried to read CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 106 pkt->makeAtomicResponse(); 107 return pioDelay; 108} 109 110 111void --- 58 unchanged lines hidden (view full) --- 170CpuLocalTimer::write(PacketPtr pkt) 171{ 172 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 173 assert(pkt->getSize() == 4); 174 Addr daddr = pkt->getAddr() - pioAddr; 175 ContextID cpu_id = pkt->req->contextId(); 176 DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr); 177 assert(cpu_id >= 0); |
178 assert(cpu_id < localTimer.size()); |
179 180 if (daddr < Timer::Size) |
181 localTimer[cpu_id]->write(pkt, daddr); |
182 else 183 panic("Tried to write CpuLocalTimer at offset %#x that doesn't exist\n", daddr); 184 pkt->makeAtomicResponse(); 185 return pioDelay; 186} 187 188void 189CpuLocalTimer::Timer::write(PacketPtr pkt, Addr daddr) --- 118 unchanged lines hidden (view full) --- 308 DPRINTF(Timer, "Timer Counter reached zero\n"); 309 310 rawIntTimer = true; 311 bool old_pending = pendingIntTimer; 312 if (timerControl.intEnable) 313 pendingIntTimer = true; 314 if (pendingIntTimer && !old_pending) { 315 DPRINTF(Timer, "-- Causing interrupt\n"); |
316 intTimer->raise(); |
317 } 318 319 if (!timerControl.autoReload) 320 return; 321 else 322 restartTimerCounter(timerLoadValue); 323} 324 --- 14 unchanged lines hidden (view full) --- 339 else if (watchdogControl.watchdogMode) { 340 rawResetWatchdog = true; 341 fatal("gem5 ARM Model does not support true watchdog operation!\n"); 342 //XXX: Should we ever support a true watchdog reset? 343 } 344 345 if (pendingIntWatchdog && !old_pending) { 346 DPRINTF(Timer, "-- Causing interrupt\n"); |
347 intWatchdog->raise(); |
348 } 349 350 if (watchdogControl.watchdogMode) 351 return; 352 else if (watchdogControl.autoReload) 353 restartWatchdogCounter(watchdogLoadValue); 354} 355 356void 357CpuLocalTimer::Timer::serialize(CheckpointOut &cp) const 358{ 359 DPRINTF(Checkpoint, "Serializing Arm CpuLocalTimer\n"); |
360 361 uint32_t timer_control_serial = timerControl; 362 uint32_t watchdog_control_serial = watchdogControl; 363 SERIALIZE_SCALAR(timer_control_serial); 364 SERIALIZE_SCALAR(watchdog_control_serial); 365 366 SERIALIZE_SCALAR(rawIntTimer); 367 SERIALIZE_SCALAR(rawIntWatchdog); --- 21 unchanged lines hidden (view full) --- 389 } 390} 391 392void 393CpuLocalTimer::Timer::unserialize(CheckpointIn &cp) 394{ 395 DPRINTF(Checkpoint, "Unserializing Arm CpuLocalTimer\n"); 396 |
397 uint32_t timer_control_serial; 398 UNSERIALIZE_SCALAR(timer_control_serial); 399 timerControl = timer_control_serial; 400 uint32_t watchdog_control_serial; 401 UNSERIALIZE_SCALAR(watchdog_control_serial); 402 watchdogControl = watchdog_control_serial; 403 404 UNSERIALIZE_SCALAR(rawIntTimer); --- 22 unchanged lines hidden (view full) --- 427 } 428} 429 430 431 432void 433CpuLocalTimer::serialize(CheckpointOut &cp) const 434{ |
435 for (int i = 0; i < sys->numContexts(); i++) 436 localTimer[i]->serializeSection(cp, csprintf("timer%d", i)); |
437} 438 439void 440CpuLocalTimer::unserialize(CheckpointIn &cp) 441{ |
442 for (int i = 0; i < sys->numContexts(); i++) 443 localTimer[i]->unserializeSection(cp, csprintf("timer%d", i)); |
444} 445 446CpuLocalTimer * 447CpuLocalTimerParams::create() 448{ 449 return new CpuLocalTimer(this); 450} |