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/*
57 * Creates a module ID from 3 ASCII characters.
58 *
59 * To declare a module-id in one of your own files:
60 * #define MODULE_ID MAKE_MODULE_ID('a', 'b', 'c')
61 */
62#define MAKE_MODULE_ID(a, b, c) \
63 (uint32_t)(((((a)&0xff) << 16) | (((b)&0xff) << 8) | ((c)&0xff)))
64
65static inline uint8_t __status_ascii_5bit(uint8_t c) {
66 if (c >= '@' && c <= '_') {
67 return c - '@';
68 } else if (c >= '`' && c <= 'z') {
69 return c - '`';
70 } else {
71 return '_' - '@';
72 }
73}
74
75/** Encode a module ID created by MAKE_MODULE_ID.
76 *
77 * The resulting encoding is a 15 bit value which can be put inside the
78 * STATUS_FIELD_MODULE_ID.
79 *
80 * @param module_id Module ID created by MAKE_MODULE_ID.
81 * @return Encoding suitable for use inside the Module Identifier field of
82 * status_t.
83 */
84static inline uint32_t status_encode_module_id(uint32_t module_id) {
85 return (uint32_t)__status_ascii_5bit((uint8_t)(module_id >> 16)) |
86 ((uint32_t)__status_ascii_5bit((uint8_t)(module_id >> 8)) << 5) |
87 ((uint32_t)__status_ascii_5bit((uint8_t)module_id) << 10);
88}
89
90#ifdef __cplusplus
91}
92#endif
93#endif // OPENTITAN_SW_DEVICE_LIB_BASE_INTERNAL_STATUS_H_