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  */
20 static_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  */
26 static 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  */
47 void 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  */
85 void base_log_internal_dv(const log_fields_t *log, uint32_t nargs, ...) {
87  mmio_region_write32(log_device, 0x0, (uintptr_t)log);
88 
89  va_list args;
90  va_start(args, nargs);
91  for (int i = 0; i < nargs; ++i) {
92  mmio_region_write32(log_device, 0x0, va_arg(args, uint32_t));
93  }
94  va_end(args);
95 }