gem5  v22.0.0.1
intel_8254_timer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004, 2005
3  * The Regents of The University of Michigan
4  * All Rights Reserved
5  *
6  * This code is part of the M5 simulator.
7  *
8  * Permission is granted to use, copy, create derivative works and
9  * redistribute this software and such derivative works for any
10  * purpose, so long as the copyright notice above, this grant of
11  * permission, and the disclaimer below appear in all copies made; and
12  * so long as the name of The University of Michigan is not used in
13  * any advertising or publicity pertaining to the use or distribution
14  * of this software without specific, written prior authorization.
15  *
16  * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
17  * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
18  * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
19  * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
22  * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
23  * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
24  * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
25  * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
26  * DAMAGES.
27  */
28 
29 #include "dev/intel_8254_timer.hh"
30 
31 #include "base/logging.hh"
32 #include "debug/Intel8254Timer.hh"
33 #include "sim/core.hh"
34 #include "sim/cur_tick.hh"
35 
36 namespace gem5
37 {
38 
40  EventManager(em), _name(name), counters{{
41  {this, name + ".counter0", 0},
42  {this, name + ".counter1", 1},
43  {this, name + ".counter2", 2}
44  }}
45 {}
46 
47 void
49 {
50  int sel = data.sel;
51 
52  if (sel == ReadBackCommand) {
53  ReadBackCommandVal rb_val = static_cast<uint8_t>(data);
54 
55  panic_if(!rb_val.status,
56  "Latching the PIT status byte is not implemented.");
57 
58  if (!rb_val.count) {
59  for (auto &counter: counters) {
60  if (bits((uint8_t)rb_val.select, counter.index()))
61  counter.latchCount();
62  }
63  }
64  return;
65  }
66 
67  if (data.rw == LatchCommand) {
68  counters[sel].latchCount();
69  } else {
70  counters[sel].setRW(data.rw);
71  counters[sel].setMode(data.mode);
72  counters[sel].setBCD(data.bcd);
73  }
74 }
75 
76 void
77 Intel8254Timer::serialize(const std::string &base, CheckpointOut &cp) const
78 {
79  // serialize the counters
80  counters[0].serialize(base + ".counter0", cp);
81  counters[1].serialize(base + ".counter1", cp);
82  counters[2].serialize(base + ".counter2", cp);
83 }
84 
85 void
87 {
88  // unserialze the counters
89  counters[0].unserialize(base + ".counter0", cp);
90  counters[1].unserialize(base + ".counter1", cp);
91  counters[2].unserialize(base + ".counter2", cp);
92 }
93 
94 void
96 {
97  counters[0].startup();
98  counters[1].startup();
99  counters[2].startup();
100 }
101 
103  const std::string &name, unsigned int _num)
104  : _name(name), num(_num), event(this), running(false),
105  initial_count(0), latched_count(0), period(0), mode(0),
106  output_high(false), latch_on(false), read_byte(LSB),
107  write_byte(LSB), parent(p)
108 {
109  offset = period * event.getInterval();
110 }
111 
112 void
114 {
115  // behave like a real latch
116  if (!latch_on) {
117  latch_on = true;
118  read_byte = LSB;
119  latched_count = currentCount();
120  }
121 }
122 
123 int
125 {
126  int clocks = event.clocksLeft();
127  if (clocks == -1) {
128  warn_once("Reading current count from inactive timer.\n");
129  return 0;
130  }
131  if (mode == RateGen || mode == SquareWave)
132  return clocks + 1;
133  else
134  return clocks;
135 }
136 
137 uint8_t
139 {
140  if (latch_on) {
141  switch (read_byte) {
142  case LSB:
143  read_byte = MSB;
144  return (uint8_t)latched_count;
145  break;
146  case MSB:
147  read_byte = LSB;
148  latch_on = false;
149  return latched_count >> 8;
150  break;
151  default:
152  panic("Shouldn't be here");
153  }
154  } else {
155  uint16_t count = currentCount();
156  switch (read_byte) {
157  case LSB:
158  read_byte = MSB;
159  return (uint8_t)count;
160  break;
161  case MSB:
162  read_byte = LSB;
163  return count >> 8;
164  break;
165  default:
166  panic("Shouldn't be here");
167  }
168  }
169 }
170 
171 void
173 {
174  switch (write_byte) {
175  case LSB:
176  initial_count = (initial_count & 0xFF00) | data;
177 
178  if (event.scheduled())
179  parent->deschedule(event);
180  output_high = false;
181  write_byte = MSB;
182  break;
183 
184  case MSB:
185  initial_count = (initial_count & 0x00FF) | (data << 8);
186  // In the RateGen or SquareWave modes, the timer wraps around and
187  // triggers on a value of 1, not 0.
188  if (mode == RateGen || mode == SquareWave)
189  period = initial_count - 1;
190  else
191  period = initial_count;
192 
193  offset = period * event.getInterval();
194 
195  if (running && (period > 0))
196  event.setTo(period);
197 
198  write_byte = LSB;
199  break;
200  }
201 }
202 
203 void
205 {
206  if (rw_val != TwoPhase)
207  panic("Only LSB/MSB read/write is implemented.\n");
208 }
209 
210 void
212 {
213  if (mode_val != InitTc && mode_val != RateGen &&
214  mode_val != SquareWave)
215  panic("PIT mode %#x is not implemented: \n", mode_val);
216 
217  mode = mode_val;
218 }
219 
220 void
222 {
223  if (bcd_val)
224  panic("PITimer does not implement BCD counts.\n");
225 }
226 
227 bool
229 {
230  return output_high;
231 }
232 
233 void
235  const std::string &base, CheckpointOut &cp) const
236 {
237  paramOut(cp, base + ".initial_count", initial_count);
238  paramOut(cp, base + ".latched_count", latched_count);
239  paramOut(cp, base + ".period", period);
240  paramOut(cp, base + ".mode", mode);
241  paramOut(cp, base + ".output_high", output_high);
242  paramOut(cp, base + ".latch_on", latch_on);
243  paramOut(cp, base + ".read_byte", read_byte);
244  paramOut(cp, base + ".write_byte", write_byte);
245 
246  Tick event_tick_offset = 0;
247  if (event.scheduled())
248  event_tick_offset = event.when() - curTick();
249  paramOut(cp, base + ".event_tick_offset", event_tick_offset);
250 }
251 
252 void
254 {
255  paramIn(cp, base + ".initial_count", initial_count);
256  paramIn(cp, base + ".latched_count", latched_count);
257  paramIn(cp, base + ".period", period);
258  paramIn(cp, base + ".mode", mode);
259  paramIn(cp, base + ".output_high", output_high);
260  paramIn(cp, base + ".latch_on", latch_on);
261  paramIn(cp, base + ".read_byte", read_byte);
262  paramIn(cp, base + ".write_byte", write_byte);
263 
264  Tick event_tick_offset = 0;
265  assert(!event.scheduled());
266  paramIn(cp, base + ".event_tick_offset", event_tick_offset);
267  offset = event_tick_offset;
268 }
269 
270 void
272 {
273  running = true;
274  if ((period > 0) && (offset > 0))
275  {
276  parent->schedule(event, curTick() + offset);
277  }
278 }
279 
281 {
282  interval = (Tick)(sim_clock::as_float::s / 1193180.0);
283  counter = c_ptr;
284 }
285 
286 void
288 {
289  switch (counter->mode) {
290  case InitTc:
291  counter->output_high = true;
292  break;
293  case RateGen:
294  case SquareWave:
295  setTo(counter->period);
296  break;
297  default:
298  panic("Unimplemented PITimer mode.\n");
299  }
300  counter->parent->counterInterrupt(counter->num);
301 }
302 
303 void
305 {
306  if (clocks == 0)
307  panic("Timer can't be set to go off instantly.\n");
308  DPRINTF(Intel8254Timer, "Timer set to curTick() + %d\n",
309  clocks * interval);
310  counter->parent->schedule(this, curTick() + clocks * interval);
311 }
312 
313 int
315 {
316  if (!scheduled())
317  return -1;
318  return (when() - curTick() + interval - 1) / interval;
319 }
320 
321 const char *
323 {
324  return "Intel 8254 Interval timer";
325 }
326 
327 Tick
329 {
330  return interval;
331 }
332 
333 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
data
const char data[]
Definition: circlebuf.test.cc:48
gem5::Intel8254Timer::Counter::latchCount
void latchCount()
Latch the current count (if one is not already latched)
Definition: intel_8254_timer.cc:113
gem5::Intel8254Timer::mode
Bitfield< 3, 1 > mode
Definition: intel_8254_timer.hh:53
gem5::Intel8254Timer
Programmable Interval Timer (Intel 8254)
Definition: intel_8254_timer.hh:47
warn_once
#define warn_once(...)
Definition: logging.hh:250
gem5::Intel8254Timer::RateGen
@ RateGen
Definition: intel_8254_timer.hh:87
gem5::Intel8254Timer::Counter::CounterEvent::process
void process()
Event process.
Definition: intel_8254_timer.cc:287
gem5::Intel8254Timer::Counter::currentCount
int currentCount()
Get the current count for this counter.
Definition: intel_8254_timer.cc:124
gem5::CheckpointIn
Definition: serialize.hh:68
gem5::MipsISA::event
Bitfield< 10, 5 > event
Definition: pra_constants.hh:300
cur_tick.hh
gem5::Intel8254Timer::startup
void startup()
Start ticking.
Definition: intel_8254_timer.cc:95
gem5::Intel8254Timer::LatchCommand
@ LatchCommand
Definition: intel_8254_timer.hh:77
gem5::Intel8254Timer::Counter
Counter element for PIT.
Definition: intel_8254_timer.hh:94
gem5::X86ISA::base
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
gem5::Intel8254Timer::Counter::CounterEvent::CounterEvent
CounterEvent(Counter *)
Definition: intel_8254_timer.cc:280
gem5::Intel8254Timer::counters
std::array< Counter, 3 > counters
PIT has three seperate counters.
Definition: intel_8254_timer.hh:216
gem5::X86ISA::em
Bitfield< 2 > em
Definition: misc.hh:602
gem5::EventManager
Definition: eventq.hh:987
gem5::VegaISA::p
Bitfield< 54 > p
Definition: pagetable.hh:70
gem5::Intel8254Timer::Counter::CounterEvent::description
virtual const char * description() const
Event description.
Definition: intel_8254_timer.cc:322
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::Intel8254Timer::TwoPhase
@ TwoPhase
Definition: intel_8254_timer.hh:80
gem5::Intel8254Timer::Counter::setMode
void setMode(int mode_val)
Set operational mode.
Definition: intel_8254_timer.cc:211
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
gem5::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:76
gem5::Intel8254Timer::name
const std::string & name() const
Definition: intel_8254_timer.hh:213
name
const std::string & name()
Definition: trace.cc:49
gem5::Intel8254Timer::serialize
void serialize(const std::string &base, CheckpointOut &cp) const
Serialize this object to the given output stream.
Definition: intel_8254_timer.cc:77
intel_8254_timer.hh
gem5::Intel8254Timer::Counter::CounterEvent::clocksLeft
int clocksLeft()
Definition: intel_8254_timer.cc:314
gem5::Intel8254Timer::Counter::CounterEvent::setTo
void setTo(int clocks)
Definition: intel_8254_timer.cc:304
gem5::Intel8254Timer::Counter::read
uint8_t read()
Read a count byte.
Definition: intel_8254_timer.cc:138
panic_if
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
gem5::Intel8254Timer::count
Bitfield< 5 > count
Definition: intel_8254_timer.hh:59
gem5::Intel8254Timer::Counter::Counter
Counter(Intel8254Timer *p, const std::string &name, unsigned int num)
Definition: intel_8254_timer.cc:102
gem5::paramOut
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
gem5::Intel8254Timer::Counter::CounterEvent::getInterval
Tick getInterval()
Definition: intel_8254_timer.cc:328
gem5::Intel8254Timer::Counter::startup
void startup()
Start ticking.
Definition: intel_8254_timer.cc:271
gem5::Intel8254Timer::InitTc
@ InitTc
Definition: intel_8254_timer.hh:85
core.hh
gem5::paramIn
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
gem5::Intel8254Timer::SquareWave
@ SquareWave
Definition: intel_8254_timer.hh:88
gem5::Intel8254Timer::Counter::unserialize
void unserialize(const std::string &base, CheckpointIn &cp)
Reconstruct the state of this object from a checkpoint.
Definition: intel_8254_timer.cc:253
logging.hh
gem5::Intel8254Timer::Counter::setRW
void setRW(int rw_val)
Set the read/write mode.
Definition: intel_8254_timer.cc:204
gem5::Intel8254Timer::Intel8254Timer
Intel8254Timer(EventManager *em, const std::string &name)
Definition: intel_8254_timer.cc:39
gem5::Intel8254Timer::Counter::serialize
void serialize(const std::string &base, CheckpointOut &cp) const
Serialize this object to the given output stream.
Definition: intel_8254_timer.cc:234
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::Intel8254Timer::Counter::outputHigh
bool outputHigh()
Is the output high?
Definition: intel_8254_timer.cc:228
gem5::Intel8254Timer::sel
sel
Definition: intel_8254_timer.hh:51
gem5::Intel8254Timer::unserialize
void unserialize(const std::string &base, CheckpointIn &cp)
Reconstruct the state of this object from a checkpoint.
Definition: intel_8254_timer.cc:86
gem5::Intel8254Timer::Counter::period
uint16_t period
Interrupt period.
Definition: intel_8254_timer.hh:140
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: gpu_translation_state.hh:37
gem5::Intel8254Timer::writeControl
void writeControl(const CtrlReg data)
Write control word.
Definition: intel_8254_timer.cc:48
gem5::Intel8254Timer::Counter::setBCD
void setBCD(int bcd_val)
Set count encoding.
Definition: intel_8254_timer.cc:221
gem5::Intel8254Timer::Counter::write
void write(const uint8_t data)
Write a count byte.
Definition: intel_8254_timer.cc:172
gem5::Intel8254Timer::Counter::offset
Tick offset
When to start ticking.
Definition: intel_8254_timer.hh:143
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
gem5::sim_clock::as_float::s
double s
These variables equal the number of ticks in the unit of time they're named after in a double.
Definition: core.cc:53
gem5::ArmISA::mode
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74

Generated on Sat Jun 18 2022 08:12:24 for gem5 by doxygen 1.8.17