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

Generated on Tue Mar 23 2021 19:41:26 for gem5 by doxygen 1.8.17