Software APIs
alert_handler_testutils.c
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/testing/alert_handler_testutils.h"
6 
7 #include "dt/dt_alert_handler.h" // Generated
8 #include "dt/dt_api.h" // Generated
13 #include "sw/device/lib/testing/test_framework/check.h"
14 
15 #include "alert_handler_regs.h" // Generated
16 
17 #define MODULE_ID MAKE_MODULE_ID('a', 'h', 't')
18 
19 /**
20  * This is used to traverse the dump treating it as an array of bits, and
21  * extract a number of bits placing them in a uint32_t. The word and bit index
22  * are updated by num_bits before returning.
23  */
24 static uint32_t get_next_n_bits(
25  int num_bits, const dif_rstmgr_alert_info_dump_segment_t *dump,
26  int *word_index, int *bit_index) {
27  CHECK(num_bits <= 32);
28  CHECK(*bit_index < 32);
29  uint32_t word = dump[*word_index] >> *bit_index;
30  if (*bit_index + num_bits >= 32) {
31  (*word_index) += 1;
32  *bit_index = *bit_index + num_bits - 32;
33  } else {
34  *bit_index += num_bits;
35  }
36  word &= (1 << num_bits) - 1;
37  return word;
38 }
39 
40 status_t alert_handler_testutils_info_parse(
41  const dif_rstmgr_alert_info_dump_segment_t *dump, int dump_size,
43  int word_index = 0;
44  int bit_index = 0;
45  for (int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
46  info->class_esc_state[i] =
47  get_next_n_bits(3, dump, &word_index, &bit_index);
48  }
49  for (int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
50  info->class_esc_cnt[i] = get_next_n_bits(32, dump, &word_index, &bit_index);
51  }
52  for (int i = 0; i < ALERT_HANDLER_PARAM_N_CLASSES; ++i) {
53  info->class_accum_cnt[i] =
54  (uint16_t)get_next_n_bits(16, dump, &word_index, &bit_index);
55  }
56  info->loc_alert_cause =
57  (uint8_t)get_next_n_bits(7, dump, &word_index, &bit_index);
58  TRY_CHECK(word_index < dump_size);
59  for (int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
60  info->alert_cause[i] = get_next_n_bits(1, dump, &word_index, &bit_index);
61  }
62  TRY_CHECK(word_index < dump_size);
63  return OK_STATUS();
64 }
65 
66 void alert_handler_testutils_info_dump(
67  const alert_handler_testutils_info_t *info) {
68  LOG_INFO("alert_info:");
69  LOG_INFO("esc_state [0]=%x, [1]=%x, [2]=%x, [3]=%x", info->class_esc_state[0],
70  info->class_esc_state[1], info->class_esc_state[2],
71  info->class_esc_state[3]);
72  LOG_INFO("esc_cnt [0]=0x%x, [1]=0x%x, [2]=0x%x, [3]=0x%x",
73  info->class_esc_cnt[0], info->class_esc_cnt[1],
74  info->class_esc_cnt[2], info->class_esc_cnt[3]);
75  LOG_INFO("accum_cnt [0]=0x%x, [1]=0x%x, [2]=0x%x, [3]=0x%x",
76  info->class_accum_cnt[0], info->class_accum_cnt[1],
77  info->class_accum_cnt[2], info->class_accum_cnt[3]);
78  LOG_INFO("loc_alert_cause=0x%x", info->loc_alert_cause);
79  int set_count = 0;
80  LOG_INFO("alert_cause bits set:");
81  // Typically very few bits are set, so it is more clear to only show the
82  // on bits.
83  for (int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
84  if (info->alert_cause[i]) {
85  LOG_INFO("alert_cause[%d] = 1", i);
86  ++set_count;
87  }
88  }
89  if (set_count == 0) {
90  LOG_INFO("No bits set");
91  }
92 }
93 
94 status_t alert_handler_testutils_configure_all(
95  const dif_alert_handler_t *alert_handler, dif_alert_handler_config_t config,
96  dif_toggle_t locked) {
97  TRY_CHECK(alert_handler != NULL);
98  TRY_CHECK(dif_is_valid_toggle(locked));
99 
100  // Check lengths of alert, local alert, and class arrays.
101  TRY_CHECK((config.alerts_len > 0 && config.alerts != NULL &&
102  config.alert_classes != NULL) ||
103  (config.alerts_len == 0 && config.alerts == NULL &&
104  config.alert_classes == NULL));
105  TRY_CHECK((config.local_alerts_len > 0 && config.local_alerts != NULL &&
106  config.local_alert_classes != NULL) ||
107  (config.local_alerts_len == 0 && config.local_alerts == NULL &&
108  config.local_alert_classes == NULL));
109  TRY_CHECK((config.classes_len > 0 && config.classes != NULL &&
110  config.class_configs != NULL) ||
111  (config.classes_len == 0 && config.classes == NULL &&
112  config.class_configs == NULL));
113 
114  // Check that the provided ping timeout actually fits in the timeout
115  // register, which is smaller than a native word length.
116  TRY_CHECK(
117  config.ping_timeout <=
118  ALERT_HANDLER_PING_TIMEOUT_CYC_SHADOWED_PING_TIMEOUT_CYC_SHADOWED_MASK);
119 
120  // Configure and enable the requested alerts.
121  for (int i = 0; i < config.alerts_len; ++i) {
122  TRY(dif_alert_handler_configure_alert(alert_handler, config.alerts[i],
123  config.alert_classes[i],
124  kDifToggleEnabled, locked));
125  }
126 
127  // Configure and enable the requested local alerts.
128  for (int i = 0; i < config.local_alerts_len; ++i) {
130  alert_handler, config.local_alerts[i], config.local_alert_classes[i],
131  kDifToggleEnabled, locked));
132  }
133 
134  // Configure and enable the requested classes.
135  for (int i = 0; i < config.classes_len; ++i) {
136  TRY(dif_alert_handler_configure_class(alert_handler, config.classes[i],
137  config.class_configs[i],
138  kDifToggleEnabled, locked));
139  }
140 
141  // Configure the ping timer.
142  TRY(dif_alert_handler_configure_ping_timer(alert_handler, config.ping_timeout,
143  kDifToggleEnabled, locked));
144 
145  return OK_STATUS();
146 }
147 
148 status_t alert_handler_testutils_get_cycles_from_us(uint64_t microseconds,
149  uint32_t *cycles) {
150  uint64_t cycles_ = udiv64_slow(
151  microseconds * dt_clock_frequency(dt_alert_handler_clock(
152  (dt_alert_handler_t)0, kDtAlertHandlerClockClk)),
153  1000000,
154  /*rem_out=*/NULL);
155  TRY_CHECK(cycles_ < UINT32_MAX,
156  "The value 0x%08x%08x can't fit into the 32 bits timer counter.",
157  (uint32_t)(cycles_ >> 32), (uint32_t)cycles_);
158  *cycles = (uint32_t)cycles_;
159  return OK_STATUS();
160 }
161 
162 uint32_t alert_handler_testutils_cycle_rescaling_factor(void) {
163  return kDeviceType == kDeviceSimDV ? 1 : 10;
164 }