lc3_ensemble/sim/device/
timer.rs1use std::ops::{Bound, RangeBounds};
2
3use rand::Rng;
4
5use super::ExternalDevice;
6
7#[derive(Clone, Copy)]
8struct SampleRange {
9 start: u32,
10 end: u32,
11 end_incl: bool
12}
13impl SampleRange {
14 fn new(r: impl RangeBounds<u32>) -> Self {
15 let start = match r.start_bound() {
16 Bound::Included(&s) => s,
17 Bound::Excluded(&s) => s.checked_add(1).expect("(Bound::Excluded(u32::MAX), _) is not an acceptable range"),
18 Bound::Unbounded => 0,
19 };
20 let (end, end_incl) = match r.end_bound() {
21 Bound::Included(&s) => (s, true),
22 Bound::Excluded(&s) => (s, false),
23 Bound::Unbounded => (u32::MAX, true),
24 };
25
26 Self { start, end, end_incl }
27 }
28}
29impl std::fmt::Debug for SampleRange {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match self {
32 SampleRange { start, end, end_incl: true } => (start..=end).fmt(f),
33 SampleRange { start, end, end_incl: false } => (start..end).fmt(f),
34 }
35 }
36}
37impl RangeBounds<u32> for SampleRange {
38 fn start_bound(&self) -> Bound<&u32> {
39 Bound::Included(&self.start)
40 }
41
42 fn end_bound(&self) -> Bound<&u32> {
43 match self.end_incl {
44 true => Bound::Included(&self.end),
45 false => Bound::Excluded(&self.end),
46 }
47 }
48}
49
50#[derive(Debug)]
55pub struct TimerDevice {
56 generator: Box<rand::rngs::StdRng>,
57 range: SampleRange,
58 time: u32,
59
60 pub vect: u8,
62 pub priority: u8,
66
67 pub enabled: bool,
69}
70impl TimerDevice {
71 pub fn new(seed: Option<u64>, range: impl RangeBounds<u32>, vect: u8, priority: u8) -> Self {
77 use rand::SeedableRng;
78 use rand::rngs::StdRng;
79
80 let generator = match seed {
81 Some(s) => StdRng::seed_from_u64(s),
82 None => StdRng::from_os_rng(),
83 };
84
85 let mut timer = Self {
86 generator: Box::new(generator),
87 range: SampleRange::new(range),
88 time: 0,
89 vect,
90 priority,
91 enabled: false
92 };
93 timer.reset_remaining();
94
95 timer
96 }
97
98 pub fn get_range(&self) -> impl RangeBounds<u32> {
100 self.range
101 }
102 pub fn set_range(&mut self, r: impl RangeBounds<u32>) -> &mut Self {
104 self.range = SampleRange::new(r);
105 self
106 }
107 pub fn set_exact(&mut self, n: u32) -> &mut Self {
109 self.set_range(n..=n)
110 }
111
112 pub fn get_remaining(&self) -> u32 {
114 self.time
115 }
116 pub fn reset_remaining(&mut self) {
118 self.time = self.try_generate_time();
119 }
120 fn try_generate_time(&mut self) -> u32 {
122 match self.range {
123 SampleRange { start, end, end_incl: true } => self.generator.random_range(start..=end),
124 SampleRange { start, end, end_incl: false } => self.generator.random_range(start..end),
125 }
126 }
127}
128impl Default for TimerDevice {
129 fn default() -> Self {
140 Self::new(None, 50..=50, 0x81, 0b100)
141 }
142}
143impl ExternalDevice for TimerDevice {
144 fn io_read(&mut self, _addr: u16, _effectful: bool) -> Option<u16> {
145 None
146 }
147
148 fn io_write(&mut self, _addr: u16, _data: u16) -> bool {
149 false
150 }
151
152 fn io_reset(&mut self) {
153 self.time = self.try_generate_time();
154 }
155 fn poll_interrupt(&mut self) -> Option<super::Interrupt> {
156 if !self.enabled { return None };
157
158 match self.time {
159 0 => {
160 self.reset_remaining();
161 None
162 },
163 1 => {
164 self.time = 0;
165 Some(super::Interrupt::vectored(self.vect, self.priority))
166 },
167 _ => {
168 self.time -= 1;
169 None
170 }
171 }
172 }
173}