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
17extern "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_