gem5  v22.1.0.0
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 <cassert>
41 
42 #include "base/intmath.hh"
43 #include "base/logging.hh"
44 #include "base/trace.hh"
45 #include "debug/Checkpoint.hh"
46 #include "debug/Timer.hh"
47 #include "dev/arm/base_gic.hh"
48 #include "mem/packet.hh"
49 #include "mem/packet_access.hh"
50 
51 namespace gem5
52 {
53 
55  : AmbaPioDevice(p, 0x1000),
56  timer0(name() + ".timer0", this, p.int0->get(), p.clock0),
57  timer1(name() + ".timer1", this, p.int1->get(), p.clock1)
58 {
59 }
60 
61 Sp804::Timer::Timer(std::string __name, Sp804 *_parent,
62  ArmInterruptPin *_interrupt, Tick _clock)
63  : _name(__name), parent(_parent), interrupt(_interrupt),
64  clock(_clock), control(0x20),
65  rawInt(false), pendingInt(false), loadValue(0xffffffff),
66  zeroEvent([this]{ counterAtZero(); }, name())
67 {
68 }
69 
70 
71 Tick
73 {
74  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
75  assert(pkt->getSize() == 4);
76  Addr daddr = pkt->getAddr() - pioAddr;
77  DPRINTF(Timer, "Reading from DualTimer at offset: %#x\n", daddr);
78 
79  if (daddr < Timer::Size)
80  timer0.read(pkt, daddr);
81  else if ((daddr - Timer::Size) < Timer::Size)
82  timer1.read(pkt, daddr - Timer::Size);
83  else if (!readId(pkt, ambaId, pioAddr))
84  panic("Tried to read SP804 at offset %#x that doesn't exist\n", daddr);
85  pkt->makeAtomicResponse();
86  return pioDelay;
87 }
88 
89 
90 void
92 {
93  switch(daddr) {
94  case LoadReg:
95  pkt->setLE<uint32_t>(loadValue);
96  break;
97  case CurrentReg:
98  DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
99  zeroEvent.when(), clock, control.timerPrescale);
100  Tick time;
101  time = zeroEvent.when() - curTick();
102  time = (time / clock) >> (4 * control.timerPrescale);
103  DPRINTF(Timer, "-- returning counter at %d\n", time);
104  pkt->setLE<uint32_t>(time);
105  break;
106  case ControlReg:
107  pkt->setLE<uint32_t>(control);
108  break;
109  case RawISR:
110  pkt->setLE<uint32_t>(rawInt);
111  break;
112  case MaskedISR:
113  pkt->setLE<uint32_t>(pendingInt);
114  break;
115  case BGLoad:
116  pkt->setLE<uint32_t>(loadValue);
117  break;
118  default:
119  panic("Tried to read SP804 timer at offset %#x\n", daddr);
120  break;
121  }
122  DPRINTF(Timer, "Reading %#x from Timer at offset: %#x\n",
123  pkt->getLE<uint32_t>(), daddr);
124 }
125 
126 Tick
128 {
129  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
130  assert(pkt->getSize() == 4);
131  Addr daddr = pkt->getAddr() - pioAddr;
132  DPRINTF(Timer, "Writing to DualTimer at offset: %#x\n", daddr);
133 
134  if (daddr < Timer::Size)
135  timer0.write(pkt, daddr);
136  else if ((daddr - Timer::Size) < Timer::Size)
137  timer1.write(pkt, daddr - Timer::Size);
138  else if (!readId(pkt, ambaId, pioAddr))
139  panic("Tried to write SP804 at offset %#x that doesn't exist\n", daddr);
140  pkt->makeAtomicResponse();
141  return pioDelay;
142 }
143 
144 void
146 {
147  DPRINTF(Timer, "Writing %#x to Timer at offset: %#x\n",
148  pkt->getLE<uint32_t>(), daddr);
149  switch (daddr) {
150  case LoadReg:
151  loadValue = pkt->getLE<uint32_t>();
152  restartCounter(loadValue);
153  break;
154  case CurrentReg:
155  // Spec says this value can't be written, but linux writes it anyway
156  break;
157  case ControlReg:
158  bool old_enable;
159  old_enable = control.timerEnable;
160  control = pkt->getLE<uint32_t>();
161  if ((old_enable == 0) && control.timerEnable)
162  restartCounter(loadValue);
163  break;
164  case IntClear:
165  rawInt = false;
166  if (pendingInt) {
167  pendingInt = false;
168  DPRINTF(Timer, "Clearing interrupt\n");
169  interrupt->clear();
170  }
171  break;
172  case BGLoad:
173  loadValue = pkt->getLE<uint32_t>();
174  break;
175  default:
176  panic("Tried to write SP804 timer at offset %#x\n", daddr);
177  break;
178  }
179 }
180 
181 void
183 {
184  DPRINTF(Timer, "Resetting counter with value %#x\n", val);
185  if (!control.timerEnable)
186  return;
187 
188  Tick time = clock << (4 * control.timerPrescale);
189  if (control.timerSize)
190  time *= val;
191  else
192  time *= bits(val,15,0);
193 
194  if (zeroEvent.scheduled()) {
195  DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
196  parent->deschedule(zeroEvent);
197  }
198  parent->schedule(zeroEvent, curTick() + time);
199  DPRINTF(Timer, "-- Scheduling new event for: %d\n", curTick() + time);
200 }
201 
202 void
204 {
205  if (!control.timerEnable)
206  return;
207 
208  DPRINTF(Timer, "Counter reached zero\n");
209 
210  rawInt = true;
211  bool old_pending = pendingInt;
212  if (control.intEnable)
213  pendingInt = true;
214  if (pendingInt && !old_pending) {
215  DPRINTF(Timer, "-- Causing interrupt\n");
216  interrupt->raise();
217  }
218 
219  if (control.oneShot)
220  return;
221 
222  // Free-running
223  if (control.timerMode == 0)
224  restartCounter(0xffffffff);
225  else
226  restartCounter(loadValue);
227 }
228 
229 void
231 {
232  DPRINTF(Checkpoint, "Serializing Arm Sp804\n");
233 
234  uint32_t control_serial = control;
235  SERIALIZE_SCALAR(control_serial);
236 
237  SERIALIZE_SCALAR(rawInt);
238  SERIALIZE_SCALAR(pendingInt);
239  SERIALIZE_SCALAR(loadValue);
240 
241  bool is_in_event = zeroEvent.scheduled();
242  SERIALIZE_SCALAR(is_in_event);
243 
244  Tick event_time;
245  if (is_in_event){
246  event_time = zeroEvent.when();
247  SERIALIZE_SCALAR(event_time);
248  }
249 }
250 
251 void
253 {
254  DPRINTF(Checkpoint, "Unserializing Arm Sp804\n");
255 
256  uint32_t control_serial;
257  UNSERIALIZE_SCALAR(control_serial);
258  control = control_serial;
259 
260  UNSERIALIZE_SCALAR(rawInt);
261  UNSERIALIZE_SCALAR(pendingInt);
262  UNSERIALIZE_SCALAR(loadValue);
263 
264  bool is_in_event;
265  UNSERIALIZE_SCALAR(is_in_event);
266 
267  Tick event_time;
268  if (is_in_event){
269  UNSERIALIZE_SCALAR(event_time);
270  parent->schedule(zeroEvent, event_time);
271  }
272 }
273 
274 
275 
276 void
278 {
279  timer0.serializeSection(cp, "timer0");
280  timer1.serializeSection(cp, "timer1");
281 }
282 
283 void
285 {
286  timer0.unserializeSection(cp, "timer0");
287  timer1.unserializeSection(cp, "timer1");
288 }
289 
290 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
Base class for ARM GIC implementations.
bool readId(PacketPtr pkt, uint64_t amba_id, Addr pio_addr)
Definition: amba_device.cc:75
AmbaPioDeviceParams Params
Definition: amba_device.hh:84
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
virtual std::string name() const
Definition: named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
Addr getAddr() const
Definition: packet.hh:805
void setLE(T v)
Set the value in the data pointer to v as little endian.
unsigned getSize() const
Definition: packet.hh:815
void makeAtomicResponse()
Definition: packet.hh:1071
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Timer(std::string __name, Sp804 *parent, ArmInterruptPin *_interrupt, Tick clock)
Definition: timer_sp804.cc:61
void counterAtZero()
Called when the counter reaches 0.
Definition: timer_sp804.cc:203
void restartCounter(uint32_t val)
Restart the counter ticking at val.
Definition: timer_sp804.cc:182
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: timer_sp804.cc:230
void write(PacketPtr pkt, Addr daddr)
Handle write for a single timer.
Definition: timer_sp804.cc:145
void read(PacketPtr pkt, Addr daddr)
Handle read for a single timer.
Definition: timer_sp804.cc:91
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: timer_sp804.cc:252
Bitfield< 3, 2 > timerPrescale
Definition: timer_sp804.hh:81
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: timer_sp804.cc:277
Timer timer0
Timers that do the actual work.
Definition: timer_sp804.hh:138
Sp804(const Params &p)
The constructor for RealView just registers itself with the MMU.
Definition: timer_sp804.cc:54
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: timer_sp804.cc:284
Tick read(PacketPtr pkt) override
Handle a read to the device.
Definition: timer_sp804.cc:72
Tick write(PacketPtr pkt) override
All writes are simply ignored.
Definition: timer_sp804.cc:127
bool int1
Definition: common.h:43
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
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
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 63 > val
Definition: misc.hh:776
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
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
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
This implements the dual Sp804 timer block.
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:33 for gem5 by doxygen 1.9.1