46#include "debug/Checkpoint.hh"
47#include "debug/Timer.hh"
67 std::stringstream oss;
68 oss <<
name() <<
".timer" <<
i;
71 new Timer(oss.str(),
this,
73 p.int_watchdog->get(tc)));
83 : _name(timer_name), parent(_parent), intTimer(int_timer),
84 intWatchdog(int_watchdog), timerControl(0x0), watchdogControl(0x0),
85 rawIntTimer(false), rawIntWatchdog(false),
86 rawResetWatchdog(false), watchdogDisableReg(0x0),
87 pendingIntTimer(false), pendingIntWatchdog(false),
88 timerLoadValue(0x0), watchdogLoadValue(0x0),
90 watchdogZeroEvent([
this]{ watchdogAtZero(); },
name())
101 DPRINTF(
Timer,
"Reading from CpuLocalTimer at offset: %#x\n", daddr);
108 panic(
"Tried to read CpuLocalTimer at offset %#x that doesn't exist\n", daddr);
117 DPRINTF(
Timer,
"Reading from CpuLocalTimer at offset: %#x\n", daddr);
122 pkt->
setLE<uint32_t>(timerLoadValue);
124 case TimerCounterReg:
125 DPRINTF(
Timer,
"Event schedule for timer %d, clock=%d, prescale=%d\n",
126 timerZeroEvent.when(), parent->clockPeriod(),
128 time = timerZeroEvent.when() -
curTick();
129 time = (time / parent->clockPeriod()) >> (4 * timerControl.prescalar);
131 pkt->
setLE<uint32_t>(time);
133 case TimerControlReg:
134 pkt->
setLE<uint32_t>(timerControl);
136 case TimerIntStatusReg:
137 pkt->
setLE<uint32_t>(rawIntTimer);
139 case WatchdogLoadReg:
140 pkt->
setLE<uint32_t>(watchdogLoadValue);
142 case WatchdogCounterReg:
144 "Event schedule for watchdog %d, clock=%d, prescale=%d\n",
145 watchdogZeroEvent.when(), parent->clockPeriod(),
147 time = watchdogZeroEvent.when() -
curTick();
148 time = (time / parent->clockPeriod()) >>
149 (4 * watchdogControl.prescalar);
151 pkt->
setLE<uint32_t>(time);
153 case WatchdogControlReg:
154 pkt->
setLE<uint32_t>(watchdogControl);
156 case WatchdogIntStatusReg:
157 pkt->
setLE<uint32_t>(rawIntWatchdog);
159 case WatchdogResetStatusReg:
160 pkt->
setLE<uint32_t>(rawResetWatchdog);
162 case WatchdogDisableReg:
163 panic(
"Tried to read from WatchdogDisableRegister\n");
166 panic(
"Tried to read CpuLocalTimer at offset %#x\n", daddr);
178 DPRINTF(
Timer,
"Writing to CpuLocalTimer at offset: %#x\n", daddr);
185 panic(
"Tried to write CpuLocalTimer at offset %#x that doesn't exist\n", daddr);
193 DPRINTF(
Timer,
"Writing to CpuLocalTimer at offset: %#x\n", daddr);
202 timerLoadValue = pkt->
getLE<uint32_t>();
203 restartTimerCounter(timerLoadValue);
205 case TimerCounterReg:
207 restartTimerCounter(pkt->
getLE<uint32_t>());
209 case TimerControlReg:
210 old_enable = timerControl.enable;
211 timerControl = pkt->
getLE<uint32_t>();
212 if ((old_enable == 0) && timerControl.enable)
213 restartTimerCounter(timerLoadValue);
215 case TimerIntStatusReg:
217 if (pendingIntTimer) {
218 pendingIntTimer =
false;
222 case WatchdogLoadReg:
223 watchdogLoadValue = pkt->
getLE<uint32_t>();
224 restartWatchdogCounter(watchdogLoadValue);
226 case WatchdogCounterReg:
228 if (!watchdogControl.watchdogMode) {
229 restartWatchdogCounter(pkt->
getLE<uint32_t>());
232 case WatchdogControlReg:
233 old_enable = watchdogControl.enable;
234 old_wd_mode = watchdogControl.watchdogMode;
235 watchdogControl = pkt->
getLE<uint32_t>();
236 if ((old_enable == 0) && watchdogControl.enable)
237 restartWatchdogCounter(watchdogLoadValue);
239 if ((old_wd_mode == 1) && watchdogControl.watchdogMode == 0)
240 watchdogControl.watchdogMode = 1;
242 case WatchdogIntStatusReg:
243 rawIntWatchdog =
false;
244 if (pendingIntWatchdog) {
245 pendingIntWatchdog =
false;
249 case WatchdogResetStatusReg:
250 rawResetWatchdog =
false;
253 case WatchdogDisableReg:
254 old_val = watchdogDisableReg;
255 watchdogDisableReg = pkt->
getLE<uint32_t>();
257 if (old_val == 0x12345678 && watchdogDisableReg == 0x87654321)
258 watchdogControl.watchdogMode = 0;
261 panic(
"Tried to write CpuLocalTimer timer at offset %#x\n", daddr);
271 if (!timerControl.enable)
274 Tick time = parent->clockPeriod() << (4 * timerControl.prescalar);
277 if (timerZeroEvent.scheduled()) {
278 DPRINTF(
Timer,
"-- Event was already schedule, de-scheduling\n");
279 parent->deschedule(timerZeroEvent);
281 parent->schedule(timerZeroEvent,
curTick() + time);
289 if (!watchdogControl.enable)
292 Tick time = parent->clockPeriod() << (4 * watchdogControl.prescalar);
295 if (watchdogZeroEvent.scheduled()) {
296 DPRINTF(
Timer,
"-- Event was already schedule, de-scheduling\n");
297 parent->deschedule(watchdogZeroEvent);
299 parent->schedule(watchdogZeroEvent,
curTick() + time);
307 if (!timerControl.enable)
313 bool old_pending = pendingIntTimer;
314 if (timerControl.intEnable)
315 pendingIntTimer =
true;
316 if (pendingIntTimer && !old_pending) {
321 if (!timerControl.autoReload)
324 restartTimerCounter(timerLoadValue);
330 if (!watchdogControl.enable)
335 rawIntWatchdog =
true;
336 bool old_pending = pendingIntWatchdog;
339 if (watchdogControl.intEnable && !watchdogControl.watchdogMode)
340 pendingIntWatchdog =
true;
341 else if (watchdogControl.watchdogMode) {
342 rawResetWatchdog =
true;
343 fatal(
"gem5 ARM Model does not support true watchdog operation!\n");
347 if (pendingIntWatchdog && !old_pending) {
349 intWatchdog->raise();
352 if (watchdogControl.watchdogMode)
354 else if (watchdogControl.autoReload)
355 restartWatchdogCounter(watchdogLoadValue);
361 DPRINTF(Checkpoint,
"Serializing Arm CpuLocalTimer\n");
363 uint32_t timer_control_serial = timerControl;
364 uint32_t watchdog_control_serial = watchdogControl;
377 bool timer_is_in_event = timerZeroEvent.scheduled();
379 bool watchdog_is_in_event = watchdogZeroEvent.scheduled();
382 Tick timer_event_time;
383 if (timer_is_in_event){
384 timer_event_time = timerZeroEvent.when();
387 Tick watchdog_event_time;
388 if (watchdog_is_in_event){
389 watchdog_event_time = watchdogZeroEvent.when();
397 DPRINTF(Checkpoint,
"Unserializing Arm CpuLocalTimer\n");
399 uint32_t timer_control_serial;
401 timerControl = timer_control_serial;
402 uint32_t watchdog_control_serial;
404 watchdogControl = watchdog_control_serial;
415 bool timer_is_in_event;
417 bool watchdog_is_in_event;
420 Tick timer_event_time;
421 if (timer_is_in_event){
423 parent->schedule(timerZeroEvent, timer_event_time);
425 Tick watchdog_event_time;
426 if (watchdog_is_in_event) {
428 parent->schedule(watchdogZeroEvent, watchdog_event_time);
Base class for ARM GIC implementations.
Generic representation of an Arm interrupt pin.
Addr pioAddr
Address that the device listens to.
Tick pioDelay
Delay that the device experinces on an access.
Addr pioSize
Size that the device's address range.
Bitfield< 15, 8 > prescalar
void serialize(CheckpointOut &cp) const override
Serialize an object.
void restartTimerCounter(uint32_t val)
Restart the counter ticking at val.
Timer(const std::string &name, CpuLocalTimer *_parent, ArmInterruptPin *int_timer, ArmInterruptPin *int_watchdog)
void write(PacketPtr pkt, Addr daddr)
Handle write for a single timer.
void timerAtZero()
Called when the counter reaches 0.
void read(PacketPtr pkt, Addr daddr)
Handle read for a single timer.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void restartWatchdogCounter(uint32_t val)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::vector< std::unique_ptr< Timer > > localTimer
Timers that do the actual work.
Tick read(PacketPtr pkt) override
Handle a read to the device.
Tick write(PacketPtr pkt) override
Handle a write to the device.
CpuLocalTimer(const Params &p)
The constructor for RealView just registers itself with the MMU.
void init() override
Inits the local timers.
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
void makeAtomicResponse()
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
ThreadContext is the external interface to all thread state for anything outside of the CPU.
#define panic(...)
This implements a cprintf based panic() function.
#define fatal(...)
This implements a cprintf based fatal() function.
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
const Params & params() const
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Tick curTick()
The universal simulation clock.
std::ostream CheckpointOut
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
uint64_t Tick
Tick count type.
int ContextID
Globally unique thread context ID.
std::string csprintf(const char *format, const Args &...args)
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
#define SERIALIZE_SCALAR(scalar)
This implements the cpu local timer from the Cortex-A9 MPCore Technical Reference Manual rev r2p2 (AR...
const std::string & name()