Software APIs
log.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
6
7#include <assert.h>
8
13
14/**
15 * Ensure that log_fields_t is always 20 bytes.
16 *
17 * The assertion below helps prevent inadvertant changes to the struct.
18 * Please see the description of log_fields_t in log.h for more details.
19 */
20static_assert(sizeof(log_fields_t) == 20,
21 "log_fields_t must always be 20 bytes.");
22
23/**
24 * Converts a severity to a static string.
25 */
26static const char *stringify_severity(log_severity_t severity) {
27 switch (severity) {
28 case kLogSeverityInfo:
29 return "I";
30 case kLogSeverityWarn:
31 return "W";
32 case kLogSeverityError:
33 return "E";
34 case kLogSeverityFatal:
35 return "F";
36 default:
37 return "?";
38 }
39}
40
41/**
42 * Logs `log` and the values that follow to stdout.
43 *
44 * @param log the log data to log.
45 * @param ... format parameters matching the format string.
46 */
47void base_log_internal_core(const log_fields_t *log, ...) {
48 size_t file_name_len =
49 (size_t)(((const char *)memchr(log->file_name, '\0', PTRDIFF_MAX)) -
50 log->file_name);
51 const char *base_name = memrchr(log->file_name, '/', file_name_len);
52 if (base_name == NULL) {
53 base_name = log->file_name;
54 } else {
55 ++base_name; // Remove the final '/'.
56 }
57
58 // A small global counter that increments with each log line. This can be
59 // useful for seeing how many times this function has been called, even if
60 // nothing was printed for some time.
61 static uint16_t global_log_counter = 0;
62
63 base_printf("%s%05d %s:%d] ", stringify_severity(log->severity),
64 global_log_counter, base_name, log->line);
65 ++global_log_counter;
66
67 va_list args;
68 va_start(args, log);
69 base_vprintf(log->format, args);
70 va_end(args);
71
72 base_printf("\r\n");
73}
74
75/**
76 * Logs `log` and the values that follow in an efficient, DV-testbench
77 * specific way, which bypasses the UART.
78 *
79 * @param log a pointer to log data to log. Note that this pointer is likely to
80 * be invalid at runtime, since the pointed-to data will have been
81 * stripped from the binary.
82 * @param nargs the number of arguments passed to the format string.
83 * @param ... format parameters matching the format string.
84 */
85void base_log_internal_dv(const log_fields_t *log, uint32_t nargs, ...) {
86 mmio_region_t log_device =
87 mmio_region_from_addr(device_log_bypass_uart_address());
88 mmio_region_write32(log_device, 0x0, (uintptr_t)log);
89
90 va_list args;
91 va_start(args, nargs);
92 for (int i = 0; i < nargs; ++i) {
93 mmio_region_write32(log_device, 0x0, va_arg(args, uint32_t));
94 }
95 va_end(args);
96}