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 */
24static 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
40status_t alert_handler_testutils_info_parse(
41 const dif_rstmgr_alert_info_dump_segment_t *dump, int dump_size,
42 alert_handler_testutils_info_t *info) {
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
66void 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
94status_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) {
129 TRY(dif_alert_handler_configure_local_alert(
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
148status_t alert_handler_testutils_get_cycles_from_us(uint64_t microseconds,
149 uint32_t *cycles) {
150 uint64_t cycles_ = udiv64_slow(
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
162uint32_t alert_handler_testutils_cycle_rescaling_factor(void) {
163 return kDeviceType == kDeviceSimDV ? 1 : 10;
164}