gem5 v24.0.0.0
Loading...
Searching...
No Matches
timer_cpulocal.cc
Go to the documentation of this file.
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
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
39
40#include <cassert>
41
42#include "arch/arm/system.hh"
43#include "base/intmath.hh"
44#include "base/logging.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
52namespace gem5
53{
54
59
60void
62{
63 const auto &p = params();
64 // Initialize the timer registers for each per cpu timer
65 for (int i = 0; i < sys->threads.size(); i++) {
66 ThreadContext* tc = sys->threads[i];
67 std::stringstream oss;
68 oss << name() << ".timer" << i;
69
70 localTimer.emplace_back(
71 new Timer(oss.str(), this,
72 p.int_timer->get(tc),
73 p.int_watchdog->get(tc)));
74 }
75
77}
78
79CpuLocalTimer::Timer::Timer(const std::string &timer_name,
80 CpuLocalTimer* _parent,
81 ArmInterruptPin* int_timer,
82 ArmInterruptPin* int_watchdog)
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),
89 timerZeroEvent([this]{ timerAtZero(); }, name()),
90 watchdogZeroEvent([this]{ watchdogAtZero(); }, name())
91{
92}
93
94Tick
96{
97 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
98 assert(pkt->getSize() == 4);
99 Addr daddr = pkt->getAddr() - pioAddr;
100 ContextID cpu_id = pkt->req->contextId();
101 DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr);
102 assert(cpu_id >= 0);
103 assert(cpu_id < localTimer.size());
104
105 if (daddr < Timer::Size)
106 localTimer[cpu_id]->read(pkt, daddr);
107 else
108 panic("Tried to read CpuLocalTimer at offset %#x that doesn't exist\n", daddr);
109 pkt->makeAtomicResponse();
110 return pioDelay;
111}
112
113
114void
116{
117 DPRINTF(Timer, "Reading from CpuLocalTimer at offset: %#x\n", daddr);
118 Tick time;
119
120 switch(daddr) {
121 case TimerLoadReg:
122 pkt->setLE<uint32_t>(timerLoadValue);
123 break;
124 case TimerCounterReg:
125 DPRINTF(Timer, "Event schedule for timer %d, clock=%d, prescale=%d\n",
126 timerZeroEvent.when(), parent->clockPeriod(),
127 timerControl.prescalar);
128 time = timerZeroEvent.when() - curTick();
129 time = (time / parent->clockPeriod()) >> (4 * timerControl.prescalar);
130 DPRINTF(Timer, "-- returning counter at %d\n", time);
131 pkt->setLE<uint32_t>(time);
132 break;
133 case TimerControlReg:
134 pkt->setLE<uint32_t>(timerControl);
135 break;
136 case TimerIntStatusReg:
137 pkt->setLE<uint32_t>(rawIntTimer);
138 break;
139 case WatchdogLoadReg:
140 pkt->setLE<uint32_t>(watchdogLoadValue);
141 break;
142 case WatchdogCounterReg:
144 "Event schedule for watchdog %d, clock=%d, prescale=%d\n",
145 watchdogZeroEvent.when(), parent->clockPeriod(),
146 watchdogControl.prescalar);
147 time = watchdogZeroEvent.when() - curTick();
148 time = (time / parent->clockPeriod()) >>
149 (4 * watchdogControl.prescalar);
150 DPRINTF(Timer, "-- returning counter at %d\n", time);
151 pkt->setLE<uint32_t>(time);
152 break;
153 case WatchdogControlReg:
154 pkt->setLE<uint32_t>(watchdogControl);
155 break;
156 case WatchdogIntStatusReg:
157 pkt->setLE<uint32_t>(rawIntWatchdog);
158 break;
159 case WatchdogResetStatusReg:
160 pkt->setLE<uint32_t>(rawResetWatchdog);
161 break;
162 case WatchdogDisableReg:
163 panic("Tried to read from WatchdogDisableRegister\n");
164 break;
165 default:
166 panic("Tried to read CpuLocalTimer at offset %#x\n", daddr);
167 break;
168 }
169}
170
171Tick
173{
174 assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
175 assert(pkt->getSize() == 4);
176 Addr daddr = pkt->getAddr() - pioAddr;
177 ContextID cpu_id = pkt->req->contextId();
178 DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr);
179 assert(cpu_id >= 0);
180 assert(cpu_id < localTimer.size());
181
182 if (daddr < Timer::Size)
183 localTimer[cpu_id]->write(pkt, daddr);
184 else
185 panic("Tried to write CpuLocalTimer at offset %#x that doesn't exist\n", daddr);
186 pkt->makeAtomicResponse();
187 return pioDelay;
188}
189
190void
192{
193 DPRINTF(Timer, "Writing to CpuLocalTimer at offset: %#x\n", daddr);
194 bool old_enable;
195 bool old_wd_mode;
196 uint32_t old_val;
197
198 switch (daddr) {
199 case TimerLoadReg:
200 // Writing to this register also resets the counter register and
201 // starts decrementing if the counter is enabled.
202 timerLoadValue = pkt->getLE<uint32_t>();
203 restartTimerCounter(timerLoadValue);
204 break;
205 case TimerCounterReg:
206 // Can be written, doesn't start counting unless the timer is enabled
207 restartTimerCounter(pkt->getLE<uint32_t>());
208 break;
209 case TimerControlReg:
210 old_enable = timerControl.enable;
211 timerControl = pkt->getLE<uint32_t>();
212 if ((old_enable == 0) && timerControl.enable)
213 restartTimerCounter(timerLoadValue);
214 break;
215 case TimerIntStatusReg:
216 rawIntTimer = false;
217 if (pendingIntTimer) {
218 pendingIntTimer = false;
219 DPRINTF(Timer, "Clearing interrupt\n");
220 }
221 break;
222 case WatchdogLoadReg:
223 watchdogLoadValue = pkt->getLE<uint32_t>();
224 restartWatchdogCounter(watchdogLoadValue);
225 break;
226 case WatchdogCounterReg:
227 // Can't be written when in watchdog mode, but can in timer mode
228 if (!watchdogControl.watchdogMode) {
229 restartWatchdogCounter(pkt->getLE<uint32_t>());
230 }
231 break;
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);
238 // cannot disable watchdog using control register
239 if ((old_wd_mode == 1) && watchdogControl.watchdogMode == 0)
240 watchdogControl.watchdogMode = 1;
241 break;
242 case WatchdogIntStatusReg:
243 rawIntWatchdog = false;
244 if (pendingIntWatchdog) {
245 pendingIntWatchdog = false;
246 DPRINTF(Timer, "Clearing watchdog interrupt\n");
247 }
248 break;
249 case WatchdogResetStatusReg:
250 rawResetWatchdog = false;
251 DPRINTF(Timer, "Clearing watchdog reset flag\n");
252 break;
253 case WatchdogDisableReg:
254 old_val = watchdogDisableReg;
255 watchdogDisableReg = pkt->getLE<uint32_t>();
256 // if this sequence is observed, turn off watchdog mode
257 if (old_val == 0x12345678 && watchdogDisableReg == 0x87654321)
258 watchdogControl.watchdogMode = 0;
259 break;
260 default:
261 panic("Tried to write CpuLocalTimer timer at offset %#x\n", daddr);
262 break;
263 }
264}
265
266//XXX: Two functions are needed because the control registers are different types
267void
269{
270 DPRINTF(Timer, "Resetting timer counter with value %#x\n", val);
271 if (!timerControl.enable)
272 return;
273
274 Tick time = parent->clockPeriod() << (4 * timerControl.prescalar);
275 time *= val;
276
277 if (timerZeroEvent.scheduled()) {
278 DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
279 parent->deschedule(timerZeroEvent);
280 }
281 parent->schedule(timerZeroEvent, curTick() + time);
282 DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
283}
284
285void
287{
288 DPRINTF(Timer, "Resetting watchdog counter with value %#x\n", val);
289 if (!watchdogControl.enable)
290 return;
291
292 Tick time = parent->clockPeriod() << (4 * watchdogControl.prescalar);
293 time *= val;
294
295 if (watchdogZeroEvent.scheduled()) {
296 DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
297 parent->deschedule(watchdogZeroEvent);
298 }
299 parent->schedule(watchdogZeroEvent, curTick() + time);
300 DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
301}
303
304void
306{
307 if (!timerControl.enable)
308 return;
309
310 DPRINTF(Timer, "Timer Counter reached zero\n");
311
312 rawIntTimer = true;
313 bool old_pending = pendingIntTimer;
314 if (timerControl.intEnable)
315 pendingIntTimer = true;
316 if (pendingIntTimer && !old_pending) {
317 DPRINTF(Timer, "-- Causing interrupt\n");
318 intTimer->raise();
319 }
320
321 if (!timerControl.autoReload)
322 return;
323 else
324 restartTimerCounter(timerLoadValue);
325}
326
327void
329{
330 if (!watchdogControl.enable)
331 return;
332
333 DPRINTF(Timer, "Watchdog Counter reached zero\n");
334
335 rawIntWatchdog = true;
336 bool old_pending = pendingIntWatchdog;
337 // generates an interrupt only if the watchdog is in timer
338 // mode.
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");
344 //XXX: Should we ever support a true watchdog reset?
345 }
346
347 if (pendingIntWatchdog && !old_pending) {
348 DPRINTF(Timer, "-- Causing interrupt\n");
349 intWatchdog->raise();
350 }
351
352 if (watchdogControl.watchdogMode)
353 return;
354 else if (watchdogControl.autoReload)
355 restartWatchdogCounter(watchdogLoadValue);
356}
357
358void
360{
361 DPRINTF(Checkpoint, "Serializing Arm CpuLocalTimer\n");
362
363 uint32_t timer_control_serial = timerControl;
364 uint32_t watchdog_control_serial = watchdogControl;
365 SERIALIZE_SCALAR(timer_control_serial);
366 SERIALIZE_SCALAR(watchdog_control_serial);
367
368 SERIALIZE_SCALAR(rawIntTimer);
369 SERIALIZE_SCALAR(rawIntWatchdog);
370 SERIALIZE_SCALAR(rawResetWatchdog);
371 SERIALIZE_SCALAR(watchdogDisableReg);
372 SERIALIZE_SCALAR(pendingIntTimer);
373 SERIALIZE_SCALAR(pendingIntWatchdog);
374 SERIALIZE_SCALAR(timerLoadValue);
375 SERIALIZE_SCALAR(watchdogLoadValue);
376
377 bool timer_is_in_event = timerZeroEvent.scheduled();
378 SERIALIZE_SCALAR(timer_is_in_event);
379 bool watchdog_is_in_event = watchdogZeroEvent.scheduled();
380 SERIALIZE_SCALAR(watchdog_is_in_event);
381
382 Tick timer_event_time;
383 if (timer_is_in_event){
384 timer_event_time = timerZeroEvent.when();
385 SERIALIZE_SCALAR(timer_event_time);
386 }
387 Tick watchdog_event_time;
388 if (watchdog_is_in_event){
389 watchdog_event_time = watchdogZeroEvent.when();
390 SERIALIZE_SCALAR(watchdog_event_time);
391 }
392}
393
394void
396{
397 DPRINTF(Checkpoint, "Unserializing Arm CpuLocalTimer\n");
398
399 uint32_t timer_control_serial;
400 UNSERIALIZE_SCALAR(timer_control_serial);
401 timerControl = timer_control_serial;
402 uint32_t watchdog_control_serial;
403 UNSERIALIZE_SCALAR(watchdog_control_serial);
404 watchdogControl = watchdog_control_serial;
405
406 UNSERIALIZE_SCALAR(rawIntTimer);
407 UNSERIALIZE_SCALAR(rawIntWatchdog);
408 UNSERIALIZE_SCALAR(rawResetWatchdog);
409 UNSERIALIZE_SCALAR(watchdogDisableReg);
410 UNSERIALIZE_SCALAR(pendingIntTimer);
411 UNSERIALIZE_SCALAR(pendingIntWatchdog);
412 UNSERIALIZE_SCALAR(timerLoadValue);
413 UNSERIALIZE_SCALAR(watchdogLoadValue);
414
415 bool timer_is_in_event;
416 UNSERIALIZE_SCALAR(timer_is_in_event);
417 bool watchdog_is_in_event;
418 UNSERIALIZE_SCALAR(watchdog_is_in_event);
419
420 Tick timer_event_time;
421 if (timer_is_in_event){
422 UNSERIALIZE_SCALAR(timer_event_time);
423 parent->schedule(timerZeroEvent, timer_event_time);
424 }
425 Tick watchdog_event_time;
426 if (watchdog_is_in_event) {
427 UNSERIALIZE_SCALAR(watchdog_event_time);
428 parent->schedule(watchdogZeroEvent, watchdog_event_time);
429 }
430}
431
432
433
434void
436{
437 for (int i = 0; i < sys->threads.size(); i++)
438 localTimer[i]->serializeSection(cp, csprintf("timer%d", i));
439}
440
441void
443{
444 for (int i = 0; i < sys->threads.size(); i++)
445 localTimer[i]->unserializeSection(cp, csprintf("timer%d", i));
446}
447
448} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
Base class for ARM GIC implementations.
Generic representation of an Arm interrupt pin.
Definition base_gic.hh:200
Addr pioAddr
Address that the device listens to.
Definition io_device.hh:151
Tick pioDelay
Delay that the device experinces on an access.
Definition io_device.hh:157
Addr pioSize
Size that the device's address range.
Definition io_device.hh:154
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....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
Definition packet.hh:377
unsigned getSize() const
Definition packet.hh:817
void makeAtomicResponse()
Definition packet.hh:1074
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
PioDeviceParams Params
Definition io_device.hh:134
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition io_device.cc:59
int size() const
Definition system.hh:210
Threads threads
Definition system.hh:310
ThreadContext is the external interface to all thread state for anything outside of the CPU.
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:200
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Definition serialize.cc:74
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition serialize.cc:81
const Params & params() const
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 0 > p
Bitfield< 63 > val
Definition misc.hh:804
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
uint64_t Tick
Tick count type.
Definition types.hh:58
int ContextID
Globally unique thread context ID.
Definition types.hh:239
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
This implements the cpu local timer from the Cortex-A9 MPCore Technical Reference Manual rev r2p2 (AR...
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0