gem5  v22.1.0.0
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
48 Intel8254Timer::writeControl(const CtrlReg data)
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
95 Intel8254Timer::startup()
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
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
virtual const char * description() const
Event description.
Counter element for PIT.
uint8_t read()
Read a count byte.
void setMode(int mode_val)
Set operational mode.
void serialize(const std::string &base, CheckpointOut &cp) const
Serialize this object to the given output stream.
uint16_t period
Interrupt period.
void unserialize(const std::string &base, CheckpointIn &cp)
Reconstruct the state of this object from a checkpoint.
void setBCD(int bcd_val)
Set count encoding.
void latchCount()
Latch the current count (if one is not already latched)
bool outputHigh()
Is the output high?
Tick offset
When to start ticking.
int currentCount()
Get the current count for this counter.
void setRW(int rw_val)
Set the read/write mode.
void write(const uint8_t data)
Write a count byte.
Programmable Interval Timer (Intel 8254)
Intel8254Timer(EventManager *em, const std::string &name)
Bitfield< 3, 1 > mode
const std::string & name() const
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
#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
#define warn_once(...)
Definition: logging.hh:250
Bitfield< 4, 0 > mode
Definition: misc_types.hh:74
Bitfield< 23, 0 > offset
Definition: types.hh:144
Bitfield< 10, 5 > event
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
Bitfield< 2 > em
Definition: misc.hh:607
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
double Counter
All counters are of 64-bit values.
Definition: types.hh:47
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
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition: types.cc:40
void unserialize(ThreadContext &tc, CheckpointIn &cp)
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition: types.cc:72
uint64_t Tick
Tick count type.
Definition: types.hh:58
void serialize(const ThreadContext &tc, CheckpointOut &cp)
Thread context serialization helpers.
const std::string & name()
Definition: trace.cc:49

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