Software APIs
dif_rv_core_ibex_unittest.cc
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
6 
7 #include "gtest/gtest.h"
9 #include "sw/device/lib/base/mock_mmio.h"
11 
12 extern "C" {
13 #include "rv_core_ibex_regs.h" // Generated.
14 } // extern "C"
15 
16 // We define global namespace == and << to make
17 // `dif_rv_core_ibex_addr_translation_mapping_t` work nicely with EXPECT_EQ.
18 bool operator==(const dif_rv_core_ibex_addr_translation_mapping_t a,
20  return !memcmp(&a, &b, sizeof(dif_rv_core_ibex_addr_translation_mapping_t));
21 }
22 
23 std::ostream &operator<<(
24  std::ostream &os,
26  return os << "{\n"
27  << " .matching_addr = " << mapping.matching_addr << ",\n"
28  << " .remap_addr = " << mapping.remap_addr << ",\n"
29  << " .size = " << mapping.size << ",\n"
30  << "}";
31 }
32 
33 // We define global namespace == and << to make `dif_rv_core_ibex_nmi_state_t`
34 // work nicely with EXPECT_EQ.
35 bool operator==(const dif_rv_core_ibex_nmi_state_t a,
37  return memcmp(&a, &b, sizeof(dif_rv_core_ibex_nmi_state_t)) == 0;
38 }
39 
40 std::ostream &operator<<(std::ostream &os,
41  const dif_rv_core_ibex_nmi_state_t &state) {
42  return os << "{\n"
43  << "state = {\n"
44  << " .alert_enabled = " << state.alert_enabled << ",\n"
45  << " .alert_raised = " << state.alert_raised << ",\n"
46  << " .wdog_enabled = " << state.wdog_enabled << ",\n"
47  << " .wdog_barked = " << state.wdog_barked << ",\n"
48  << "}";
49 }
50 
51 std::ostream &operator<<(std::ostream &os,
53  return os << "{\n"
54  << "fault_state = {\n"
55  << " .mtval = " << info.fault_state.mtval << ",\n"
56  << " .mpec = " << info.fault_state.mpec << ",\n"
57  << " .mdaa = " << info.fault_state.mdaa << ",\n"
58  << " .mnpc = " << info.fault_state.mnpc << ",\n"
59  << " .mcpc = " << info.fault_state.mcpc << ",\n"
60  << "},\n"
61  << "previous_fault_state = {\n"
62  << " .mtval = " << info.previous_fault_state.mtval << ",\n"
63  << " .mpec = " << info.previous_fault_state.mpec << ",\n"
64  << "},\n"
65  << "double_fault = " << info.double_fault << ",\n"
66  << "}";
67 }
68 
69 bool operator==(const dif_rv_core_ibex_crash_dump_info_t a,
71  return memcmp(&a, &b, sizeof(dif_rv_core_ibex_crash_dump_info_t)) == 0;
72 }
73 namespace dif_rv_core_ibex_test {
76 using testing::Test;
77 
78 // Base class for the rest fixtures in this file.
79 class RvCoreIbexTest : public testing::Test, public mock_mmio::MmioTest {};
80 
81 // Base class for the rest of the tests in this file, provides a
82 // `dif_aes_t` instance.
84  protected:
85  dif_rv_core_ibex_t ibex_;
86 
88  EXPECT_DIF_OK(dif_rv_core_ibex_init(dev().region(), &ibex_));
89  }
90 };
91 
94  public testing::WithParamInterface<
95  std::tuple<dif_rv_core_ibex_addr_translation_slot_t,
96  dif_rv_core_ibex_addr_translation_bus_t, uint32_t,
97  uint32_t, uint32_t, uint32_t>> {
98  protected:
99  static constexpr dif_rv_core_ibex_addr_translation_mapping_t kMapping = {
100  .matching_addr = 0x9000000,
101  .remap_addr = 0x2000000,
102  .size = 0x8000,
103  };
104 
105  uint32_t Napot(uint32_t addr, size_t size) { return addr | (size - 1) >> 1; }
106 };
108  AddressTranslationTest::kMapping;
109 
110 INSTANTIATE_TEST_SUITE_P(
112  testing::ValuesIn(std::vector<
113  std::tuple<dif_rv_core_ibex_addr_translation_slot_t,
114  dif_rv_core_ibex_addr_translation_bus_t,
115  uint32_t, uint32_t, uint32_t, uint32_t>>{{
116  {kDifRvCoreIbexAddrTranslationSlot_0, kDifRvCoreIbexAddrTranslationDBus,
117  RV_CORE_IBEX_DBUS_ADDR_MATCHING_0_REG_OFFSET,
118  RV_CORE_IBEX_DBUS_REMAP_ADDR_0_REG_OFFSET,
119  RV_CORE_IBEX_DBUS_ADDR_EN_0_REG_OFFSET,
120  RV_CORE_IBEX_DBUS_REGWEN_0_REG_OFFSET},
121 
122  {kDifRvCoreIbexAddrTranslationSlot_0, kDifRvCoreIbexAddrTranslationIBus,
123  RV_CORE_IBEX_IBUS_ADDR_MATCHING_0_REG_OFFSET,
124  RV_CORE_IBEX_IBUS_REMAP_ADDR_0_REG_OFFSET,
125  RV_CORE_IBEX_IBUS_ADDR_EN_0_REG_OFFSET,
126  RV_CORE_IBEX_IBUS_REGWEN_0_REG_OFFSET},
127 
128  {kDifRvCoreIbexAddrTranslationSlot_1, kDifRvCoreIbexAddrTranslationDBus,
129  RV_CORE_IBEX_DBUS_ADDR_MATCHING_1_REG_OFFSET,
130  RV_CORE_IBEX_DBUS_REMAP_ADDR_1_REG_OFFSET,
131  RV_CORE_IBEX_DBUS_ADDR_EN_1_REG_OFFSET,
132  RV_CORE_IBEX_DBUS_REGWEN_1_REG_OFFSET},
133 
134  {kDifRvCoreIbexAddrTranslationSlot_1, kDifRvCoreIbexAddrTranslationIBus,
135  RV_CORE_IBEX_IBUS_ADDR_MATCHING_1_REG_OFFSET,
136  RV_CORE_IBEX_IBUS_REMAP_ADDR_1_REG_OFFSET,
137  RV_CORE_IBEX_IBUS_ADDR_EN_1_REG_OFFSET,
138  RV_CORE_IBEX_IBUS_REGWEN_1_REG_OFFSET},
139  }}),
140  [](const ::testing::TestParamInfo<AddressTranslationTest::ParamType>
141  &info) {
142  const auto slot = std::get<0>(info.param);
143  const auto bus = std::get<1>(info.param);
144  std::string name = "";
145  name += bus == kDifRvCoreIbexAddrTranslationDBus ? "DBus" : "IBus";
146  name += slot == kDifRvCoreIbexAddrTranslationSlot_0 ? "Slot0" : "Slot1";
147  return name;
148  });
149 
150 TEST_P(AddressTranslationTest, DisableSuccess) {
151  const auto slot = std::get<0>(GetParam());
152  const auto bus = std::get<1>(GetParam());
153  const auto en_reg = std::get<4>(GetParam());
154  const auto r_regwen = std::get<5>(GetParam());
155 
156  EXPECT_READ32(r_regwen, 1);
157  EXPECT_WRITE32(en_reg, 0);
158  EXPECT_DIF_OK(dif_rv_core_ibex_disable_addr_translation(&ibex_, slot, bus));
159 }
160 
161 TEST_P(AddressTranslationTest, EnableSuccess) {
162  const auto slot = std::get<0>(GetParam());
163  const auto bus = std::get<1>(GetParam());
164  const auto en_reg = std::get<4>(GetParam());
165  const auto r_regwen = std::get<5>(GetParam());
166 
167  EXPECT_READ32(r_regwen, 1);
168  EXPECT_WRITE32(en_reg, 1);
169  EXPECT_DIF_OK(dif_rv_core_ibex_enable_addr_translation(&ibex_, slot, bus));
170 }
171 
172 TEST_P(AddressTranslationTest, ConfigureSuccess) {
173  const auto slot = std::get<0>(GetParam());
174  const auto bus = std::get<1>(GetParam());
175  const auto r_matching = std::get<2>(GetParam());
176  const auto r_remap = std::get<3>(GetParam());
177  const auto r_regwen = std::get<5>(GetParam());
178 
179  EXPECT_READ32(r_regwen, 1);
180 
181  EXPECT_WRITE32(r_matching, 0x9003fff);
182  EXPECT_WRITE32(r_remap, kMapping.remap_addr);
183 
185  dif_rv_core_ibex_configure_addr_translation(&ibex_, slot, bus, kMapping));
186 }
187 
188 TEST_P(AddressTranslationTest, PowerOfTwoAlignmentSuccess) {
189  const auto slot = std::get<0>(GetParam());
190  const auto bus = std::get<1>(GetParam());
191  const auto r_matching = std::get<2>(GetParam());
192  const auto r_remap = std::get<3>(GetParam());
193  const auto r_regwen = std::get<5>(GetParam());
194 
196  mapping.matching_addr = 0x8000000;
197 
198  for (size_t i = 0; i < (sizeof(uint32_t) * 8) - 1; ++i) {
199  mapping.size = 1u << i;
200 
201  EXPECT_READ32(r_regwen, 1);
202 
203  EXPECT_WRITE32(r_matching, Napot(mapping.matching_addr, mapping.size));
204  EXPECT_WRITE32(r_remap, mapping.remap_addr);
205 
206  EXPECT_DIF_OK(dif_rv_core_ibex_configure_addr_translation(&ibex_, slot, bus,
207  mapping));
208  }
209 }
210 
211 TEST_P(AddressTranslationTest, NotPowerOfTwo) {
212  const auto slot = std::get<0>(GetParam());
213  const auto bus = std::get<1>(GetParam());
214 
216  mapping.size += 0x20;
218  dif_rv_core_ibex_configure_addr_translation(&ibex_, slot, bus, mapping));
219 }
220 
221 TEST_P(AddressTranslationTest, ReadSuccess) {
222  const auto slot = std::get<0>(GetParam());
223  const auto bus = std::get<1>(GetParam());
224  const auto r_matching = std::get<2>(GetParam());
225  const auto r_remap = std::get<3>(GetParam());
226 
227  EXPECT_READ32(r_matching, 0x9003fff);
228  EXPECT_READ32(r_remap, kMapping.remap_addr);
229 
232  dif_rv_core_ibex_read_addr_translation(&ibex_, slot, bus, &mapping));
233 
234  EXPECT_EQ(mapping, kMapping);
235 }
236 
237 TEST_P(AddressTranslationTest, LockSuccess) {
238  const auto slot = std::get<0>(GetParam());
239  const auto bus = std::get<1>(GetParam());
240  const auto r_regwen = std::get<5>(GetParam());
241 
242  EXPECT_READ32(r_regwen, 1);
243  EXPECT_WRITE32(r_regwen, 0);
244 
245  EXPECT_DIF_OK(dif_rv_core_ibex_lock_addr_translation(&ibex_, slot, bus));
246 }
247 
248 TEST_P(AddressTranslationTest, Locked) {
249  const auto slot = std::get<0>(GetParam());
250  const auto bus = std::get<1>(GetParam());
251  const auto r_regwen = std::get<5>(GetParam());
252 
253  EXPECT_READ32(r_regwen, 0);
254  EXPECT_EQ(
255  dif_rv_core_ibex_configure_addr_translation(&ibex_, slot, bus, kMapping),
256  kDifLocked);
257 
258  EXPECT_READ32(r_regwen, 0);
259  EXPECT_EQ(dif_rv_core_ibex_enable_addr_translation(&ibex_, slot, bus),
260  kDifLocked);
261 
262  EXPECT_READ32(r_regwen, 0);
263  EXPECT_EQ(dif_rv_core_ibex_disable_addr_translation(&ibex_, slot, bus),
264  kDifLocked);
265 
266  // The lock function should quietly do nothing,
267  // if address translation is already locked.
268  EXPECT_READ32(r_regwen, 0);
269  EXPECT_DIF_OK(dif_rv_core_ibex_lock_addr_translation(&ibex_, slot, bus));
270 }
271 
272 TEST_F(AddressTranslationTest, BadArg) {
273  const auto slot = kDifRvCoreIbexAddrTranslationSlot_0;
274  const auto bus = kDifRvCoreIbexAddrTranslationDBus;
275  const auto bad_slot = kDifRvCoreIbexAddrTranslationSlotCount;
276  const auto bad_bus = kDifRvCoreIbexAddrTranslationBusCount;
277 
280  dif_rv_core_ibex_configure_addr_translation(nullptr, slot, bus, mapping));
281  EXPECT_DIF_BADARG(dif_rv_core_ibex_configure_addr_translation(
282  &ibex_, slot, bad_bus, mapping));
283  EXPECT_DIF_BADARG(dif_rv_core_ibex_configure_addr_translation(
284  &ibex_, bad_slot, bus, mapping));
285 
287  dif_rv_core_ibex_read_addr_translation(nullptr, slot, bus, &mapping));
289  dif_rv_core_ibex_read_addr_translation(&ibex_, bad_slot, bus, &mapping));
291  dif_rv_core_ibex_read_addr_translation(&ibex_, slot, bad_bus, &mapping));
293  dif_rv_core_ibex_read_addr_translation(&ibex_, slot, bus, nullptr));
294 
295  EXPECT_DIF_BADARG(dif_rv_core_ibex_lock_addr_translation(nullptr, slot, bus));
297  dif_rv_core_ibex_lock_addr_translation(&ibex_, bad_slot, bus));
299  dif_rv_core_ibex_lock_addr_translation(&ibex_, slot, bad_bus));
300 
302  dif_rv_core_ibex_enable_addr_translation(nullptr, slot, bus));
304  dif_rv_core_ibex_enable_addr_translation(&ibex_, bad_slot, bus));
306  dif_rv_core_ibex_enable_addr_translation(&ibex_, slot, bad_bus));
307 
309  dif_rv_core_ibex_disable_addr_translation(nullptr, slot, bus));
311  dif_rv_core_ibex_disable_addr_translation(&ibex_, bad_slot, bus));
313  dif_rv_core_ibex_disable_addr_translation(&ibex_, slot, bad_bus));
314 }
315 
317  : public RvCoreIbexTestInitialized,
318  public testing::WithParamInterface<
319  std::tuple<uint32_t, dif_rv_core_ibex_error_status_t>> {};
320 
321 TEST_P(ErrorStatusTest, ReadSuccess) {
322  auto reg = std::get<0>(GetParam());
323  auto status = std::get<1>(GetParam());
324 
325  EXPECT_READ32(RV_CORE_IBEX_ERR_STATUS_REG_OFFSET, {{reg, 1}});
326  dif_rv_core_ibex_error_status_t error_status;
327  EXPECT_DIF_OK(dif_rv_core_ibex_get_error_status(&ibex_, &error_status));
328  EXPECT_EQ(status, error_status);
329 }
330 
331 TEST_P(ErrorStatusTest, ClearSuccess) {
332  auto reg = std::get<0>(GetParam());
333  auto status = std::get<1>(GetParam());
334  EXPECT_WRITE32(RV_CORE_IBEX_ERR_STATUS_REG_OFFSET, {{reg, 1}});
335  EXPECT_DIF_OK(dif_rv_core_ibex_clear_error_status(&ibex_, status));
336 }
337 
338 INSTANTIATE_TEST_SUITE_P(
339  ErrorStatusTest, ErrorStatusTest,
340  testing::ValuesIn(
341  std::vector<std::tuple<uint32_t, dif_rv_core_ibex_error_status_t>>{{
342  {RV_CORE_IBEX_ERR_STATUS_REG_INTG_ERR_BIT,
343  kDifRvCoreIbexErrorStatusRegisterTransmissionIntegrity},
344  {RV_CORE_IBEX_ERR_STATUS_FATAL_INTG_ERR_BIT,
345  kDifRvCoreIbexErrorStatusFatalResponseIntegrity},
346  {RV_CORE_IBEX_ERR_STATUS_FATAL_CORE_ERR_BIT,
347  kDifRvCoreIbexErrorStatusFatalInternalError},
348  {RV_CORE_IBEX_ERR_STATUS_RECOV_CORE_ERR_BIT,
349  kDifRvCoreIbexErrorStatusRecoverableInternal},
350  }}));
351 
352 TEST_F(ErrorStatusTest, ReadBadArg) {
353  dif_rv_core_ibex_error_status_t error_status;
354  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_error_status(nullptr, &error_status));
355  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_error_status(&ibex_, nullptr));
356 }
357 
358 TEST_F(ErrorStatusTest, ClearBadArg) {
359  EXPECT_DIF_BADARG(dif_rv_core_ibex_clear_error_status(
360  nullptr, kDifRvCoreIbexErrorStatusRegisterTransmissionIntegrity));
361  EXPECT_DIF_BADARG(dif_rv_core_ibex_clear_error_status(
362  &ibex_, static_cast<dif_rv_core_ibex_error_status_t>(-1)));
363 }
364 
365 class NMITest
366  : public RvCoreIbexTestInitialized,
367  public testing::WithParamInterface<dif_rv_core_ibex_nmi_state_t> {};
368 
369 TEST_F(NMITest, EnableAlertSuccess) {
370  EXPECT_WRITE32(RV_CORE_IBEX_NMI_ENABLE_REG_OFFSET,
371  {{RV_CORE_IBEX_NMI_ENABLE_ALERT_EN_BIT, 1}});
373  dif_rv_core_ibex_enable_nmi(&ibex_, kDifRvCoreIbexNmiSourceAlert));
374 }
375 
376 TEST_F(NMITest, EnableWdogSuccess) {
377  EXPECT_WRITE32(RV_CORE_IBEX_NMI_ENABLE_REG_OFFSET,
378  {{RV_CORE_IBEX_NMI_ENABLE_WDOG_EN_BIT, 1}});
380  dif_rv_core_ibex_enable_nmi(&ibex_, kDifRvCoreIbexNmiSourceWdog));
381 }
382 
383 TEST_F(NMITest, EnableAllSuccess) {
384  EXPECT_WRITE32(RV_CORE_IBEX_NMI_ENABLE_REG_OFFSET,
385  {{RV_CORE_IBEX_NMI_ENABLE_WDOG_EN_BIT, 1},
386  {RV_CORE_IBEX_NMI_ENABLE_ALERT_EN_BIT, 1}});
388  dif_rv_core_ibex_enable_nmi(&ibex_, kDifRvCoreIbexNmiSourceAll));
389 }
390 
391 TEST_F(NMITest, EnableBadArg) {
393  dif_rv_core_ibex_enable_nmi(nullptr, kDifRvCoreIbexNmiSourceWdog));
394  EXPECT_DIF_BADARG(dif_rv_core_ibex_enable_nmi(
395  &ibex_, static_cast<dif_rv_core_ibex_nmi_source_t>(-1)));
396 }
397 
398 TEST_P(NMITest, GetStateSuccess) {
399  dif_rv_core_ibex_nmi_state_t expected_state = GetParam();
400 
401  EXPECT_READ32(
402  RV_CORE_IBEX_NMI_ENABLE_REG_OFFSET,
403  {
404  {RV_CORE_IBEX_NMI_ENABLE_ALERT_EN_BIT, expected_state.alert_enabled},
405  {RV_CORE_IBEX_NMI_ENABLE_WDOG_EN_BIT, expected_state.wdog_enabled},
406  });
407 
408  EXPECT_READ32(
409  RV_CORE_IBEX_NMI_STATE_REG_OFFSET,
410  {
411  {RV_CORE_IBEX_NMI_STATE_ALERT_BIT, expected_state.alert_raised},
412  {RV_CORE_IBEX_NMI_STATE_WDOG_BIT, expected_state.wdog_barked},
413  });
414 
416  EXPECT_DIF_OK(dif_rv_core_ibex_get_nmi_state(&ibex_, &state));
417  EXPECT_EQ(expected_state, state);
418 }
419 
420 INSTANTIATE_TEST_SUITE_P(
421  NMITest, NMITest,
422  testing::ValuesIn(std::vector<dif_rv_core_ibex_nmi_state_t>{{
423  {true, false, false, false},
424  {false, true, false, false},
425  {false, false, true, false},
426  {false, false, false, true},
427  }}));
428 
429 TEST_F(NMITest, GetStateBadArg) {
431  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_nmi_state(nullptr, &nmi_state));
432  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_nmi_state(&ibex_, nullptr));
433 }
434 
435 TEST_F(NMITest, ClearAlertSuccess) {
436  EXPECT_WRITE32(RV_CORE_IBEX_NMI_STATE_REG_OFFSET,
437  {{RV_CORE_IBEX_NMI_STATE_ALERT_BIT, 1}});
439  dif_rv_core_ibex_clear_nmi_state(&ibex_, kDifRvCoreIbexNmiSourceAlert));
440 }
441 
442 TEST_F(NMITest, ClearWdogSuccess) {
443  EXPECT_WRITE32(RV_CORE_IBEX_NMI_STATE_REG_OFFSET,
444  {{RV_CORE_IBEX_NMI_STATE_WDOG_BIT, 1}});
446  dif_rv_core_ibex_clear_nmi_state(&ibex_, kDifRvCoreIbexNmiSourceWdog));
447 }
448 
449 TEST_F(NMITest, ClearAllSuccess) {
450  EXPECT_WRITE32(RV_CORE_IBEX_NMI_STATE_REG_OFFSET,
451  {{RV_CORE_IBEX_NMI_STATE_WDOG_BIT, 1},
452  {RV_CORE_IBEX_NMI_ENABLE_ALERT_EN_BIT, 1}});
454  dif_rv_core_ibex_clear_nmi_state(&ibex_, kDifRvCoreIbexNmiSourceAll));
455 }
456 
457 TEST_F(NMITest, ClearBadArg) {
459  dif_rv_core_ibex_clear_nmi_state(nullptr, kDifRvCoreIbexNmiSourceWdog));
460  EXPECT_DIF_BADARG(dif_rv_core_ibex_clear_nmi_state(
461  &ibex_, static_cast<dif_rv_core_ibex_nmi_source_t>(-1)));
462 }
463 
465 
466 TEST_F(RndTest, ReadSuccess) {
467  EXPECT_READ32(RV_CORE_IBEX_RND_DATA_REG_OFFSET, 0xf55ef65e);
468 
469  uint32_t data;
470  EXPECT_DIF_OK(dif_rv_core_ibex_read_rnd_data(&ibex_, &data));
471  EXPECT_EQ(data, 0xf55ef65e);
472 }
473 
474 TEST_F(RndTest, ReadBadArg) {
475  uint32_t data;
476  EXPECT_DIF_BADARG(dif_rv_core_ibex_read_rnd_data(nullptr, &data));
477  EXPECT_DIF_BADARG(dif_rv_core_ibex_read_rnd_data(&ibex_, nullptr));
478 }
479 
480 TEST_F(RndTest, StatusValid) {
481  EXPECT_READ32(RV_CORE_IBEX_RND_STATUS_REG_OFFSET,
482  {{RV_CORE_IBEX_RND_STATUS_RND_DATA_VALID_BIT, true}});
483 
484  dif_rv_core_ibex_rnd_status_t status;
485  EXPECT_DIF_OK(dif_rv_core_ibex_get_rnd_status(&ibex_, &status));
486  EXPECT_EQ(status, kDifRvCoreIbexRndStatusValid);
487 }
488 
489 TEST_F(RndTest, StatusFipsCompliant) {
490  EXPECT_READ32(RV_CORE_IBEX_RND_STATUS_REG_OFFSET,
491  {{RV_CORE_IBEX_RND_STATUS_RND_DATA_FIPS_BIT, true}});
492 
493  dif_rv_core_ibex_rnd_status_t status;
494  EXPECT_DIF_OK(dif_rv_core_ibex_get_rnd_status(&ibex_, &status));
495  EXPECT_EQ(status, kDifRvCoreIbexRndStatusFipsCompliant);
496 }
497 
498 TEST_F(RndTest, StatusBadArg) {
499  dif_rv_core_ibex_rnd_status_t status;
500  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_rnd_status(nullptr, &status));
501  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_rnd_status(&ibex_, nullptr));
502 }
503 
505 
506 TEST_F(FpgaInfoTest, ReadSuccess) {
507  EXPECT_READ32(RV_CORE_IBEX_FPGA_INFO_REG_OFFSET, 0xf55ef65e);
508  dif_rv_core_ibex_fpga_info_t info;
509  EXPECT_DIF_OK(dif_rv_core_ibex_read_fpga_info(&ibex_, &info));
510  EXPECT_EQ(info, 0xf55ef65e);
511 }
512 
513 TEST_F(FpgaInfoTest, ReadZero) {
514  EXPECT_READ32(RV_CORE_IBEX_FPGA_INFO_REG_OFFSET, 0);
515  dif_rv_core_ibex_fpga_info_t info;
516  EXPECT_DIF_OK(dif_rv_core_ibex_read_fpga_info(&ibex_, &info));
517  EXPECT_EQ(info, 0);
518 }
519 
520 TEST_F(FpgaInfoTest, ReadBadArg) {
521  dif_rv_core_ibex_fpga_info_t info;
522  EXPECT_DIF_BADARG(dif_rv_core_ibex_read_fpga_info(nullptr, &info));
523  EXPECT_DIF_BADARG(dif_rv_core_ibex_read_fpga_info(&ibex_, nullptr));
524 }
525 
527 
528 TEST_F(FatalErrorAlertTest, ReadAlertEnabled) {
529  bool enabled;
530 
531  EXPECT_READ32(RV_CORE_IBEX_SW_FATAL_ERR_REG_OFFSET, 0x01);
532  EXPECT_DIF_OK(dif_rv_core_ibex_get_sw_fatal_err_alert(&ibex_, &enabled));
533  EXPECT_TRUE(enabled);
534 
535  EXPECT_READ32(RV_CORE_IBEX_SW_FATAL_ERR_REG_OFFSET, kMultiBitBool4True);
536  EXPECT_DIF_OK(dif_rv_core_ibex_get_sw_fatal_err_alert(&ibex_, &enabled));
537  EXPECT_TRUE(enabled);
538 }
539 
540 TEST_F(FatalErrorAlertTest, ReadAlertDisabled) {
541  bool enabled;
542 
543  EXPECT_READ32(RV_CORE_IBEX_SW_FATAL_ERR_REG_OFFSET, kMultiBitBool4False);
544  EXPECT_DIF_OK(dif_rv_core_ibex_get_sw_fatal_err_alert(&ibex_, &enabled));
545  EXPECT_FALSE(enabled);
546 }
547 
548 TEST_F(FatalErrorAlertTest, TriggerSuccess) {
549  EXPECT_WRITE32(RV_CORE_IBEX_SW_FATAL_ERR_REG_OFFSET, kMultiBitBool4True);
550  EXPECT_DIF_OK(dif_rv_core_ibex_trigger_sw_fatal_err_alert(&ibex_));
551 }
552 
553 TEST_F(FatalErrorAlertTest, ReadBadArg) {
554  bool enabled;
555  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_sw_fatal_err_alert(nullptr, &enabled));
556  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_sw_fatal_err_alert(&ibex_, nullptr));
557 }
558 
559 TEST_F(FatalErrorAlertTest, TriggerBadArg) {
560  EXPECT_DIF_BADARG(dif_rv_core_ibex_trigger_sw_fatal_err_alert(nullptr));
561 }
562 
564 
565 TEST_F(RecoverableErrorAlertTest, ReadAlertEnabled) {
566  bool enabled;
567 
568  EXPECT_READ32(RV_CORE_IBEX_SW_RECOV_ERR_REG_OFFSET, 0x01);
569  EXPECT_DIF_OK(dif_rv_core_ibex_get_sw_recov_err_alert(&ibex_, &enabled));
570  EXPECT_TRUE(enabled);
571 
572  EXPECT_READ32(RV_CORE_IBEX_SW_RECOV_ERR_REG_OFFSET, kMultiBitBool4True);
573  EXPECT_DIF_OK(dif_rv_core_ibex_get_sw_recov_err_alert(&ibex_, &enabled));
574  EXPECT_TRUE(enabled);
575 }
576 
577 TEST_F(RecoverableErrorAlertTest, ReadAlertDisabled) {
578  bool enabled;
579 
580  EXPECT_READ32(RV_CORE_IBEX_SW_RECOV_ERR_REG_OFFSET, kMultiBitBool4False);
581  EXPECT_DIF_OK(dif_rv_core_ibex_get_sw_recov_err_alert(&ibex_, &enabled));
582  EXPECT_FALSE(enabled);
583 }
584 
585 TEST_F(RecoverableErrorAlertTest, TriggerSuccess) {
586  EXPECT_WRITE32(RV_CORE_IBEX_SW_RECOV_ERR_REG_OFFSET, kMultiBitBool4True);
587  EXPECT_DIF_OK(dif_rv_core_ibex_trigger_sw_recov_err_alert(&ibex_));
588 }
589 
590 TEST_F(RecoverableErrorAlertTest, ReadBadArg) {
591  bool enabled;
592  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_sw_recov_err_alert(nullptr, &enabled));
593  EXPECT_DIF_BADARG(dif_rv_core_ibex_get_sw_recov_err_alert(&ibex_, nullptr));
594 }
595 
596 TEST_F(RecoverableErrorAlertTest, TriggerBadArg) {
597  EXPECT_DIF_BADARG(dif_rv_core_ibex_trigger_sw_recov_err_alert(nullptr));
598 }
599 
601 
602 TEST_F(ParseCrashDumpTest, DoubleFault) {
604  .fault_state = {.mtval = 0x55555555,
605  .mpec = 0x51555555,
606  .mdaa = 0x55515555,
607  .mnpc = 0x55555155,
608  .mcpc = 0x55555551},
609  .previous_fault_state = {.mtval = 0x15555555, .mpec = 0x25555555},
610  .double_fault = kDifToggleEnabled,
611  };
613 
614  uint32_t
615  cpu_info[sizeof(dif_rv_core_ibex_crash_dump_info_t) / sizeof(uint32_t)];
616  memcpy(cpu_info, &ref, sizeof(cpu_info));
618  dif_rv_core_ibex_parse_crash_dump(&ibex_, cpu_info, sizeof(ref), &dump));
619  EXPECT_EQ(dump, ref);
620 }
621 
622 TEST_F(ParseCrashDumpTest, SingleFault) {
624  .fault_state = {.mtval = 0x55555555,
625  .mpec = 0x51555555,
626  .mdaa = 0x55515555,
627  .mnpc = 0x55555155,
628  .mcpc = 0x55555551},
629  .previous_fault_state = {.mtval = 0x15555555, .mpec = 0x25555555},
630  .double_fault = kDifToggleDisabled,
631  };
633 
634  uint32_t
635  cpu_info[sizeof(dif_rv_core_ibex_crash_dump_info_t) / sizeof(uint32_t)];
636  memcpy(cpu_info, &ref, sizeof(cpu_info));
638  dif_rv_core_ibex_parse_crash_dump(&ibex_, cpu_info, sizeof(ref), &dump));
639  EXPECT_EQ(dump, ref);
640 }
641 
642 TEST_F(ParseCrashDumpTest, ReadBadArg) {
644  uint32_t info[9];
645  EXPECT_DIF_BADARG(dif_rv_core_ibex_parse_crash_dump(nullptr, info, 9, &out));
647  dif_rv_core_ibex_parse_crash_dump(&ibex_, nullptr, 9, &out));
648  EXPECT_DIF_BADARG(dif_rv_core_ibex_parse_crash_dump(&ibex_, info, 7, &out));
650  dif_rv_core_ibex_parse_crash_dump(&ibex_, info, 9, nullptr));
651 }
652 
653 } // namespace dif_rv_core_ibex_test