gem5  v20.1.0.0
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 
40 
41 #include "base/intmath.hh"
42 #include "base/trace.hh"
43 #include "debug/Checkpoint.hh"
44 #include "debug/Timer.hh"
45 #include "dev/arm/base_gic.hh"
46 #include "mem/packet.hh"
47 #include "mem/packet_access.hh"
48 
50  : BasicPioDevice(p, 0x1C), gic(p->gic),
51  global_timer(name() + ".globaltimer", this, p->int_num)
52 {
53 }
54 
55 A9GlobalTimer::Timer::Timer(std::string __name, A9GlobalTimer *_parent,
56  int int_num)
57  : _name(__name), parent(_parent), intNum(int_num), control(0x0),
58  rawInt(false), pendingInt(false), autoIncValue(0x0), cmpValEvent(this)
59 {
60 }
61 
62 Tick
64 {
65  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
66  assert(pkt->getSize() == 4);
67  Addr daddr = pkt->getAddr() - pioAddr;
68 
69  if (daddr < Timer::Size)
70  global_timer.read(pkt, daddr);
71  else
72  panic("Tried to read A9GlobalTimer at offset %#x that doesn't exist\n",
73  daddr);
74  pkt->makeAtomicResponse();
75  return pioDelay;
76 }
77 
78 uint64_t
80 {
81  return ticks / parent->clockPeriod() / (control.prescalar + 1) - 1;
82 }
83 
84 void
86 {
87  DPRINTF(Timer, "Reading from A9GlobalTimer at offset: %#x\n", daddr);
88  uint64_t time;
89 
90  switch(daddr) {
91  case CounterRegLow32:
92  time = getTimeCounterFromTicks(curTick());
93  DPRINTF(Timer, "-- returning lower 32-bits of counter: %u\n", time);
94  pkt->setLE<uint32_t>(time);
95  break;
96  case CounterRegHigh32:
97  time = getTimeCounterFromTicks(curTick());
98  time >>= 32;
99  DPRINTF(Timer, "-- returning upper 32-bits of counter: %u\n", time);
100  pkt->setLE<uint32_t>(time);
101  break;
102  case ControlReg:
103  pkt->setLE<uint32_t>(control);
104  break;
105  case IntStatusReg:
106  pkt->setLE<uint32_t>(rawInt);
107  break;
108  case CmpValRegLow32:
109  DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
110  cmpValEvent.when(), parent->clockPeriod(), control.prescalar);
111  if (cmpValEvent.scheduled()) {
112  time = getTimeCounterFromTicks(cmpValEvent.when() - curTick());
113  } else {
114  time = 0;
115  }
116  DPRINTF(Timer, "-- returning lower 32-bits of comparator: %u\n", time);
117  pkt->setLE<uint32_t>(time);
118  break;
119  case CmpValRegHigh32:
120  DPRINTF(Timer, "Event schedule for %d, clock=%d, prescale=%d\n",
121  cmpValEvent.when(), parent->clockPeriod(), control.prescalar);
122  if (cmpValEvent.scheduled()) {
123  time = getTimeCounterFromTicks(cmpValEvent.when() - curTick());
124  time >>= 32;
125  } else {
126  time = 0;
127  }
128  DPRINTF(Timer, "-- returning upper 32-bits of comparator: %u\n", time);
129  pkt->setLE<uint32_t>(time);
130  break;
131  case AutoIncrementReg:
132  pkt->setLE<uint32_t>(autoIncValue);
133  break;
134  default:
135  panic("Tried to read A9GlobalTimer at offset %#x\n", daddr);
136  break;
137  }
138  DPRINTF(Timer, "Reading %#x from A9GlobalTimer at offset: %#x\n",
139  pkt->getLE<uint32_t>(), daddr);
140 }
141 
142 Tick
144 {
145  assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize);
146  assert(pkt->getSize() == 4);
147  Addr daddr = pkt->getAddr() - pioAddr;
148  DPRINTF(Timer, "Writing to A9GlobalTimer at offset: %#x\n", daddr);
149 
150  warn_once("A9 Global Timer doesn't support banked per-cpu registers\n");
151 
152  if (daddr < Timer::Size)
153  global_timer.write(pkt, daddr);
154  else
155  panic("Tried to write A9GlobalTimer at offset %#x doesn't exist\n",
156  daddr);
157  pkt->makeAtomicResponse();
158  return pioDelay;
159 }
160 
161 void
163 {
164  DPRINTF(Timer, "Writing %#x to A9GlobalTimer at offset: %#x\n",
165  pkt->getLE<uint32_t>(), daddr);
166  switch (daddr) {
167  case CounterRegLow32:
168  case CounterRegHigh32:
169  DPRINTF(Timer, "Ignoring unsupported write to Global Timer Counter\n");
170  break;
171  case ControlReg:
172  bool old_enable;
173  bool old_cmpEnable;
174  old_enable = control.enable;
175  old_cmpEnable = control.cmpEnable;
176  control = pkt->getLE<uint32_t>();
177  if ((old_enable == 0) && control.enable)
178  restartCounter();
179  if ((old_cmpEnable == 0) && control.cmpEnable)
180  restartCounter();
181  break;
182  case IntStatusReg:
183  /* TODO: should check that '1' was written. */
184  rawInt = false;
185  if (pendingInt) {
186  pendingInt = false;
187  DPRINTF(Timer, "Clearing interrupt\n");
188  parent->gic->clearInt(intNum);
189  }
190  break;
191  case CmpValRegLow32:
192  cmpVal &= 0xFFFFFFFF00000000ULL;
193  cmpVal |= (uint64_t)pkt->getLE<uint32_t>();
194  break;
195  case CmpValRegHigh32:
196  cmpVal &= 0x00000000FFFFFFFFULL;
197  cmpVal |= ((uint64_t)pkt->getLE<uint32_t>() << 32);
198  break;
199  case AutoIncrementReg:
200  autoIncValue = pkt->getLE<uint32_t>();
201  break;
202  default:
203  panic("Tried to write A9GlobalTimer at offset %#x\n", daddr);
204  break;
205  }
206 }
207 
208 void
210 {
211  if (!control.enable)
212  return;
213  DPRINTF(Timer, "Restarting counter with value %#x\n", cmpVal);
214 
215  Tick time = parent->clockPeriod() * (control.prescalar + 1) * (cmpVal + 1);
216 
217  if (time < curTick()) {
218  DPRINTF(Timer, "-- Event time %#x < curTick %#x\n", time, curTick());
219  return;
220  }
221  if (cmpValEvent.scheduled()) {
222  DPRINTF(Timer, "-- Event was already schedule, de-scheduling\n");
223  parent->deschedule(cmpValEvent);
224  }
225  parent->schedule(cmpValEvent, time);
226  DPRINTF(Timer, "-- Scheduling new event for: %d\n", time);
227 }
228 
229 void
231 {
232  if (!control.enable)
233  return;
234 
235  DPRINTF(Timer, "Counter reached cmpVal\n");
236 
237  rawInt = true;
238  bool old_pending = pendingInt;
239  if (control.intEnable)
240  pendingInt = true;
241  if (pendingInt && !old_pending) {
242  DPRINTF(Timer, "-- Causing interrupt\n");
243  parent->gic->sendPPInt(intNum, 0); /* FIXME: cpuNum */
244  }
245 
246  if (control.autoIncrement == 0) // one-shot
247  return;
248 
249  cmpVal += (uint64_t)autoIncValue;
250  restartCounter();
251 }
252 
253 void
255 {
256  DPRINTF(Checkpoint, "Serializing Arm A9GlobalTimer\n");
257 
258  uint32_t control_serial = control;
259  SERIALIZE_SCALAR(control_serial);
260 
261  SERIALIZE_SCALAR(rawInt);
262  SERIALIZE_SCALAR(pendingInt);
263  SERIALIZE_SCALAR(cmpVal);
264  SERIALIZE_SCALAR(autoIncValue);
265 
266  bool is_in_event = cmpValEvent.scheduled();
267  SERIALIZE_SCALAR(is_in_event);
268 
269  Tick event_time;
270  if (is_in_event){
271  event_time = cmpValEvent.when();
272  SERIALIZE_SCALAR(event_time);
273  }
274 }
275 
276 void
278 {
279  DPRINTF(Checkpoint, "Unserializing Arm A9GlobalTimer\n");
280 
281  uint32_t control_serial;
282  UNSERIALIZE_SCALAR(control_serial);
283  control = control_serial;
284 
285  UNSERIALIZE_SCALAR(rawInt);
286  UNSERIALIZE_SCALAR(pendingInt);
287  UNSERIALIZE_SCALAR(cmpVal);
288  UNSERIALIZE_SCALAR(autoIncValue);
289 
290  bool is_in_event;
291  UNSERIALIZE_SCALAR(is_in_event);
292 
293  Tick event_time;
294  if (is_in_event){
295  UNSERIALIZE_SCALAR(event_time);
296  parent->schedule(cmpValEvent, event_time);
297  }
298 }
299 
300 void
302 {
304 }
305 
306 void
308 {
310 }
311 
313 A9GlobalTimerParams::create()
314 {
315  return new A9GlobalTimer(this);
316 }
A9GlobalTimer::Params
A9GlobalTimerParams Params
Definition: timer_a9global.hh:145
Packet::makeAtomicResponse
void makeAtomicResponse()
Definition: packet.hh:1016
A9GlobalTimer::read
Tick read(PacketPtr pkt) override
Handle a read to the device.
Definition: timer_a9global.cc:63
BasicPioDevice::pioAddr
Addr pioAddr
Address that the device listens to.
Definition: io_device.hh:154
A9GlobalTimer::Timer::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: timer_a9global.cc:277
A9GlobalTimer::unserialize
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: timer_a9global.cc:307
UNSERIALIZE_SCALAR
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:797
Packet::getAddr
Addr getAddr() const
Definition: packet.hh:754
warn_once
#define warn_once(...)
Definition: logging.hh:243
A9GlobalTimer::write
Tick write(PacketPtr pkt) override
Handle a write to the device.
Definition: timer_a9global.cc:143
A9GlobalTimer
Definition: timer_a9global.hh:52
base_gic.hh
Tick
uint64_t Tick
Tick count type.
Definition: types.hh:63
A9GlobalTimer::Timer::read
void read(PacketPtr pkt, Addr daddr)
Handle read for a single timer.
Definition: timer_a9global.cc:85
Packet::getSize
unsigned getSize() const
Definition: packet.hh:764
A9GlobalTimer::Timer::Timer
Timer(std::string __name, A9GlobalTimer *parent, int int_num)
Definition: timer_a9global.cc:55
A9GlobalTimer::Timer::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: timer_a9global.cc:254
packet.hh
A9GlobalTimer::global_timer
Timer global_timer
Timer that does the actual work.
Definition: timer_a9global.hh:142
A9GlobalTimer::Timer::counterAtCmpVal
void counterAtCmpVal()
Called when the counter reaches the comparator.
Definition: timer_a9global.cc:230
cp
Definition: cprintf.cc:40
A9GlobalTimer::Timer::restartCounter
void restartCounter()
Restart the counter ticking.
Definition: timer_a9global.cc:209
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
A9GlobalTimer::Timer::prescalar
Bitfield< 15, 8 > prescalar
Definition: timer_a9global.hh:80
BasicPioDevice::pioSize
Addr pioSize
Size that the device's address range.
Definition: io_device.hh:157
A9GlobalTimer::Timer::Size
@ Size
Definition: timer_a9global.hh:70
Addr
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
name
const std::string & name()
Definition: trace.cc:50
SERIALIZE_SCALAR
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:790
packet_access.hh
A9GlobalTimer::Timer::write
void write(PacketPtr pkt, Addr daddr)
Handle write for a single timer.
Definition: timer_a9global.cc:162
A9GlobalTimer::Timer::getTimeCounterFromTicks
uint64_t getTimeCounterFromTicks(Tick ticks)
Convert a number of ticks into the time counter format.
Definition: timer_a9global.cc:79
Packet::getLE
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
Definition: packet_access.hh:75
A9GlobalTimer::serialize
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: timer_a9global.cc:301
Packet
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:257
ArmISA::gic
Bitfield< 27, 24 > gic
Definition: miscregs_types.hh:171
BasicPioDevice
Definition: io_device.hh:150
A9GlobalTimer::Timer
Definition: timer_a9global.hh:55
BasicPioDevice::pioDelay
Tick pioDelay
Delay that the device experinces on an access.
Definition: io_device.hh:160
Packet::setLE
void setLE(T v)
Set the value in the data pointer to v as little endian.
Definition: packet_access.hh:105
CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:63
trace.hh
MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:323
intmath.hh
CheckpointIn
Definition: serialize.hh:67
A9GlobalTimer::A9GlobalTimer
A9GlobalTimer(Params *p)
The constructor for RealView just registers itself with the MMU.
Definition: timer_a9global.cc:49
ULL
#define ULL(N)
uint64_t constant
Definition: types.hh:50
timer_a9global.hh
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:171
curTick
Tick curTick()
The current simulated tick.
Definition: core.hh:45

Generated on Wed Sep 30 2020 14:02:10 for gem5 by doxygen 1.8.17