1 #include <catch.hpp>
2 #include "../src/timer.h"
3 
4 struct TimerTestEnvironment {
5     Teakra::CoreTiming core_timing;
6     Teakra::Timer timer{core_timing};
7     int interrupt_counter = 0;
TimerTestEnvironmentTimerTestEnvironment8     TimerTestEnvironment() {
9         timer.SetInterruptHandler([&]() { interrupt_counter++; });
10     }
11 };
12 
13 TEST_CASE("Single mode", "[timer]") {
14     TimerTestEnvironment env;
15     env.timer.count_mode = Teakra::Timer::CountMode::Single;
16     env.timer.update_mmio = 1;
17     env.timer.start_low = 5;
18     env.timer.start_high = 0;
19     env.timer.Restart();
20 
21     REQUIRE(env.timer.counter_low == 5);
22     REQUIRE(env.timer.counter_high == 0);
23     REQUIRE(env.interrupt_counter == 0);
24     REQUIRE(env.timer.GetMaxSkip() == 4);
25 
26     env.timer.Tick();
27     env.timer.Tick();
28 
29     REQUIRE(env.timer.counter_low == 3);
30     REQUIRE(env.timer.counter_high == 0);
31     REQUIRE(env.interrupt_counter == 0);
32     REQUIRE(env.timer.GetMaxSkip() == 2);
33 
34     env.timer.Skip(2);
35     REQUIRE(env.timer.counter_low == 1);
36     REQUIRE(env.timer.counter_high == 0);
37     REQUIRE(env.interrupt_counter == 0);
38     REQUIRE(env.timer.GetMaxSkip() == 0);
39 
40     env.timer.pause = 1;
41     env.timer.Tick();
42     REQUIRE(env.timer.counter_low == 1);
43     REQUIRE(env.timer.counter_high == 0);
44     REQUIRE(env.interrupt_counter == 0);
45     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
46 
47     env.timer.pause = 0;
48     env.timer.Tick();
49     REQUIRE(env.timer.counter_low == 0);
50     REQUIRE(env.timer.counter_high == 0);
51     REQUIRE(env.interrupt_counter == 1);
52     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
53 
54     env.timer.Tick();
55     REQUIRE(env.timer.counter_low == 0);
56     REQUIRE(env.timer.counter_high == 0);
57     REQUIRE(env.interrupt_counter == 1);
58     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
59 }
60 
61 TEST_CASE("Auto restart mode", "[timer]") {
62     TimerTestEnvironment env;
63     env.timer.count_mode = Teakra::Timer::CountMode::AutoRestart;
64     env.timer.update_mmio = 1;
65     env.timer.start_low = 5;
66     env.timer.start_high = 0x1234;
67     env.timer.Restart();
68 
69     REQUIRE(env.timer.counter_low == 5);
70     REQUIRE(env.timer.counter_high == 0x1234);
71     REQUIRE(env.interrupt_counter == 0);
72     REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
73 
74     env.timer.Tick();
75     env.timer.Tick();
76 
77     REQUIRE(env.timer.counter_low == 3);
78     REQUIRE(env.timer.counter_high == 0x1234);
79     REQUIRE(env.interrupt_counter == 0);
80     REQUIRE(env.timer.GetMaxSkip() == 0x12340002);
81 
82     env.timer.Skip(0x12340002);
83     REQUIRE(env.timer.counter_low == 1);
84     REQUIRE(env.timer.counter_high == 0);
85     REQUIRE(env.interrupt_counter == 0);
86     REQUIRE(env.timer.GetMaxSkip() == 0);
87 
88     env.timer.pause = 1;
89     env.timer.Tick();
90     REQUIRE(env.timer.counter_low == 1);
91     REQUIRE(env.timer.counter_high == 0);
92     REQUIRE(env.interrupt_counter == 0);
93     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
94 
95     env.timer.pause = 0;
96     env.timer.Tick();
97     REQUIRE(env.timer.counter_low == 0);
98     REQUIRE(env.timer.counter_high == 0);
99     REQUIRE(env.interrupt_counter == 1);
100     REQUIRE(env.timer.GetMaxSkip() == 0x12340005);
101 
102     env.timer.Tick();
103     REQUIRE(env.timer.counter_low == 5);
104     REQUIRE(env.timer.counter_high == 0x1234);
105     REQUIRE(env.interrupt_counter == 1);
106     REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
107 }
108 
109 TEST_CASE("Free running mode", "[timer]") {
110     TimerTestEnvironment env;
111     // Set to Single most first to reset counter
112     env.timer.count_mode = Teakra::Timer::CountMode::Single;
113     env.timer.update_mmio = 1;
114     env.timer.start_low = 5;
115     env.timer.start_high = 0x1234;
116     env.timer.Restart();
117     env.timer.count_mode = Teakra::Timer::CountMode::FreeRunning;
118 
119     REQUIRE(env.timer.counter_low == 5);
120     REQUIRE(env.timer.counter_high == 0x1234);
121     REQUIRE(env.interrupt_counter == 0);
122     REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
123 
124     env.timer.Restart();
125 
126     REQUIRE(env.timer.counter_low == 5);
127     REQUIRE(env.timer.counter_high == 0x1234);
128     REQUIRE(env.interrupt_counter == 0);
129     REQUIRE(env.timer.GetMaxSkip() == 0x12340004);
130 
131     env.timer.Tick();
132     env.timer.Tick();
133 
134     REQUIRE(env.timer.counter_low == 3);
135     REQUIRE(env.timer.counter_high == 0x1234);
136     REQUIRE(env.interrupt_counter == 0);
137     REQUIRE(env.timer.GetMaxSkip() == 0x12340002);
138 
139     env.timer.Skip(0x12340002);
140     REQUIRE(env.timer.counter_low == 1);
141     REQUIRE(env.timer.counter_high == 0);
142     REQUIRE(env.interrupt_counter == 0);
143     REQUIRE(env.timer.GetMaxSkip() == 0);
144 
145     env.timer.pause = 1;
146     env.timer.Tick();
147     REQUIRE(env.timer.counter_low == 1);
148     REQUIRE(env.timer.counter_high == 0);
149     REQUIRE(env.interrupt_counter == 0);
150     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
151 
152     env.timer.pause = 0;
153     env.timer.Tick();
154     REQUIRE(env.timer.counter_low == 0);
155     REQUIRE(env.timer.counter_high == 0);
156     REQUIRE(env.interrupt_counter == 1);
157     REQUIRE(env.timer.GetMaxSkip() == 0xFFFFFFFF);
158 
159     env.timer.Tick();
160     REQUIRE(env.timer.counter_low == 0xFFFF);
161     REQUIRE(env.timer.counter_high == 0xFFFF);
162     REQUIRE(env.interrupt_counter == 1);
163     REQUIRE(env.timer.GetMaxSkip() == 0xFFFFFFFE);
164 }
165 
166 TEST_CASE("Event counting restart mode", "[timer]") {
167     TimerTestEnvironment env;
168     env.timer.count_mode = Teakra::Timer::CountMode::EventCount;
169     env.timer.update_mmio = 1;
170     env.timer.start_low = 5;
171     env.timer.start_high = 0;
172     env.timer.Restart();
173 
174     REQUIRE(env.timer.counter_low == 5);
175     REQUIRE(env.timer.counter_high == 0);
176     REQUIRE(env.interrupt_counter == 0);
177     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
178 
179     env.timer.Tick();
180 
181     REQUIRE(env.timer.counter_low == 5);
182     REQUIRE(env.timer.counter_high == 0);
183     REQUIRE(env.interrupt_counter == 0);
184     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
185 
186     env.timer.TickEvent();
187 
188     REQUIRE(env.timer.counter_low == 4);
189     REQUIRE(env.timer.counter_high == 0);
190     REQUIRE(env.interrupt_counter == 0);
191     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
192 
193     env.timer.pause = 1;
194     env.timer.TickEvent();
195 
196     REQUIRE(env.timer.counter_low == 4);
197     REQUIRE(env.timer.counter_high == 0);
198     REQUIRE(env.interrupt_counter == 0);
199     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
200 
201     env.timer.pause = 0;
202     env.timer.TickEvent();
203     env.timer.TickEvent();
204     env.timer.TickEvent();
205 
206     REQUIRE(env.timer.counter_low == 1);
207     REQUIRE(env.timer.counter_high == 0);
208     REQUIRE(env.interrupt_counter == 0);
209     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
210 
211     env.timer.TickEvent();
212 
213     REQUIRE(env.timer.counter_low == 0);
214     REQUIRE(env.timer.counter_high == 0);
215     REQUIRE(env.interrupt_counter == 1);
216     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
217 
218     env.timer.TickEvent();
219 
220     REQUIRE(env.timer.counter_low == 0);
221     REQUIRE(env.timer.counter_high == 0);
222     REQUIRE(env.interrupt_counter == 1);
223     REQUIRE(env.timer.GetMaxSkip() == Teakra::CoreTiming::Callbacks::Infinity);
224 }
225