gem5  v20.0.0.3
timer_sp804.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 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 
38 #include "dev/arm/timer_sp804.hh"
39 
40 #include "base/intmath.hh"
41 #include "base/trace.hh"
42 #include "debug/Checkpoint.hh"
43 #include "debug/Timer.hh"
44 #include "dev/arm/base_gic.hh"
45 #include "mem/packet.hh"
46 #include "mem/packet_access.hh"
47 
49  : AmbaPioDevice(p, 0x1000), gic(p->gic),
50  timer0(name() + ".timer0", this, p->int_num0, p->clock0),
51  timer1(name() + ".timer1", this, p->int_num1, p->clock1)
52 {
53 }
54 
55 Sp804::Timer::Timer(std::string __name, Sp804 *_parent, int int_num, Tick _clock)
56  : _name(__name), parent(_parent), intNum(int_num), clock(_clock), control(0x20),
57  rawInt(false), pendingInt(false), loadValue(0xffffffff),
58  zeroEvent([this]{ counterAtZero(); }, name())
59 {
60 }
61 
62 
63 Tick
65 {
66  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
67  assert(pkt->getSize() == 4);
68  Addr daddr = pkt->getAddr() - pioAddr;
69  DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr);
70 
71  if (daddr < Timer::Size)
72  timer0.read(pkt, daddr);
73  else if ((daddr - Timer::Size) < Timer::Size)
74  timer1.read(pkt, daddr - Timer::Size);
75  else if (!readId(pkt, ambaId, pioAddr))
76  panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr);
77  pkt->makeAtomicResponse();
78  return pioDelay;
79 }
80 
81 
82 void
84 {
85  switch(daddr) {
86  case LoadReg:
87  pkt->setLE<uint32_t>(loadValue);
88  break;
89  case CurrentReg:
90  DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
91  zeroEvent.when(), clock, control.timerPrescale);
92  Tick time;
93  time = zeroEvent.when() - curTick();
94  time = time / clock / power(16, control.timerPrescale);
95  DPRINTF(Timer, "-- returning counter at %d\n", time);
96  pkt->setLE<uint32_t>(time);
97  break;
98  case ControlReg:
99  pkt->setLE<uint32_t>(control);
100  break;
101  case RawISR:
102  pkt->setLE<uint32_t>(rawInt);
103  break;
104  case MaskedISR:
105  pkt->setLE<uint32_t>(pendingInt);
106  break;
107  case BGLoad:
108  pkt->setLE<uint32_t>(loadValue);
109  break;
110  default:
111  panic("Tried to read SP804 timer at offset %#x\n", daddr);
112  break;
113  }
114  DPRINTF(Timer, "Reading %#x from Timer at offset: %#x\n",
115  pkt->getLE<uint32_t>(), daddr);
116 }
117 
118 Tick
120 {
121  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
122  assert(pkt->getSize() == 4);
123  Addr daddr = pkt->getAddr() - pioAddr;
124  DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr);
125 
126  if (daddr < Timer::Size)
127  timer0.write(pkt, daddr);
128  else if ((daddr - Timer::Size) < Timer::Size)
129  timer1.write(pkt, daddr - Timer::Size);
130  else if (!readId(pkt, ambaId, pioAddr))
131  panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr);
132  pkt->makeAtomicResponse();
133  return pioDelay;
134 }
135 
136 void
138 {
139  DPRINTF(Timer, "Writing %#x to Timer at offset: %#x\n",
140  pkt->getLE<uint32_t>(), daddr);
141  switch (daddr) {
142  case LoadReg:
143  loadValue = pkt->getLE<uint32_t>();
145  break;
146  case CurrentReg:
147  // Spec says this value can't be written, but linux writes it anyway
148  break;
149  case ControlReg:
150  bool old_enable;
151  old_enable = control.timerEnable;
152  control = pkt->getLE<uint32_t>();
153  if ((old_enable == 0) && control.timerEnable)
155  break;
156  case IntClear:
157  rawInt = false;
158  if (pendingInt) {
159  pendingInt = false;
160  DPRINTF(Timer, "Clearing interrupt\n");
162  }
163  break;
164  case BGLoad:
165  loadValue = pkt->getLE<uint32_t>();
166  break;
167  default:
168  panic("Tried to write SP804 timer at offset %#x\n", daddr);
169  break;
170  }
171 }
172 
173 void
175 {
176  DPRINTF(Timer, "Resetting counter with value %#x\n", val);
177  if (!control.timerEnable)
178  return;
179 
180  Tick time = clock * power(16, control.timerPrescale);
181  if (control.timerSize)
182  time *= val;
183  else
184  time *= bits(val,15,0);
185 
186  if (zeroEvent.scheduled()) {
187  DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
189  }
190  parent->schedule(zeroEvent, curTick() + time);
191  DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
192 }
193 
194 void
196 {
197  if (!control.timerEnable)
198  return;
199 
200  DPRINTF(Timer, "Counter reached zero\n");
201 
202  rawInt = true;
203  bool old_pending = pendingInt;
204  if (control.intEnable)
205  pendingInt = true;
206  if (pendingInt && !old_pending) {
207  DPRINTF(Timer, "-- Causing interrupt\n");
209  }
210 
211  if (control.oneShot)
212  return;
213 
214  // Free-running
215  if (control.timerMode == 0)
216  restartCounter(0xffffffff);
217  else
219 }
220 
221 void
223 {
224  DPRINTF(Checkpoint, "Serializing Arm Sp804\n");
225 
226  uint32_t control_serial = control;
227  SERIALIZE_SCALAR(control_serial);
228 
232 
233  bool is_in_event = zeroEvent.scheduled();
234  SERIALIZE_SCALAR(is_in_event);
235 
236  Tick event_time;
237  if (is_in_event){
238  event_time = zeroEvent.when();
239  SERIALIZE_SCALAR(event_time);
240  }
241 }
242 
243 void
245 {
246  DPRINTF(Checkpoint, "Unserializing Arm Sp804\n");
247 
248  uint32_t control_serial;
249  UNSERIALIZE_SCALAR(control_serial);
250  control = control_serial;
251 
255 
256  bool is_in_event;
257  UNSERIALIZE_SCALAR(is_in_event);
258 
259  Tick event_time;
260  if (is_in_event){
261  UNSERIALIZE_SCALAR(event_time);
262  parent->schedule(zeroEvent, event_time);
263  }
264 }
265 
266 
267 
268 void
270 {
271  timer0.serializeSection(cp, "timer0");
272  timer1.serializeSection(cp, "timer1");
273 }
274 
275 void
277 {
278  timer0.unserializeSection(cp, "timer0");
279  timer1.unserializeSection(cp, "timer1");
280 }
281 
282 Sp804 *
283 Sp804Params::create()
284 {
285  return new Sp804(this);
286 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
#define DPRINTF(x,...)
Definition: trace.hh:225
void counterAtZero()
Called when the counter reaches 0.
Definition: timer_sp804.cc:195
void read(PacketPtr pkt, Addr daddr)
Handle read for a single timer.
Definition: timer_sp804.cc:83
virtual void clearInt(uint32_t num)=0
Clear an interrupt from a device that is connected to the GIC.
const std::string & name()
Definition: trace.cc:50
EndBitUnion(CTRL) protected Sp804 * parent
Pointer to parent class.
Definition: timer_sp804.hh:75
void restartCounter(uint32_t val)
Restart the counter ticking at val.
Definition: timer_sp804.cc:174
CTRL control
Control register as specified above.
Definition: timer_sp804.hh:90
AmbaPioDeviceParams Params
Definition: amba_device.hh:82
Definition: cprintf.cc:40
Timer timer0
Timers that do the actual work.
Definition: timer_sp804.hh:130
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Definition: serialize.cc:171
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: timer_sp804.cc:269
Bitfield< 63 > val
Definition: misc.hh:769
void setLE(T v)
Set the value in the data pointer to v as little endian.
unsigned getSize() const
Definition: packet.hh:730
std::string name() const
Definition: timer_sp804.hh:114
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: timer_sp804.cc:244
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:770
Tick curTick()
The current simulated tick.
Definition: core.hh:44
Sp804(Params *p)
The constructor for RealView just registers itself with the MMU.
Definition: timer_sp804.cc:48
Addr pioSize
Size that the device&#39;s address range.
Definition: io_device.hh:157
virtual void sendInt(uint32_t num)=0
Post an interrupt from a device that is connected to the GIC.
void makeAtomicResponse()
Definition: packet.hh:943
uint64_t Tick
Tick count type.
Definition: types.hh:61
uint64_t power(uint32_t n, uint32_t e)
Definition: intmath.hh:40
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: timer_sp804.cc:276
void deschedule(Event &event)
Definition: eventq.hh:943
bool pendingInt
If an interrupt is currently pending.
Definition: timer_sp804.hh:98
uint32_t loadValue
Value to load into counter when periodic mode reaches 0.
Definition: timer_sp804.hh:101
Addr getAddr() const
Definition: packet.hh:720
Tick write(PacketPtr pkt) override
All writes are simply ignored.
Definition: timer_sp804.cc:119
void schedule(Event &event, Tick when)
Definition: eventq.hh:934
This implements the dual Sp804 timer block.
bool readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr)
Definition: amba_device.cc:72
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:140
uint64_t ambaId
Definition: amba_device.hh:79
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:249
EventFunctionWrapper zeroEvent
Definition: timer_sp804.hh:105
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:763
bool scheduled() const
Determine if the current event is scheduled.
Definition: eventq.hh:459
bool rawInt
If timer has caused an interrupt.
Definition: timer_sp804.hh:94
Base class for ARM GIC implementations.
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:63
const Tick clock
Number of ticks in a clock input.
Definition: timer_sp804.hh:87
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
Bitfield< 27, 24 > gic
void write(PacketPtr pkt, Addr daddr)
Handle write for a single timer.
Definition: timer_sp804.cc:137
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Timer(std::string __name, Sp804 *parent, int int_num, Tick clock)
Definition: timer_sp804.cc:55
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:71
Timer timer1
Definition: timer_sp804.hh:131
Bitfield< 0 > p
Tick when() const
Get the time that the event is scheduled.
Definition: eventq.hh:499
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
BaseGic * gic
Pointer to the GIC for causing an interrupt.
Definition: timer_sp804.hh:127
const uint32_t intNum
Number of interrupt to cause/clear.
Definition: timer_sp804.hh:84
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: timer_sp804.cc:222
Tick read(PacketPtr pkt) override
Handle a read to the device.
Definition: timer_sp804.cc:64
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition: serialize.cc:178

Generated on Fri Jul 3 2020 15:53:01 for gem5 by doxygen 1.8.13