blob: 4faedb07e91830dafb385a49d307df12e7cefedd [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "sw/device/lib/base/status.h"
#include <stdbool.h>
#include <stdint.h>
#include "sw/device/lib/base/bitfield.h"
const uint32_t MODULE_ID = 0;
static const char *basename(const char *file) {
const char *f = file;
// Go to the end of the string.
while (*f)
++f;
// Back up to the start of the last filename path component.
while (f > file && f[-1] != '/' && f[-1] != '\\')
--f;
return f;
}
status_t status_create(absl_status_t code, uint32_t module_id, const char *file,
int32_t arg) {
if (code == kOk) {
if (arg >= 0) {
return (status_t){.value = arg};
} else {
// If you find yourself here, then someone returned a OK_STATUS
// a negative value.
arg = __LINE__;
}
}
/**
* Our status(error) codes are arranged as a packed bitfield:
*
* 32 31 26 21 16 5 0
* +---+-------+-------+-------+-------------+-------+
* | | 15 bit | 11 bit | 5 bit |
* | s | Module Identifier | Line Number | code |
* +---+-------+-------+-------+-------------+-------+
*
* The sign bit is set on all not-Ok statuses, thus proviging a covenient
* overloaded return value from functions that may return an error.
*/
if (module_id == 0) {
// First three characters of the filename.
const char *f = basename(file);
module_id = MAKE_MODULE_ID(f[0], f[1], f[2]);
}
// At this point, the module_id is already packed into the correct bitfield.
return (status_t){
.value = (int32_t)(module_id |
bitfield_bit32_write(0, STATUS_BIT_ERROR, true) |
bitfield_field32_write(0, STATUS_FIELD_CODE, code) |
bitfield_field32_write(0, STATUS_FIELD_ARG,
(uint32_t)arg))};
}
const char *status_codes[] = {
"Ok",
"Cancelled",
"Unknown",
"InvalidArgument",
"DeadlineExceeded",
"NotFound",
"AlreadyExists",
"PermissionDenied",
"ResourceExhausted",
"FailedPrecondition",
"Aborted",
"OutOfRange",
"Unimplemented",
"Internal",
"Unavailable",
"DataLoss",
"Unauthenticated",
"Undefined17",
"Undefined18",
"Undefined19",
"Undefined20",
"Undefined21",
"Undefined22",
"Undefined23",
"Undefined24",
"Undefined25",
"Undefined26",
"Undefined27",
"Undefined28",
"Undefined29",
"Undefined30",
"Undefined31",
// A "ErrorError" means the error bit is set but the err field is kOk.
"ErrorError",
};
bool status_extract(status_t s, const char **code, int32_t *arg, char *mod_id) {
size_t err = (size_t)status_err(s);
if (s.value < 0 && err == 0) {
err = sizeof(status_codes) / sizeof(status_codes[0]) - 1;
}
*code = status_codes[err];
if (err) {
*arg = (int32_t)bitfield_field32_read((uint32_t)s.value, STATUS_FIELD_ARG);
uint32_t module_id =
bitfield_field32_read((uint32_t)s.value, STATUS_FIELD_MODULE_ID);
*mod_id++ = '@' + ((module_id >> 0) & 0x1F);
*mod_id++ = '@' + ((module_id >> 5) & 0x1F);
*mod_id++ = '@' + ((module_id >> 10) & 0x1F);
return true;
} else {
*arg = s.value;
return false;
}
}