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

Generated on Tue Jun 22 2021 15:28:28 for gem5 by doxygen 1.8.17