Software APIs
status.h
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 #ifndef OPENTITAN_SW_DEVICE_LIB_BASE_INTERNAL_STATUS_H_
6 #define OPENTITAN_SW_DEVICE_LIB_BASE_INTERNAL_STATUS_H_
7 
8 #ifndef USING_INTERNAL_STATUS
9 #error "Do not include internal/status.h directly. Include status.h instead."
10 #endif
12 
13 #define USING_ABSL_STATUS
14 #include "sw/device/lib/base/internal/absl_status.h"
15 #undef USING_ABSL_STATUS
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 /**
21  * We use the error category codes from absl_status.h. We build a packed
22  * status value that identifies the source of the error (in the form of the
23  * module identifier and line number).
24  *
25  * By default, the module identifier is the first three letters of the
26  * source filename. The identifier can be overridden (per-module) with the
27  * DECLARE_MODULE_ID macro.
28  *
29  * Our status codes are arranged as a packed bitfield, with the sign
30  * bit signifying whether the value represents a result or an error.
31  *
32  * All Ok (good) values:
33  * 31 0
34  * +---+---------------------------------------------+
35  * | | 31 bit |
36  * | 0 | Result |
37  * +---+---------------------------------------------+
38  *
39  * All Error values:
40  * 31 26 21 16 5 0
41  * +---+-------+-------+-------+-------------+-------+
42  * | | 15 bit | 11 bit | 5 bit |
43  * | 1 | Module Identifier | Line Number | code |
44  * +---+-------+-------+-------+-------------+-------+
45  *
46  * The module identifier value is interpreted as three 5-bit fields
47  * representing the characters [0x40..0x5F] (e.g. [@ABC ... _]).
48  */
49 
50 #define STATUS_FIELD_CODE ((bitfield_field32_t){.mask = 0x1f, .index = 0})
51 #define STATUS_FIELD_ARG ((bitfield_field32_t){.mask = 0x7ff, .index = 5})
52 #define STATUS_FIELD_MODULE_ID \
53  ((bitfield_field32_t){.mask = 0x7fff, .index = 16})
54 #define STATUS_BIT_ERROR 31
55 
56 // clang-format off
57 #define ASCII_5BIT(v) ( \
58  /*uppercase characters*/ (v) >= '@' && (v) <= '_' ? OT_UNSIGNED((v) - '@') \
59  /*lower cvt upper*/ : (v) >= '`' && (v) <= 'z' ? OT_UNSIGNED((v) - '`') \
60  /*else cvt underscore*/ : OT_UNSIGNED('_' - '@') \
61  )
62 // clang-format on
63 
64 /*
65  * Creates a module ID from 3 ASCII characters.
66  *
67  * Note: the result is pre-shifted into the module identifier position within
68  * a `status_t`.
69  * - The kStatusModuleId can simply be ORed in when constucting a `status_t`.
70  * - The value of MAKE_MODULE_ID can be used in constructing constants for
71  * types compatible with `status_t`.
72  *
73  * To declare a module-id in one of your own files:
74  * #define MODULE_ID MAKE_MODULE_ID('a', 'b', 'c')
75  */
76 #define MAKE_MODULE_ID(a, b, c) \
77  (ASCII_5BIT(a) << 16) | (ASCII_5BIT(b) << 21) | (ASCII_5BIT(c) << 26)
78 
79 #ifdef __cplusplus
80 }
81 #endif
82 #endif // OPENTITAN_SW_DEVICE_LIB_BASE_INTERNAL_STATUS_H_