gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
timer_a9global.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 Gedare Bloom
3  * Copyright (c) 2010 ARM Limited
4  * All rights reserved
5  *
6  * The license below extends only to copyright in the software and shall
7  * not be construed as granting a license to any other intellectual
8  * property including but not limited to intellectual property relating
9  * to a hardware implementation of the functionality of the software
10  * licensed hereunder. You may use the software subject to the license
11  * terms below provided that you ensure that this notice is replicated
12  * unmodified and in its entirety in all distributions of the software,
13  * modified or unmodified, in source code or in binary form.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions are
17  * met: redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer;
19  * redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the distribution;
22  * neither the name of the copyright holders nor the names of its
23  * contributors may be used to endorse or promote products derived from
24  * this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Authors: Ali Saidi
39  * Gedare Bloom
40  */
41 
43 
44 #include "base/intmath.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 
53  : BasicPioDevice(p, 0x1C), gic(p->gic),
54  global_timer(name() + ".globaltimer", this, p->int_num)
55 {
56 }
57 
58 A9GlobalTimer::Timer::Timer(std::string __name, A9GlobalTimer *_parent,
59  int int_num)
60  : _name(__name), parent(_parent), intNum(int_num), control(0x0),
61  rawInt(false), pendingInt(false), autoIncValue(0x0), cmpValEvent(this)
62 {
63 }
64 
65 Tick
67 {
68  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
69  assert(pkt->getSize() == 4);
70  Addr daddr = pkt->getAddr() - pioAddr;
71 
72  if (daddr < Timer::Size)
73  global_timer.read(pkt, daddr);
74  else
75  panic("Tried to read A9GlobalTimer at offset %#x that doesn't exist\n",
76  daddr);
77  pkt->makeAtomicResponse();
78  return pioDelay;
79 }
80 
81 uint64_t
83 {
84  return ticks / parent->clockPeriod() / (control.prescalar + 1) - 1;
85 }
86 
87 void
89 {
90  DPRINTF(Timer, "Reading from A9GlobalTimer at offset: %#x\n", daddr);
91  uint64_t time;
92 
93  switch(daddr) {
94  case CounterRegLow32:
96  DPRINTF(Timer, "-- returning lower 32-bits of counter: %u\n", time);
97  pkt->setLE<uint32_t>(time);
98  break;
99  case CounterRegHigh32:
101  time >>= 32;
102  DPRINTF(Timer, "-- returning upper 32-bits of counter: %u\n", time);
103  pkt->setLE<uint32_t>(time);
104  break;
105  case ControlReg:
106  pkt->setLE<uint32_t>(control);
107  break;
108  case IntStatusReg:
109  pkt->setLE<uint32_t>(rawInt);
110  break;
111  case CmpValRegLow32:
112  DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
113  cmpValEvent.when(), parent->clockPeriod(), control.prescalar);
114  if (cmpValEvent.scheduled()) {
115  time = getTimeCounterFromTicks(cmpValEvent.when() - curTick());
116  } else {
117  time = 0;
118  }
119  DPRINTF(Timer, "-- returning lower 32-bits of comparator: %u\n", time);
120  pkt->setLE<uint32_t>(time);
121  break;
122  case CmpValRegHigh32:
123  DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
124  cmpValEvent.when(), parent->clockPeriod(), control.prescalar);
125  if (cmpValEvent.scheduled()) {
126  time = getTimeCounterFromTicks(cmpValEvent.when() - curTick());
127  time >>= 32;
128  } else {
129  time = 0;
130  }
131  DPRINTF(Timer, "-- returning upper 32-bits of comparator: %u\n", time);
132  pkt->setLE<uint32_t>(time);
133  break;
134  case AutoIncrementReg:
135  pkt->setLE<uint32_t>(autoIncValue);
136  break;
137  default:
138  panic("Tried to read A9GlobalTimer at offset %#x\n", daddr);
139  break;
140  }
141  DPRINTF(Timer, "Reading %#x from A9GlobalTimer at offset: %#x\n",
142  pkt->getLE<uint32_t>(), daddr);
143 }
144 
145 Tick
147 {
148  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
149  assert(pkt->getSize() == 4);
150  Addr daddr = pkt->getAddr() - pioAddr;
151  DPRINTF(Timer, "Writing to A9GlobalTimer at offset: %#x\n", daddr);
152 
153  warn_once("A9 Global Timer doesn't support banked per-cpu registers\n");
154 
155  if (daddr < Timer::Size)
156  global_timer.write(pkt, daddr);
157  else
158  panic("Tried to write A9GlobalTimer at offset %#x doesn't exist\n",
159  daddr);
160  pkt->makeAtomicResponse();
161  return pioDelay;
162 }
163 
164 void
166 {
167  DPRINTF(Timer, "Writing %#x to A9GlobalTimer at offset: %#x\n",
168  pkt->getLE<uint32_t>(), daddr);
169  switch (daddr) {
170  case CounterRegLow32:
171  case CounterRegHigh32:
172  DPRINTF(Timer, "Ignoring unsupported write to Global Timer Counter\n");
173  break;
174  case ControlReg:
175  bool old_enable;
176  bool old_cmpEnable;
177  old_enable = control.enable;
178  old_cmpEnable = control.cmpEnable;
179  control = pkt->getLE<uint32_t>();
180  if ((old_enable == 0) && control.enable)
181  restartCounter();
182  if ((old_cmpEnable == 0) && control.cmpEnable)
183  restartCounter();
184  break;
185  case IntStatusReg:
186  /* TODO: should check that '1' was written. */
187  rawInt = false;
188  if (pendingInt) {
189  pendingInt = false;
190  DPRINTF(Timer, "Clearing interrupt\n");
192  }
193  break;
194  case CmpValRegLow32:
195  cmpVal &= 0xFFFFFFFF00000000ULL;
196  cmpVal |= (uint64_t)pkt->getLE<uint32_t>();
197  break;
198  case CmpValRegHigh32:
199  cmpVal &= 0x00000000FFFFFFFFULL;
200  cmpVal |= ((uint64_t)pkt->getLE<uint32_t>() << 32);
201  break;
202  case AutoIncrementReg:
203  autoIncValue = pkt->getLE<uint32_t>();
204  break;
205  default:
206  panic("Tried to write A9GlobalTimer at offset %#x\n", daddr);
207  break;
208  }
209 }
210 
211 void
213 {
214  if (!control.enable)
215  return;
216  DPRINTF(Timer, "Restarting counter with value %#x\n", cmpVal);
217 
218  Tick time = parent->clockPeriod() * (control.prescalar + 1) * (cmpVal + 1);
219 
220  if (time < curTick()) {
221  DPRINTF(Timer, "-- Event time %#x < curTick %#x\n", time, curTick());
222  return;
223  }
224  if (cmpValEvent.scheduled()) {
225  DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
227  }
228  parent->schedule(cmpValEvent, time);
229  DPRINTF(Timer, "-- Scheduling new event for: %d\n", time);
230 }
231 
232 void
234 {
235  if (!control.enable)
236  return;
237 
238  DPRINTF(Timer, "Counter reached cmpVal\n");
239 
240  rawInt = true;
241  bool old_pending = pendingInt;
242  if (control.intEnable)
243  pendingInt = true;
244  if (pendingInt && !old_pending) {
245  DPRINTF(Timer, "-- Causing interrupt\n");
246  parent->gic->sendPPInt(intNum, 0); /* FIXME: cpuNum */
247  }
248 
249  if (control.autoIncrement == 0) // one-shot
250  return;
251 
252  cmpVal += (uint64_t)autoIncValue;
253  restartCounter();
254 }
255 
256 void
258 {
259  DPRINTF(Checkpoint, "Serializing Arm A9GlobalTimer\n");
260 
261  uint32_t control_serial = control;
262  SERIALIZE_SCALAR(control_serial);
263 
268 
269  bool is_in_event = cmpValEvent.scheduled();
270  SERIALIZE_SCALAR(is_in_event);
271 
272  Tick event_time;
273  if (is_in_event){
274  event_time = cmpValEvent.when();
275  SERIALIZE_SCALAR(event_time);
276  }
277 }
278 
279 void
281 {
282  DPRINTF(Checkpoint, "Unserializing Arm A9GlobalTimer\n");
283 
284  uint32_t control_serial;
285  UNSERIALIZE_SCALAR(control_serial);
286  control = control_serial;
287 
292 
293  bool is_in_event;
294  UNSERIALIZE_SCALAR(is_in_event);
295 
296  Tick event_time;
297  if (is_in_event){
298  UNSERIALIZE_SCALAR(event_time);
299  parent->schedule(cmpValEvent, event_time);
300  }
301 }
302 
303 void
305 {
307 }
308 
309 void
311 {
313 }
314 
316 A9GlobalTimerParams::create()
317 {
318  return new A9GlobalTimer(this);
319 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
void write(PacketPtr pkt, Addr daddr)
Handle write for a single timer.
BaseGic * gic
Pointer to the GIC for causing an interrupt.
Tick write(PacketPtr pkt) override
Handle a write to the device.
void unserialize(CheckpointIn &cp) override
Unserialize an object.
uint64_t getTimeCounterFromTicks(Tick ticks)
Convert a number of ticks into the time counter format.
A9GlobalTimer(Params *p)
The constructor for RealView just registers itself with the MMU.
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:54
CTRL control
Control register as specified above.
EventWrapper< Timer, &Timer::counterAtCmpVal > cmpValEvent
Timer global_timer
Timer that does the actual work.
Definition: cprintf.cc:42
Tick clockPeriod() const
Timer(std::string __name, A9GlobalTimer *parent, int int_num)
void deschedule(Event &event)
Definition: eventq.hh:750
Tick read(PacketPtr pkt) override
Handle a read to the device.
void setLE(T v)
Set the value in the data pointer to v as little endian.
unsigned getSize() const
Definition: packet.hh:736
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
void restartCounter()
Restart the counter ticking.
Tick curTick()
The current simulated tick.
Definition: core.hh:47
Addr pioSize
Size that the device&#39;s address range.
Definition: io_device.hh:160
void serialize(CheckpointOut &cp) const override
Serialize an object.
virtual void sendPPInt(uint32_t num, uint32_t cpu)=0
Interface call for private peripheral interrupts.
void makeAtomicResponse()
Definition: packet.hh:949
EndBitUnion(CTRL) protected A9GlobalTimer * parent
Pointer to parent class.
uint64_t Tick
Tick count type.
Definition: types.hh:63
const uint32_t intNum
Number of interrupt to cause/clear.
bool pendingInt
If an interrupt is currently pending.
Addr getAddr() const
Definition: packet.hh:726
uint64_t cmpVal
Value of the comparator.
void serialize(CheckpointOut &cp) const override
Serialize an object.
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
#define ULL(N)
uint64_t constant
Definition: types.hh:50
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:255
#define warn_once(...)
Definition: logging.hh:216
void counterAtCmpVal()
Called when the counter reaches the comparator.
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
Base class for ARM GIC implementations.
A9GlobalTimerParams Params
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:68
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:163
Bitfield< 27, 24 > gic
void schedule(Event &event, Tick when)
Definition: eventq.hh:744
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
void read(PacketPtr pkt, Addr daddr)
Handle read for a single timer.
This implements the Cortex A9-MPCore global timer from TRM rev r4p1.
bool rawInt
If timer has caused an interrupt.
uint32_t autoIncValue
Value to add to comparator when counter reaches comparator.
Bitfield< 0 > p
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:157

Generated on Fri Feb 28 2020 16:27:00 for gem5 by doxygen 1.8.13