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
5
#include "
sw/device/lib/runtime/log.h
"
6
7
#include <assert.h>
8
9
#include "
sw/device/lib/arch/device.h
"
10
#include "
sw/device/lib/base/memory.h
"
11
#include "
sw/device/lib/base/mmio.h
"
12
#include "
sw/device/lib/runtime/print.h
"
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, ...) {
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
}
sw
device
lib
runtime
log.c
Return to
OpenTitan Documentation