Software APIs
status.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/base/status.h"
6
7#include <stdbool.h>
8#include <stdint.h>
9
11
12const uint32_t MODULE_ID = 0;
13
14static const char *basename(const char *file, size_t *basename_len) {
15 const char *f = file;
16 // Go to the end of the string.
17 while (*f)
18 ++f;
19 // Back up to the start of the last filename path component.
20 *basename_len = 0;
21 while (f > file && f[-1] != '/' && f[-1] != '\\') {
22 ++(*basename_len);
23 --f;
24 }
25 return f;
26}
27
28status_t status_create(absl_status_t code, uint32_t module_id, const char *file,
29 int32_t arg) {
30 if (code == kOk) {
31 if (arg >= 0) {
32 return (status_t){.value = arg};
33 } else {
34 // If you find yourself here, then someone returned a OK_STATUS
35 // a negative value.
36 arg = __LINE__;
37 }
38 }
39 /**
40 * Our status(error) codes are arranged as a packed bitfield:
41 *
42 * 32 31 26 21 16 5 0
43 * +---+-------+-------+-------+-------------+-------+
44 * | | 15 bit | 11 bit | 5 bit |
45 * | s | Module Identifier | Line Number | code |
46 * +---+-------+-------+-------+-------------+-------+
47 *
48 * The sign bit is set on all not-Ok statuses, thus proviging a covenient
49 * overloaded return value from functions that may return an error.
50 */
51 if (module_id == 0) {
52 // First three characters of the filename.
53 size_t basename_len = 0;
54 const char *f = basename(file, &basename_len);
55 module_id = basename_len >= 3 ? MAKE_MODULE_ID(f[0], f[1], f[2])
56 : MAKE_MODULE_ID('u', 'n', 'd');
57 }
58 // At this point, the module_id is already packed into the correct bitfield.
59 return (status_t){
60 .value = (int32_t)(module_id |
61 bitfield_bit32_write(0, STATUS_BIT_ERROR, true) |
62 bitfield_field32_write(0, STATUS_FIELD_CODE, code) |
63 bitfield_field32_write(0, STATUS_FIELD_ARG,
64 (uint32_t)arg))};
65}
66
67const char *status_codes[] = {
68 "Ok",
69 "Cancelled",
70 "Unknown",
71 "InvalidArgument",
72 "DeadlineExceeded",
73 "NotFound",
74 "AlreadyExists",
75 "PermissionDenied",
76 "ResourceExhausted",
77 "FailedPrecondition",
78 "Aborted",
79 "OutOfRange",
80 "Unimplemented",
81 "Internal",
82 "Unavailable",
83 "DataLoss",
84 "Unauthenticated",
85
86 "Undefined17",
87 "Undefined18",
88 "Undefined19",
89 "Undefined20",
90 "Undefined21",
91 "Undefined22",
92 "Undefined23",
93 "Undefined24",
94 "Undefined25",
95 "Undefined26",
96 "Undefined27",
97 "Undefined28",
98 "Undefined29",
99 "Undefined30",
100 "Undefined31",
101
102 // A "ErrorError" means the error bit is set but the err field is kOk.
103 "ErrorError",
104};
105
106bool status_extract(status_t s, const char **code, int32_t *arg, char *mod_id) {
107 size_t err = (size_t)status_err(s);
108 if (s.value < 0 && err == 0) {
109 err = sizeof(status_codes) / sizeof(status_codes[0]) - 1;
110 }
111 *code = status_codes[err];
112 if (err) {
113 *arg = (int32_t)bitfield_field32_read((uint32_t)s.value, STATUS_FIELD_ARG);
114 uint32_t module_id =
115 bitfield_field32_read((uint32_t)s.value, STATUS_FIELD_MODULE_ID);
116 *mod_id++ = '@' + ((module_id >> 0) & 0x1F);
117 *mod_id++ = '@' + ((module_id >> 5) & 0x1F);
118 *mod_id++ = '@' + ((module_id >> 10) & 0x1F);
119 return true;
120 } else {
121 *arg = s.value;
122 return false;
123 }
124}
125
126extern bool status_ok(status_t s);
127extern absl_status_t status_err(status_t s);
128
129// This is a weak implementation that does nothing. This way it can easily be
130// overidden and does not require every user of status to manually add a
131// dependency.
133void status_report(status_t value) { (void)value; }