gem5 v24.0.0.0
Loading...
Searching...
No Matches
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
30
31#include "base/logging.hh"
32#include "debug/Intel8254Timer.hh"
33#include "sim/core.hh"
34#include "sim/cur_tick.hh"
35
36namespace 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
47void
48Intel8254Timer::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
76void
77Intel8254Timer::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
85void
86Intel8254Timer::unserialize(const std::string &base, CheckpointIn &cp)
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
94void
95Intel8254Timer::startup()
96{
97 counters[0].startup();
98 counters[1].startup();
99 counters[2].startup();
100}
101
102Intel8254Timer::Counter::Counter(Intel8254Timer *p,
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
112void
113Intel8254Timer::Counter::latchCount()
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
123int
124Intel8254Timer::Counter::currentCount()
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
137uint8_t
138Intel8254Timer::Counter::read()
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
171void
172Intel8254Timer::Counter::write(const uint8_t data)
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
203void
204Intel8254Timer::Counter::setRW(int rw_val)
205{
206 if (rw_val != TwoPhase)
207 panic("Only LSB/MSB read/write is implemented.\n");
208}
209
210void
211Intel8254Timer::Counter::setMode(int mode_val)
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
220void
221Intel8254Timer::Counter::setBCD(int bcd_val)
222{
223 if (bcd_val)
224 panic("PITimer does not implement BCD counts.\n");
225}
226
227bool
228Intel8254Timer::Counter::outputHigh()
229{
230 return output_high;
231}
232
233void
234Intel8254Timer::Counter::serialize(
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
252void
253Intel8254Timer::Counter::unserialize(const std::string &base, CheckpointIn &cp)
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
270void
271Intel8254Timer::Counter::startup()
272{
273 running = true;
274 if ((period > 0) && (offset > 0))
275 {
276 parent->schedule(event, curTick() + offset);
277 }
278}
279
280Intel8254Timer::Counter::CounterEvent::CounterEvent(Counter* c_ptr)
281{
282 interval = (Tick)(sim_clock::as_float::s / 1193180.0);
283 counter = c_ptr;
284}
285
286void
287Intel8254Timer::Counter::CounterEvent::process()
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
303void
304Intel8254Timer::Counter::CounterEvent::setTo(int clocks)
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
313int
314Intel8254Timer::Counter::CounterEvent::clocksLeft()
315{
316 if (!scheduled())
317 return -1;
318 return (when() - curTick() + interval - 1) / interval;
319}
320
321const char *
322Intel8254Timer::Counter::CounterEvent::description() const
323{
324 return "Intel 8254 Interval timer";
325}
326
327Tick
328Intel8254Timer::Counter::CounterEvent::getInterval()
329{
330 return interval;
331}
332
333} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
Counter element for PIT.
uint16_t period
Interrupt period.
bool output_high
Output goes high when the counter reaches zero.
Tick offset
When to start ticking.
Programmable Interval Timer (Intel 8254)
const std::string & name() const
Intel8254Timer(EventManager *em, const std::string &name)
Bitfield< 3, 1 > mode
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:79
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
#define warn_once(...)
Definition logging.hh:260
Bitfield< 4, 0 > mode
Definition misc_types.hh:74
Bitfield< 23, 0 > offset
Definition types.hh:144
Bitfield< 10, 5 > event
Bitfield< 51, 12 > base
Definition pagetable.hh:141
Bitfield< 2 > em
Definition misc.hh:617
double s
These variables equal the number of ticks in the unit of time they're named after in a double.
Definition core.cc:51
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
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 paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition types.cc:72
uint64_t Tick
Tick count type.
Definition types.hh:58
const std::string & name()
Definition trace.cc:48

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0