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