gem5  v21.1.0.2
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  Counter *counter0, Counter *counter1, Counter *counter2) :
41  EventManager(em), _name(name)
42 {
43  counter[0] = counter0;
44  counter[1] = counter1;
45  counter[2] = counter2;
46 }
47 
49  EventManager(em), _name(name)
50 {
51  counter[0] = new Counter(this, name + ".counter0", 0);
52  counter[1] = new Counter(this, name + ".counter1", 1);
53  counter[2] = new Counter(this, name + ".counter2", 2);
54 }
55 
56 void
58 {
59  int sel = data.sel;
60 
61  if (sel == ReadBackCommand)
62  panic("PITimer Read-Back Command is not implemented.\n");
63 
64  if (data.rw == LatchCommand)
66  else {
67  counter[sel]->setRW(data.rw);
68  counter[sel]->setMode(data.mode);
69  counter[sel]->setBCD(data.bcd);
70  }
71 }
72 
73 void
74 Intel8254Timer::serialize(const std::string &base, CheckpointOut &cp) const
75 {
76  // serialize the counters
77  counter[0]->serialize(base + ".counter0", cp);
78  counter[1]->serialize(base + ".counter1", cp);
79  counter[2]->serialize(base + ".counter2", cp);
80 }
81 
82 void
84 {
85  // unserialze the counters
86  counter[0]->unserialize(base + ".counter0", cp);
87  counter[1]->unserialize(base + ".counter1", cp);
88  counter[2]->unserialize(base + ".counter2", cp);
89 }
90 
91 void
93 {
94  counter[0]->startup();
95  counter[1]->startup();
96  counter[2]->startup();
97 }
98 
100  const std::string &name, unsigned int _num)
101  : _name(name), num(_num), event(this), running(false),
102  initial_count(0), latched_count(0), period(0), mode(0),
103  output_high(false), latch_on(false), read_byte(LSB),
104  write_byte(LSB), parent(p)
105 {
106  offset = period * event.getInterval();
107 }
108 
109 void
111 {
112  // behave like a real latch
113  if (!latch_on) {
114  latch_on = true;
115  read_byte = LSB;
116  latched_count = currentCount();
117  }
118 }
119 
120 int
122 {
123  int clocks = event.clocksLeft();
124  if (clocks == -1) {
125  warn_once("Reading current count from inactive timer.\n");
126  return 0;
127  }
128  if (mode == RateGen || mode == SquareWave)
129  return clocks + 1;
130  else
131  return clocks;
132 }
133 
134 uint8_t
136 {
137  if (latch_on) {
138  switch (read_byte) {
139  case LSB:
140  read_byte = MSB;
141  return (uint8_t)latched_count;
142  break;
143  case MSB:
144  read_byte = LSB;
145  latch_on = false;
146  return latched_count >> 8;
147  break;
148  default:
149  panic("Shouldn't be here");
150  }
151  } else {
152  uint16_t count = currentCount();
153  switch (read_byte) {
154  case LSB:
155  read_byte = MSB;
156  return (uint8_t)count;
157  break;
158  case MSB:
159  read_byte = LSB;
160  return count >> 8;
161  break;
162  default:
163  panic("Shouldn't be here");
164  }
165  }
166 }
167 
168 void
170 {
171  switch (write_byte) {
172  case LSB:
173  initial_count = (initial_count & 0xFF00) | data;
174 
175  if (event.scheduled())
176  parent->deschedule(event);
177  output_high = false;
178  write_byte = MSB;
179  break;
180 
181  case MSB:
182  initial_count = (initial_count & 0x00FF) | (data << 8);
183  // In the RateGen or SquareWave modes, the timer wraps around and
184  // triggers on a value of 1, not 0.
185  if (mode == RateGen || mode == SquareWave)
186  period = initial_count - 1;
187  else
188  period = initial_count;
189 
190  offset = period * event.getInterval();
191 
192  if (running && (period > 0))
193  event.setTo(period);
194 
195  write_byte = LSB;
196  break;
197  }
198 }
199 
200 void
202 {
203  if (rw_val != TwoPhase)
204  panic("Only LSB/MSB read/write is implemented.\n");
205 }
206 
207 void
209 {
210  if (mode_val != InitTc && mode_val != RateGen &&
211  mode_val != SquareWave)
212  panic("PIT mode %#x is not implemented: \n", mode_val);
213 
214  mode = mode_val;
215 }
216 
217 void
219 {
220  if (bcd_val)
221  panic("PITimer does not implement BCD counts.\n");
222 }
223 
224 bool
226 {
227  return output_high;
228 }
229 
230 void
232  const std::string &base, CheckpointOut &cp) const
233 {
234  paramOut(cp, base + ".initial_count", initial_count);
235  paramOut(cp, base + ".latched_count", latched_count);
236  paramOut(cp, base + ".period", period);
237  paramOut(cp, base + ".mode", mode);
238  paramOut(cp, base + ".output_high", output_high);
239  paramOut(cp, base + ".latch_on", latch_on);
240  paramOut(cp, base + ".read_byte", read_byte);
241  paramOut(cp, base + ".write_byte", write_byte);
242 
243  Tick event_tick_offset = 0;
244  if (event.scheduled())
245  event_tick_offset = event.when() - curTick();
246  paramOut(cp, base + ".event_tick_offset", event_tick_offset);
247 }
248 
249 void
251 {
252  paramIn(cp, base + ".initial_count", initial_count);
253  paramIn(cp, base + ".latched_count", latched_count);
254  paramIn(cp, base + ".period", period);
255  paramIn(cp, base + ".mode", mode);
256  paramIn(cp, base + ".output_high", output_high);
257  paramIn(cp, base + ".latch_on", latch_on);
258  paramIn(cp, base + ".read_byte", read_byte);
259  paramIn(cp, base + ".write_byte", write_byte);
260 
261  Tick event_tick_offset = 0;
262  assert(!event.scheduled());
263  paramIn(cp, base + ".event_tick_offset", event_tick_offset);
264  offset = event_tick_offset;
265 }
266 
267 void
269 {
270  running = true;
271  if ((period > 0) && (offset > 0))
272  {
273  parent->schedule(event, curTick() + offset);
274  }
275 }
276 
278 {
279  interval = (Tick)(sim_clock::as_float::s / 1193180.0);
280  counter = c_ptr;
281 }
282 
283 void
285 {
286  switch (counter->mode) {
287  case InitTc:
288  counter->output_high = true;
289  break;
290  case RateGen:
291  case SquareWave:
292  setTo(counter->period);
293  break;
294  default:
295  panic("Unimplemented PITimer mode.\n");
296  }
298 }
299 
300 void
302 {
303  if (clocks == 0)
304  panic("Timer can't be set to go off instantly.\n");
305  DPRINTF(Intel8254Timer, "Timer set to curTick() + %d\n",
306  clocks * interval);
307  counter->parent->schedule(this, curTick() + clocks * interval);
308 }
309 
310 int
312 {
313  if (!scheduled())
314  return -1;
315  return (when() - curTick() + interval - 1) / interval;
316 }
317 
318 const char *
320 {
321  return "Intel 8254 Interval timer";
322 }
323 
324 Tick
326 {
327  return interval;
328 }
329 
330 } // namespace gem5
gem5::curTick
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
gem5::Counter
int64_t Counter
Statistics counter type.
Definition: types.hh:53
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:110
gem5::Intel8254Timer::mode
Bitfield< 3, 1 > mode
Definition: intel_8254_timer.hh:52
gem5::Intel8254Timer::Counter::mode
uint8_t mode
Current mode of operation.
Definition: intel_8254_timer.hh:135
gem5::Intel8254Timer
Programmable Interval Timer (Intel 8254)
Definition: intel_8254_timer.hh:46
warn_once
#define warn_once(...)
Definition: logging.hh:249
gem5::Intel8254Timer::RateGen
@ RateGen
Definition: intel_8254_timer.hh:76
gem5::Intel8254Timer::Counter::CounterEvent::process
void process()
Event process.
Definition: intel_8254_timer.cc:284
gem5::Intel8254Timer::Counter::currentCount
int currentCount()
Get the current count for this counter.
Definition: intel_8254_timer.cc:121
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:92
gem5::Intel8254Timer::LatchCommand
@ LatchCommand
Definition: intel_8254_timer.hh:66
gem5::EventManager::schedule
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
gem5::Intel8254Timer::Counter
Counter element for PIT.
Definition: intel_8254_timer.hh:83
gem5::X86ISA::base
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
gem5::Intel8254Timer::Counter::CounterEvent::CounterEvent
CounterEvent(Counter *)
Definition: intel_8254_timer.cc:277
gem5::Intel8254Timer::Counter::parent
Intel8254Timer * parent
Pointer to container.
Definition: intel_8254_timer.hh:150
gem5::X86ISA::em
Bitfield< 2 > em
Definition: misc.hh:608
gem5::EventManager
Definition: eventq.hh:987
gem5::Intel8254Timer::Counter::CounterEvent::description
virtual const char * description() const
Event description.
Definition: intel_8254_timer.cc:319
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:186
gem5::X86ISA::count
count
Definition: misc.hh:709
gem5::Intel8254Timer::TwoPhase
@ TwoPhase
Definition: intel_8254_timer.hh:69
gem5::Intel8254Timer::Counter::setMode
void setMode(int mode_val)
Set operational mode.
Definition: intel_8254_timer.cc:208
gem5::MipsISA::p
Bitfield< 0 > p
Definition: pra_constants.hh:326
gem5::Tick
uint64_t Tick
Tick count type.
Definition: types.hh:58
gem5::Intel8254Timer::Counter::num
unsigned int num
Definition: intel_8254_timer.hh:115
gem5::Intel8254Timer::Intel8254Timer
Intel8254Timer(EventManager *em, const std::string &name, Counter *counter0, Counter *counter1, Counter *counter2)
Definition: intel_8254_timer.cc:39
gem5::Intel8254Timer::counterInterrupt
virtual void counterInterrupt(unsigned int num)
Definition: intel_8254_timer.hh:206
gem5::ArmISA::offset
Bitfield< 23, 0 > offset
Definition: types.hh:144
core.hh
gem5::Intel8254Timer::name
const std::string & name() const
Definition: intel_8254_timer.hh:200
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:74
intel_8254_timer.hh
gem5::Intel8254Timer::Counter::CounterEvent::clocksLeft
int clocksLeft()
Definition: intel_8254_timer.cc:311
gem5::Intel8254Timer::Counter::CounterEvent::setTo
void setTo(int clocks)
Definition: intel_8254_timer.cc:301
gem5::Intel8254Timer::Counter::read
uint8_t read()
Read a count byte.
Definition: intel_8254_timer.cc:135
gem5::Intel8254Timer::Counter::Counter
Counter(Intel8254Timer *p, const std::string &name, unsigned int num)
Definition: intel_8254_timer.cc:99
gem5::Intel8254Timer::Counter::output_high
bool output_high
Output goes high when the counter reaches zero.
Definition: intel_8254_timer.hh:138
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:325
gem5::Intel8254Timer::Counter::startup
void startup()
Start ticking.
Definition: intel_8254_timer.cc:268
gem5::Intel8254Timer::InitTc
@ InitTc
Definition: intel_8254_timer.hh:74
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:77
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:250
logging.hh
gem5::Intel8254Timer::Counter::setRW
void setRW(int rw_val)
Set the read/write mode.
Definition: intel_8254_timer.cc:201
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:231
gem5::CheckpointOut
std::ostream CheckpointOut
Definition: serialize.hh:66
gem5::Intel8254Timer::Counter::outputHigh
bool outputHigh()
Is the output high?
Definition: intel_8254_timer.cc:225
gem5::Intel8254Timer::sel
sel
Definition: intel_8254_timer.hh:50
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:83
gem5::Intel8254Timer::Counter::period
uint16_t period
Interrupt period.
Definition: intel_8254_timer.hh:129
gem5
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Definition: decoder.cc:40
gem5::Intel8254Timer::counter
Counter * counter[3]
PIT has three seperate counters.
Definition: intel_8254_timer.hh:203
gem5::Intel8254Timer::writeControl
void writeControl(const CtrlReg data)
Write control word.
Definition: intel_8254_timer.cc:57
gem5::Intel8254Timer::Counter::setBCD
void setBCD(int bcd_val)
Set count encoding.
Definition: intel_8254_timer.cc:218
gem5::Intel8254Timer::Counter::write
void write(const uint8_t data)
Write a count byte.
Definition: intel_8254_timer.cc:169
gem5::Intel8254Timer::Counter::offset
Tick offset
When to start ticking.
Definition: intel_8254_timer.hh:132
panic
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:177
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:73

Generated on Tue Sep 21 2021 12:25:15 for gem5 by doxygen 1.8.17