blob: 6b8180920f0bbebb272aa8421d41212c6c98d717 [file] [log] [blame]
Miguel Young de la Sota6146c672020-04-15 13:09:52 -04001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
Timothy Trippelf63b7352021-08-25 18:09:44 +00005#include "sw/device/lib/dif/dif_rv_timer.h"
6
Miguel Young de la Sota6146c672020-04-15 13:09:52 -04007#include <cstring>
8#include <limits>
9#include <ostream>
10#include <stdint.h>
11
Miguel Young de la Sota6146c672020-04-15 13:09:52 -040012#include "gtest/gtest.h"
13#include "sw/device/lib/base/mmio.h"
Miguel Osorio96d8d572021-04-25 12:47:24 -070014#include "sw/device/lib/base/testing/mock_mmio.h"
Miguel Young de la Sota6146c672020-04-15 13:09:52 -040015
Timothy Trippelf63b7352021-08-25 18:09:44 +000016#include "rv_timer_regs.h" // Generated.
17
Miguel Young de la Sota6146c672020-04-15 13:09:52 -040018// We define global namespace == and << to make `dif_i2c_timing_params_t` work
19// nicely with EXPECT_EQ.
20bool operator==(dif_rv_timer_tick_params_t a, dif_rv_timer_tick_params_t b) {
21 return a.prescale == b.prescale && a.tick_step == b.tick_step;
22}
23
24std::ostream &operator<<(std::ostream &os,
25 const dif_rv_timer_tick_params_t &params) {
26 // Note that `tick_step` is actually a `char`, so it doesn't print correctly.
27 auto step = static_cast<uint32_t>(params.tick_step);
28 return os << "{ .prescale = " << params.prescale << ", .tick_step = " << step
29 << " }";
30}
31
32namespace dif_rv_timer_unittest {
33namespace {
34using ::mock_mmio::LeInt;
35using ::mock_mmio::MmioTest;
36using ::mock_mmio::MockDevice;
37
38constexpr uint32_t kFastClockSpeed = 2'000'000'000; // 2 GHz
39constexpr uint32_t kClockSpeed = 50'000'000; // 50 MHz
40constexpr uint32_t kSlowClockSpeed = 50; // 50 Hz
41
42constexpr uint32_t kSlowTimer = 1'000'000; // 1 MHz
43constexpr uint32_t kFastTimer = 120'000'000; // 120 MHz
44constexpr uint32_t kSluggishTimer = 3; // 3 Hz
45
46TEST(ApproximateParamsTest, Baseline) {
47 // The timer frequency devices the clock speed, so their quotient minus 1 is
48 // the prescale.
49 dif_rv_timer_tick_params_t params, expected = {
Timothy Trippelf63b7352021-08-25 18:09:44 +000050 .prescale = 49,
51 .tick_step = 1,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -040052 };
53 EXPECT_EQ(
54 dif_rv_timer_approximate_tick_params(kClockSpeed, kSlowTimer, &params),
55 kDifRvTimerOk);
56 EXPECT_EQ(params, expected);
57}
58
59TEST(ApproximateParamsTest, WithStep) {
60 // 50 MHz / 5 is 10 MHz; multiplied by 12, we get 120 MHz.
61 dif_rv_timer_tick_params_t params, expected = {
Timothy Trippelf63b7352021-08-25 18:09:44 +000062 .prescale = 4,
63 .tick_step = 12,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -040064 };
65 EXPECT_EQ(
66 dif_rv_timer_approximate_tick_params(kClockSpeed, kFastTimer, &params),
67 kDifRvTimerOk);
68 EXPECT_EQ(params, expected);
69}
70
71TEST(ApproximateParamsTest, UnrepresenableTooSlow) {
72 // This frequency is unrepresentable; the GCD of the clock and timer
73 // frequencies is 1, so the prescale is the clock speed, which does not fit in
74 // a u12.
75 dif_rv_timer_tick_params_t params;
76 EXPECT_EQ(dif_rv_timer_approximate_tick_params(kFastClockSpeed,
77 kSluggishTimer, &params),
78 kDifRvTimerApproximateTickParamsUnrepresentable);
79}
80
81TEST(ApproximateParamsTest, UnrepresenableTooFast) {
82 // This freqncy is unrepresentable; the GCD is 50, meaning that the step must
83 // be 2'400'000, which does not fit into a u8.
84 dif_rv_timer_tick_params_t params;
85 EXPECT_EQ(dif_rv_timer_approximate_tick_params(kSlowClockSpeed, kFastTimer,
86 &params),
87 kDifRvTimerApproximateTickParamsUnrepresentable);
88}
89
90TEST(ApproximateParamsTest, NullArgs) {
91 EXPECT_EQ(dif_rv_timer_approximate_tick_params(kSlowClockSpeed, kFastTimer,
92 nullptr),
93 kDifRvTimerBadArg);
94}
95
96class TimerTest : public testing::Test, public MmioTest {
97 protected:
98 dif_rv_timer_t MakeTimer(dif_rv_timer_config_t config) {
99 return {
Timothy Trippelf63b7352021-08-25 18:09:44 +0000100 .base_addr = dev().region(),
101 .config = config,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400102 };
103 }
104};
105
106// Copy of `reg_for_hart()` in the C translation unit under test.
107ptrdiff_t RegForHart(uint32_t hart, ptrdiff_t reg_offset) {
108 return 0x100 * hart + reg_offset;
109}
110
111// Copy of `irq_reg_for_hart()` in the C translation unit under test.
112ptrdiff_t IrqRegForHart(uint32_t hart, uint32_t comparators,
113 ptrdiff_t reg_offset) {
114 auto base = RegForHart(hart, reg_offset);
115 auto extra_comparator_offset = sizeof(uint64_t) * (comparators - 1);
116 return base + extra_comparator_offset;
117}
118
119constexpr uint32_t kAllOnes = std::numeric_limits<uint32_t>::max();
120
121class InitTest : public TimerTest {};
122
123TEST_F(InitTest, OneEach) {
124 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0);
125
126 EXPECT_WRITE32(IrqRegForHart(0, 1, RV_TIMER_INTR_ENABLE0_REG_OFFSET), 0x0);
127 EXPECT_WRITE32(IrqRegForHart(0, 1, RV_TIMER_INTR_STATE0_REG_OFFSET),
128 kAllOnes);
129
130 EXPECT_WRITE32(RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET), kAllOnes);
131 EXPECT_WRITE32(RegForHart(0, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET), kAllOnes);
132 EXPECT_WRITE32(RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET), kAllOnes);
133
134 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0);
135 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0);
136
137 dif_rv_timer timer;
138 EXPECT_EQ(dif_rv_timer_init(dev().region(),
139 {
Timothy Trippelf63b7352021-08-25 18:09:44 +0000140 .hart_count = 1,
141 .comparator_count = 1,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400142 },
143 &timer),
144 kDifRvTimerOk);
145}
146
147TEST_F(InitTest, FourCmps) {
148 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0);
149
150 EXPECT_WRITE32(IrqRegForHart(0, 4, RV_TIMER_INTR_ENABLE0_REG_OFFSET), 0x0);
151 EXPECT_WRITE32(IrqRegForHart(0, 4, RV_TIMER_INTR_STATE0_REG_OFFSET),
152 kAllOnes);
153
154 for (ptrdiff_t cmp_offset = 0; cmp_offset < 32; cmp_offset += 8) {
155 EXPECT_WRITE32(
156 RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
157 kAllOnes);
158 EXPECT_WRITE32(
159 RegForHart(0, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET) + cmp_offset,
160 kAllOnes);
161 EXPECT_WRITE32(
162 RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
163 kAllOnes);
164 }
165
166 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0);
167 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0);
168
169 dif_rv_timer timer;
170 EXPECT_EQ(dif_rv_timer_init(dev().region(),
171 {
Timothy Trippelf63b7352021-08-25 18:09:44 +0000172 .hart_count = 1,
173 .comparator_count = 4,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400174 },
175 &timer),
176 kDifRvTimerOk);
177}
178
179TEST_F(InitTest, FourEach) {
180 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0);
181
182 for (uint32_t hart = 0; hart < 4; ++hart) {
183 EXPECT_WRITE32(IrqRegForHart(hart, 4, RV_TIMER_INTR_ENABLE0_REG_OFFSET),
184 0x0);
185 EXPECT_WRITE32(IrqRegForHart(hart, 4, RV_TIMER_INTR_STATE0_REG_OFFSET),
186 kAllOnes);
187
188 for (ptrdiff_t cmp_offset = 0; cmp_offset < 32; cmp_offset += 8) {
189 EXPECT_WRITE32(
190 RegForHart(hart, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
191 kAllOnes);
192 EXPECT_WRITE32(
193 RegForHart(hart, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET) + cmp_offset,
194 kAllOnes);
195 EXPECT_WRITE32(
196 RegForHart(hart, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
197 kAllOnes);
198 }
199
200 EXPECT_WRITE32(RegForHart(hart, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0);
201 EXPECT_WRITE32(RegForHart(hart, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0);
202 }
203
204 dif_rv_timer timer;
205 EXPECT_EQ(dif_rv_timer_init(dev().region(),
206 {
Timothy Trippelf63b7352021-08-25 18:09:44 +0000207 .hart_count = 4,
208 .comparator_count = 4,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400209 },
210 &timer),
211 kDifRvTimerOk);
212}
213
214TEST_F(InitTest, NullArgs) {
215 EXPECT_EQ(dif_rv_timer_init(dev().region(),
216 {
Timothy Trippelf63b7352021-08-25 18:09:44 +0000217 .hart_count = 1,
218 .comparator_count = 1,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400219 },
220 nullptr),
221 kDifRvTimerBadArg);
222}
223
224TEST_F(InitTest, NoHartNoTimers) {
225 dif_rv_timer_t timer;
226 EXPECT_EQ(dif_rv_timer_init(dev().region(),
227 {
Timothy Trippelf63b7352021-08-25 18:09:44 +0000228 .hart_count = 0,
229 .comparator_count = 1,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400230 },
231 &timer),
232 kDifRvTimerBadArg);
233 EXPECT_EQ(dif_rv_timer_init(dev().region(),
234 {
Timothy Trippelf63b7352021-08-25 18:09:44 +0000235 .hart_count = 1,
236 .comparator_count = 0,
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400237 },
238 &timer),
239 kDifRvTimerBadArg);
240}
241
242class ResetTest : public TimerTest {};
243
244TEST_F(ResetTest, OneEach) {
245 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0);
246
247 EXPECT_WRITE32(IrqRegForHart(0, 1, RV_TIMER_INTR_ENABLE0_REG_OFFSET), 0x0);
248 EXPECT_WRITE32(IrqRegForHart(0, 1, RV_TIMER_INTR_STATE0_REG_OFFSET),
249 kAllOnes);
250
251 EXPECT_WRITE32(RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET), kAllOnes);
252 EXPECT_WRITE32(RegForHart(0, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET), kAllOnes);
253 EXPECT_WRITE32(RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET), kAllOnes);
254
255 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0);
256 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0);
257
258 auto timer = MakeTimer({1, 1});
259 EXPECT_EQ(dif_rv_timer_reset(&timer), kDifRvTimerOk);
260}
261
262TEST_F(ResetTest, FourCmps) {
263 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0);
264
265 EXPECT_WRITE32(IrqRegForHart(0, 4, RV_TIMER_INTR_ENABLE0_REG_OFFSET), 0x0);
266 EXPECT_WRITE32(IrqRegForHart(0, 4, RV_TIMER_INTR_STATE0_REG_OFFSET),
267 kAllOnes);
268
269 for (ptrdiff_t cmp_offset = 0; cmp_offset < 32; cmp_offset += 8) {
270 EXPECT_WRITE32(
271 RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
272 kAllOnes);
273 EXPECT_WRITE32(
274 RegForHart(0, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET) + cmp_offset,
275 kAllOnes);
276 EXPECT_WRITE32(
277 RegForHart(0, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
278 kAllOnes);
279 }
280
281 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0);
282 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0);
283
284 auto timer = MakeTimer({1, 4});
285 EXPECT_EQ(dif_rv_timer_reset(&timer), kDifRvTimerOk);
286}
287
288TEST_F(ResetTest, FourSix) {
289 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0);
290
291 for (uint32_t hart = 0; hart < 4; ++hart) {
292 EXPECT_WRITE32(IrqRegForHart(hart, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET),
293 0x0);
294 EXPECT_WRITE32(IrqRegForHart(hart, 6, RV_TIMER_INTR_STATE0_REG_OFFSET),
295 kAllOnes);
296
297 for (ptrdiff_t cmp_offset = 0; cmp_offset < 48; cmp_offset += 8) {
298 EXPECT_WRITE32(
299 RegForHart(hart, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
300 kAllOnes);
301 EXPECT_WRITE32(
302 RegForHart(hart, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET) + cmp_offset,
303 kAllOnes);
304 EXPECT_WRITE32(
305 RegForHart(hart, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + cmp_offset,
306 kAllOnes);
307 }
308
309 EXPECT_WRITE32(RegForHart(hart, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0);
310 EXPECT_WRITE32(RegForHart(hart, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0);
311 }
312
313 auto timer = MakeTimer({4, 6});
314 EXPECT_EQ(dif_rv_timer_reset(&timer), kDifRvTimerOk);
315}
316
317TEST_F(ResetTest, NullArgs) {
318 EXPECT_EQ(dif_rv_timer_reset(nullptr), kDifRvTimerBadArg);
319}
320
321class SetParamsTest : public TimerTest {};
322
323TEST_F(SetParamsTest, Baseline) {
324 EXPECT_WRITE32(
325 RegForHart(2, RV_TIMER_CFG0_REG_OFFSET),
326 {{RV_TIMER_CFG0_PRESCALE_OFFSET, 400}, {RV_TIMER_CFG0_STEP_OFFSET, 25}});
327
328 auto timer = MakeTimer({4, 6});
329 EXPECT_EQ(dif_rv_timer_set_tick_params(&timer, 2,
330 {.prescale = 400, .tick_step = 25}),
331 kDifRvTimerOk);
332}
333
334TEST_F(SetParamsTest, NullArgs) {
335 EXPECT_EQ(dif_rv_timer_set_tick_params(nullptr, 2,
336 {.prescale = 400, .tick_step = 25}),
337 kDifRvTimerBadArg);
338}
339
340TEST_F(SetParamsTest, BadHart) {
341 auto timer = MakeTimer({4, 6});
342 EXPECT_EQ(dif_rv_timer_set_tick_params(&timer, 4,
343 {.prescale = 400, .tick_step = 25}),
344 kDifRvTimerBadArg);
345 EXPECT_EQ(dif_rv_timer_set_tick_params(&timer, 500,
346 {.prescale = 400, .tick_step = 25}),
347 kDifRvTimerBadArg);
348}
349
350class TimerEnableTest : public TimerTest {};
351
352TEST_F(TimerEnableTest, Baseline) {
353 EXPECT_MASK32(RV_TIMER_CTRL_REG_OFFSET,
354 {{/*offset=*/1, /*mask=*/1, /*value=*/1}});
355 EXPECT_MASK32(RV_TIMER_CTRL_REG_OFFSET,
356 {{/*offset=*/3, /*mask=*/1, /*value=*/0}});
357
358 auto timer = MakeTimer({4, 6});
359 EXPECT_EQ(dif_rv_timer_counter_set_enabled(&timer, 1, kDifRvTimerEnabled),
360 kDifRvTimerOk);
361 EXPECT_EQ(dif_rv_timer_counter_set_enabled(&timer, 3, kDifRvTimerDisabled),
362 kDifRvTimerOk);
363}
364
365TEST_F(TimerEnableTest, NullArgs) {
366 EXPECT_EQ(dif_rv_timer_counter_set_enabled(nullptr, 1, kDifRvTimerEnabled),
367 kDifRvTimerBadArg);
368}
369
370TEST_F(TimerEnableTest, BadHart) {
371 auto timer = MakeTimer({4, 6});
372 EXPECT_EQ(dif_rv_timer_counter_set_enabled(&timer, 4, kDifRvTimerEnabled),
373 kDifRvTimerBadArg);
374 EXPECT_EQ(dif_rv_timer_counter_set_enabled(&timer, 5, kDifRvTimerDisabled),
375 kDifRvTimerBadArg);
376}
377
378class CounterReadTest : public TimerTest {};
379
380TEST_F(CounterReadTest, Baseline) {
381 EXPECT_READ32(RegForHart(0, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0222'0222);
382 EXPECT_READ32(RegForHart(0, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0333'0333);
383 EXPECT_READ32(RegForHart(0, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0222'0222);
384
385 auto timer = MakeTimer({4, 6});
386 uint64_t value;
387 EXPECT_EQ(dif_rv_timer_counter_read(&timer, 0, &value), kDifRvTimerOk);
388 EXPECT_EQ(value, 0x0222'0222'0333'0333);
389}
390
391TEST_F(CounterReadTest, Overflow) {
392 EXPECT_READ32(RegForHart(1, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0222'0222);
393 EXPECT_READ32(RegForHart(1, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0333'0333);
394 EXPECT_READ32(RegForHart(1, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0222'0223);
395
396 EXPECT_READ32(RegForHart(1, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0222'0223);
397 EXPECT_READ32(RegForHart(1, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET), 0x0333'0444);
398 EXPECT_READ32(RegForHart(1, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET), 0x0222'0223);
399
400 auto timer = MakeTimer({4, 6});
401 uint64_t value;
402 EXPECT_EQ(dif_rv_timer_counter_read(&timer, 1, &value), kDifRvTimerOk);
403 EXPECT_EQ(value, 0x0222'0223'0333'0444);
404}
405
406TEST_F(CounterReadTest, NullArgs) {
407 auto timer = MakeTimer({4, 6});
408 uint64_t value;
409 EXPECT_EQ(dif_rv_timer_counter_read(nullptr, 2, &value), kDifRvTimerBadArg);
410 EXPECT_EQ(dif_rv_timer_counter_read(&timer, 2, nullptr), kDifRvTimerBadArg);
411}
412
413TEST_F(CounterReadTest, BadHart) {
414 auto timer = MakeTimer({4, 6});
415 uint64_t value;
416 EXPECT_EQ(dif_rv_timer_counter_read(&timer, 4, &value), kDifRvTimerBadArg);
417 EXPECT_EQ(dif_rv_timer_counter_read(&timer, 5, &value), kDifRvTimerBadArg);
418}
419
Timothy Trippelf63b7352021-08-25 18:09:44 +0000420class CounterWriteTest : public TimerTest {};
421
422TEST_F(CounterWriteTest, Baseline) {
423 EXPECT_READ32(RV_TIMER_CTRL_REG_OFFSET, 0x0000'0001);
424 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0000'0000);
425 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_LOWER0_REG_OFFSET),
426 0xDEAD'BEEF);
427 EXPECT_WRITE32(RegForHart(0, RV_TIMER_TIMER_V_UPPER0_REG_OFFSET),
428 0xCAFE'FEED);
429 EXPECT_WRITE32(RV_TIMER_CTRL_REG_OFFSET, 0x0000'0001);
430
431 auto timer = MakeTimer({1, 1});
432 uint64_t count = 0xCAFE'FEED'DEAD'BEEF;
433 EXPECT_EQ(dif_rv_timer_counter_write(&timer, 0, count), kDifRvTimerOk);
434}
435
436TEST_F(CounterWriteTest, NullArgs) {
437 uint64_t count = 0xCAFE'FEED'DEAD'BEEF;
438 EXPECT_EQ(dif_rv_timer_counter_write(nullptr, 0, count), kDifRvTimerBadArg);
439}
440
441TEST_F(CounterWriteTest, BadHart) {
442 auto timer = MakeTimer({1, 1});
443 uint64_t count = 0xCAFE'FEED'DEAD'BEEF;
444 EXPECT_EQ(dif_rv_timer_counter_write(&timer, 1, count), kDifRvTimerBadArg);
445 EXPECT_EQ(dif_rv_timer_counter_write(&timer, 2, count), kDifRvTimerBadArg);
446}
447
Miguel Young de la Sota6146c672020-04-15 13:09:52 -0400448class ArmTest : public TimerTest {};
449
450TEST_F(ArmTest, Baseline) {
451 // Note: 16 = 2 * sizeof(uint64_t), since these need to be the registers
452 // for the third (index 2) comparator.
453 auto lower_reg = RegForHart(1, RV_TIMER_COMPARE_LOWER0_0_REG_OFFSET) + 16;
454 auto upper_reg = RegForHart(1, RV_TIMER_COMPARE_UPPER0_0_REG_OFFSET) + 16;
455
456 EXPECT_WRITE32(upper_reg, kAllOnes);
457 EXPECT_WRITE32(lower_reg, 0x0444'0555);
458 EXPECT_WRITE32(upper_reg, 0x0222'0333);
459
460 auto timer = MakeTimer({4, 6});
461 EXPECT_EQ(dif_rv_timer_arm(&timer, 1, 2, 0x0222'0333'0444'0555),
462 kDifRvTimerOk);
463}
464
465TEST_F(ArmTest, NullArgs) {
466 EXPECT_EQ(dif_rv_timer_arm(nullptr, 1, 2, 0x0222'0333'0444'0555),
467 kDifRvTimerBadArg);
468}
469
470TEST_F(ArmTest, BadHartBadComp) {
471 auto timer = MakeTimer({4, 6});
472 EXPECT_EQ(dif_rv_timer_arm(&timer, 4, 2, 0x0222'0333'0444'0555),
473 kDifRvTimerBadArg);
474 EXPECT_EQ(dif_rv_timer_arm(&timer, 5, 2, 0x0222'0333'0444'0555),
475 kDifRvTimerBadArg);
476 EXPECT_EQ(dif_rv_timer_arm(&timer, 1, 6, 0x0222'0333'0444'0555),
477 kDifRvTimerBadArg);
478 EXPECT_EQ(dif_rv_timer_arm(&timer, 1, 7, 0x0222'0333'0444'0555),
479 kDifRvTimerBadArg);
480}
481
482class IrqEnableTest : public TimerTest {};
483
484TEST_F(IrqEnableTest, Baseline) {
485 EXPECT_MASK32(IrqRegForHart(1, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET),
486 {{/*offset=*/2, /*mask=*/1, /*value=*/1}});
487 EXPECT_MASK32(IrqRegForHart(3, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET),
488 {{/*offset=*/4, /*mask=*/1, /*value=*/0}});
489
490 auto timer = MakeTimer({4, 6});
491 EXPECT_EQ(dif_rv_timer_irq_enable(&timer, 1, 2, kDifRvTimerEnabled),
492 kDifRvTimerOk);
493 EXPECT_EQ(dif_rv_timer_irq_enable(&timer, 3, 4, kDifRvTimerDisabled),
494 kDifRvTimerOk);
495}
496
497TEST_F(IrqEnableTest, NullArgs) {
498 EXPECT_EQ(dif_rv_timer_irq_enable(nullptr, 1, 2, kDifRvTimerEnabled),
499 kDifRvTimerBadArg);
500}
501
502TEST_F(IrqEnableTest, BadHartBadComp) {
503 auto timer = MakeTimer({4, 6});
504 EXPECT_EQ(dif_rv_timer_irq_enable(&timer, 4, 2, kDifRvTimerEnabled),
505 kDifRvTimerBadArg);
506 EXPECT_EQ(dif_rv_timer_irq_enable(&timer, 5, 4, kDifRvTimerDisabled),
507 kDifRvTimerBadArg);
508 EXPECT_EQ(dif_rv_timer_irq_enable(&timer, 1, 6, kDifRvTimerEnabled),
509 kDifRvTimerBadArg);
510 EXPECT_EQ(dif_rv_timer_irq_enable(&timer, 3, 7, kDifRvTimerDisabled),
511 kDifRvTimerBadArg);
512}
513
514class IrqGetTest : public TimerTest {};
515
516TEST_F(IrqGetTest, Baseline) {
517 EXPECT_READ32(IrqRegForHart(1, 6, RV_TIMER_INTR_STATE0_REG_OFFSET),
518 {
519 {/*offset=*/0, /*value=*/1},
520 {/*offset=*/2, /*value=*/1},
521 {/*offset=*/5, /*value=*/1},
522 });
523 EXPECT_READ32(IrqRegForHart(3, 6, RV_TIMER_INTR_STATE0_REG_OFFSET),
524 {
525 {/*offset=*/0, /*value=*/1},
526 {/*offset=*/2, /*value=*/1},
527 {/*offset=*/5, /*value=*/1},
528 });
529
530 auto timer = MakeTimer({4, 6});
531 bool flag;
532 EXPECT_EQ(dif_rv_timer_irq_get(&timer, 1, 2, &flag), kDifRvTimerOk);
533 EXPECT_TRUE(flag);
534 EXPECT_EQ(dif_rv_timer_irq_get(&timer, 3, 4, &flag), kDifRvTimerOk);
535 EXPECT_FALSE(flag);
536}
537
538TEST_F(IrqGetTest, NullArgs) {
539 auto timer = MakeTimer({4, 6});
540 bool flag;
541 EXPECT_EQ(dif_rv_timer_irq_get(nullptr, 1, 2, &flag), kDifRvTimerBadArg);
542 EXPECT_EQ(dif_rv_timer_irq_get(&timer, 3, 4, nullptr), kDifRvTimerBadArg);
543}
544
545TEST_F(IrqGetTest, BadHartBadComp) {
546 auto timer = MakeTimer({4, 6});
547 bool flag;
548 EXPECT_EQ(dif_rv_timer_irq_get(&timer, 4, 2, &flag), kDifRvTimerBadArg);
549 EXPECT_EQ(dif_rv_timer_irq_get(&timer, 5, 4, &flag), kDifRvTimerBadArg);
550 EXPECT_EQ(dif_rv_timer_irq_get(&timer, 1, 6, &flag), kDifRvTimerBadArg);
551 EXPECT_EQ(dif_rv_timer_irq_get(&timer, 3, 7, &flag), kDifRvTimerBadArg);
552}
553
554class IrqClearTest : public TimerTest {};
555
556TEST_F(IrqClearTest, Baseline) {
557 EXPECT_WRITE32(IrqRegForHart(1, 6, RV_TIMER_INTR_STATE0_REG_OFFSET),
558 {
559 {/*offset=*/2, /*value=*/1},
560 });
561 EXPECT_WRITE32(IrqRegForHart(3, 6, RV_TIMER_INTR_STATE0_REG_OFFSET),
562 {
563 {/*offset=*/4, /*value=*/1},
564 });
565
566 auto timer = MakeTimer({4, 6});
567 EXPECT_EQ(dif_rv_timer_irq_clear(&timer, 1, 2), kDifRvTimerOk);
568 EXPECT_EQ(dif_rv_timer_irq_clear(&timer, 3, 4), kDifRvTimerOk);
569}
570
571TEST_F(IrqClearTest, NullArgs) {
572 EXPECT_EQ(dif_rv_timer_irq_clear(nullptr, 1, 2), kDifRvTimerBadArg);
573}
574
575TEST_F(IrqClearTest, BadHartBadComp) {
576 auto timer = MakeTimer({4, 6});
577 EXPECT_EQ(dif_rv_timer_irq_clear(&timer, 4, 2), kDifRvTimerBadArg);
578 EXPECT_EQ(dif_rv_timer_irq_clear(&timer, 5, 4), kDifRvTimerBadArg);
579 EXPECT_EQ(dif_rv_timer_irq_clear(&timer, 1, 6), kDifRvTimerBadArg);
580 EXPECT_EQ(dif_rv_timer_irq_clear(&timer, 3, 7), kDifRvTimerBadArg);
581}
582
583class IrqDisableTest : public TimerTest {};
584
585TEST_F(IrqDisableTest, Baseline) {
586 EXPECT_READ32(IrqRegForHart(1, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET),
587 0b101010);
588 EXPECT_WRITE32(IrqRegForHart(1, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET), 0);
589
590 EXPECT_WRITE32(IrqRegForHart(3, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET), 0);
591
592 auto timer = MakeTimer({4, 6});
593 uint32_t state;
594 EXPECT_EQ(dif_rv_timer_irq_disable(&timer, 1, &state), kDifRvTimerOk);
595 EXPECT_EQ(state, 0b101010);
596 EXPECT_EQ(dif_rv_timer_irq_disable(&timer, 3, nullptr), kDifRvTimerOk);
597}
598
599TEST_F(IrqDisableTest, NullArgs) {
600 uint32_t state;
601 EXPECT_EQ(dif_rv_timer_irq_disable(nullptr, 1, &state), kDifRvTimerBadArg);
602}
603
604TEST_F(IrqDisableTest, BadHart) {
605 auto timer = MakeTimer({4, 6});
606 uint32_t state;
607 EXPECT_EQ(dif_rv_timer_irq_disable(&timer, 4, &state), kDifRvTimerBadArg);
608 EXPECT_EQ(dif_rv_timer_irq_disable(&timer, 5, &state), kDifRvTimerBadArg);
609}
610
611class IrqRestoreTest : public TimerTest {};
612
613TEST_F(IrqRestoreTest, Baseline) {
614 EXPECT_WRITE32(IrqRegForHart(1, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET),
615 0b101010);
616 EXPECT_WRITE32(IrqRegForHart(3, 6, RV_TIMER_INTR_ENABLE0_REG_OFFSET),
617 0b011011);
618
619 auto timer = MakeTimer({4, 6});
620 EXPECT_EQ(dif_rv_timer_irq_restore(&timer, 1, 0b101010), kDifRvTimerOk);
621 EXPECT_EQ(dif_rv_timer_irq_restore(&timer, 3, 0b011011), kDifRvTimerOk);
622}
623
624TEST_F(IrqRestoreTest, NullArgs) {
625 EXPECT_EQ(dif_rv_timer_irq_restore(nullptr, 1, 0), kDifRvTimerBadArg);
626}
627
628TEST_F(IrqRestoreTest, BadHart) {
629 auto timer = MakeTimer({4, 6});
630 EXPECT_EQ(dif_rv_timer_irq_restore(&timer, 4, 0), kDifRvTimerBadArg);
631 EXPECT_EQ(dif_rv_timer_irq_restore(&timer, 5, 0), kDifRvTimerBadArg);
632}
633
634class IrqForceTest : public TimerTest {};
635
636TEST_F(IrqForceTest, Baseline) {
637 EXPECT_WRITE32(IrqRegForHart(1, 6, RV_TIMER_INTR_TEST0_REG_OFFSET),
638 {
639 {/*offset=*/2, /*value=*/1},
640 });
641 EXPECT_WRITE32(IrqRegForHart(3, 6, RV_TIMER_INTR_TEST0_REG_OFFSET),
642 {
643 {/*offset=*/4, /*value=*/1},
644 });
645
646 auto timer = MakeTimer({4, 6});
647 EXPECT_EQ(dif_rv_timer_irq_force(&timer, 1, 2), kDifRvTimerOk);
648 EXPECT_EQ(dif_rv_timer_irq_force(&timer, 3, 4), kDifRvTimerOk);
649}
650
651TEST_F(IrqForceTest, NullArgs) {
652 EXPECT_EQ(dif_rv_timer_irq_force(nullptr, 1, 2), kDifRvTimerBadArg);
653}
654
655TEST_F(IrqForceTest, BadHartBadComp) {
656 auto timer = MakeTimer({4, 6});
657 EXPECT_EQ(dif_rv_timer_irq_force(&timer, 4, 2), kDifRvTimerBadArg);
658 EXPECT_EQ(dif_rv_timer_irq_force(&timer, 5, 4), kDifRvTimerBadArg);
659 EXPECT_EQ(dif_rv_timer_irq_force(&timer, 1, 6), kDifRvTimerBadArg);
660 EXPECT_EQ(dif_rv_timer_irq_force(&timer, 3, 7), kDifRvTimerBadArg);
661}
662} // namespace
663} // namespace dif_rv_timer_unittest