Skip to content

Commit e9c48b8

Browse files
committed
[sw] Add DV_LOG_* macros for SW-to-DV logging
Each call site places a log_fields_t entry in a new .logs.fields ELF section; extract_sw_logs.py produces the database consumed by sw_logger_if to decode printf-style messages at simulation start, with no UART overhead. Add mocha_system_dv_log() to the HAL for CHERI-safe access to the log write port (0x2002_0008). Add the .logs.fields section to the linker script after .rodata so string constants are resolved before log entries are laid out. Add dv_log.h/c implementing the DV_LOG_INFO/WARNING/ERROR/ FATAL macros and the runtime dv_log_write() function. Add dv_log_smoketest to verify the end-to-end path. Signed-off-by: martin-velay <mvelay@lowrisc.org>
1 parent 70f2f23 commit e9c48b8

8 files changed

Lines changed: 121 additions & 1 deletion

File tree

sw/device/lib/boot/mocha.ld

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ SECTIONS {
3030
. = ALIGN(8);
3131
} > ram
3232

33+
/* DV simulation log database. Each call site puts a log_fields_t entry here.
34+
* extract_sw_logs.py reads the ELF section to produce a .logs.txt database
35+
* consumed by sw_logger_if at simulation start. The first word is the section
36+
* load address (header used by extract_sw_logs.py to map each entry to its
37+
* runtime address). */
38+
.logs.fields : {
39+
QUAD(LOADADDR(.logs.fields));
40+
KEEP(*(.logs.fields))
41+
. = ALIGN(8);
42+
} > ram
43+
3344
/* capability relocation entries */
3445
/* __start___cap_relocs and __stop___cap_relocs are provided by the toolchain */
3546
__cap_relocs : {

sw/device/lib/hal/mocha.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
static const uintptr_t rom_base = 0x80000ul;
1515
static const uintptr_t mailbox_base = 0x20010000ul;
1616
static const uintptr_t dv_test_status_base = 0x20020000ul;
17+
static const uintptr_t dv_log_base = 0x20020008ul;
1718
static const uintptr_t ethernet_base = 0x30000000ul;
1819
static const uintptr_t gpio_base = 0x40000000ul;
1920
static const uintptr_t clkmgr_base = 0x40020000ul;
@@ -201,3 +202,12 @@ void *mocha_system_dv_test_status(void)
201202
return (void *)dv_test_status_base;
202203
#endif /* defined(__riscv_zcherihybrid) */
203204
}
205+
206+
void *mocha_system_dv_log(void)
207+
{
208+
#if defined(__riscv_zcherihybrid)
209+
return create_mmio_capability(dv_log_base, 0x4u);
210+
#else /* !defined(__riscv_zcherihybrid) */
211+
return (void *)dv_log_base;
212+
#endif /* defined(__riscv_zcherihybrid) */
213+
}

sw/device/lib/hal/mocha.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,4 @@ plic_t mocha_system_plic(void);
5252
void *mocha_system_dram(void);
5353

5454
void *mocha_system_dv_test_status(void);
55+
void *mocha_system_dv_log(void);

sw/device/lib/test_framework/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
44

5-
set(SRCS main.c)
5+
set(SRCS main.c dv_log.c)
66
set(LIBS hal startup runtime)
77

88
mocha_add_library(NAME test_framework SOURCES ${SRCS} LIBRARIES ${LIBS})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright lowRISC contributors (COSMIC project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "test_framework/dv_log.h"
6+
7+
#include <stdarg.h>
8+
9+
#include "hal/mmio.h"
10+
#include "hal/mocha.h"
11+
12+
void dv_log_write(const log_fields_t *log, ...)
13+
{
14+
void *port = mocha_system_dv_log();
15+
DEV_WRITE(port, (uint32_t)(uintptr_t)log);
16+
17+
va_list args;
18+
va_start(args, log);
19+
for (uint32_t i = 0; i < log->nargs; i++) {
20+
DEV_WRITE(port, va_arg(args, uint32_t));
21+
}
22+
va_end(args);
23+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright lowRISC contributors (COSMIC project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#pragma once
6+
7+
#include <stdint.h>
8+
9+
// SW-to-DV logging: writes a log_fields_t entry address + arguments to
10+
// SW_DV_LOG_ADDR; sw_logger_if reconstructs the formatted string in simulation.
11+
12+
// const char * for string fields: required for a valid C99 static initialiser
13+
// (pointer-to-integer casts are not constant expressions). extract_sw_logs.py
14+
// detects the rv64 ELF class and uses '<I4xQIIQ' (32 B) instead of '<IIIII'.
15+
typedef struct {
16+
uint32_t severity;
17+
const char *file;
18+
uint32_t line;
19+
uint32_t nargs;
20+
const char *format;
21+
} log_fields_t;
22+
23+
// Writes the log entry address followed by each argument to SW_DV_LOG_ADDR.
24+
void dv_log_write(const log_fields_t *log, ...);
25+
26+
// Count variadic arguments (0–8). DV_LOG_NARGS_SEQ_ is used directly by
27+
// DV_LOG_ rather than via a wrapper; see comment on DV_LOG_ for why.
28+
#define DV_LOG_NARGS_SEQ_(x1,x2,x3,x4,x5,x6,x7,x8,x9,N,...) N
29+
30+
#define DV_LOG_CONCAT_(a, b) a##b
31+
#define DV_LOG_UNIQUE_(pfx) DV_LOG_CONCAT_(pfx, __LINE__)
32+
33+
// Internal macro shared by all severity levels.
34+
// DV_LOG_NARGS_SEQ_ is used inline (not via DV_LOG_NARGS wrapper) so that
35+
// ##__VA_ARGS__ operates directly on DV_LOG_'s own __VA_ARGS__. Passing
36+
// __VA_ARGS__ through an extra macro call causes Clang to treat the empty
37+
// pack as one empty argument, returning N=1 instead of N=0 for 0-arg calls.
38+
#define DV_LOG_(sev, fmt, ...) \
39+
do { \
40+
static const log_fields_t DV_LOG_UNIQUE_(dv_log_entry_) \
41+
__attribute__((section(".logs.fields"), used)) = { \
42+
.severity = (sev), \
43+
.file = __FILE__, \
44+
.line = (uint32_t)__LINE__, \
45+
.nargs = DV_LOG_NARGS_SEQ_(x, ##__VA_ARGS__, 8,7,6,5,4,3,2,1,0), \
46+
.format = (fmt), \
47+
}; \
48+
dv_log_write(&DV_LOG_UNIQUE_(dv_log_entry_), ##__VA_ARGS__); \
49+
} while (0)
50+
51+
#define DV_LOG_INFO(fmt, ...) DV_LOG_(0, fmt, ##__VA_ARGS__)
52+
#define DV_LOG_WARNING(fmt, ...) DV_LOG_(1, fmt, ##__VA_ARGS__)
53+
#define DV_LOG_ERROR(fmt, ...) DV_LOG_(2, fmt, ##__VA_ARGS__)
54+
#define DV_LOG_FATAL(fmt, ...) DV_LOG_(3, fmt, ##__VA_ARGS__)

sw/device/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(LIBS hal runtime startup test_framework)
66

77
mocha_add_test(NAME test_framework_test SOURCES test_framework/smoketest.c LIBRARIES ${LIBS} VERILATOR_TIMEOUT 20 FPGA_TIMEOUT 10)
88
mocha_add_test(NAME test_framework_exception_test SOURCES test_framework/exception.c LIBRARIES ${LIBS})
9+
mocha_add_test(NAME dv_log_smoketest SOURCES test_framework/dv_log_smoketest.c LIBRARIES ${LIBS} SKIP_VERILATOR SKIP_FPGA)
910
mocha_add_test(NAME axi_sram_smoketest SOURCES axi_sram/smoketest.c LIBRARIES ${LIBS})
1011
mocha_add_test(NAME axi_sram_tag_test SOURCES axi_sram/tag_test.c LIBRARIES ${LIBS})
1112
mocha_add_test(NAME entropy_src_smoketest SOURCES entropy_src/smoketest.c LIBRARIES ${LIBS})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright lowRISC contributors (COSMIC project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
// Smoke test for the SW-DV log interface.
6+
7+
#include "test_framework/dv_log.h"
8+
#include "hal/uart.h"
9+
10+
bool test_main(uart_t console)
11+
{
12+
(void)console;
13+
14+
DV_LOG_INFO("SW-DV log smoketest starting...");
15+
DV_LOG_INFO("a = %d, b = %d, c = %d", 10, 20, 12);
16+
DV_LOG_INFO("a + b + c = %d", 42);
17+
DV_LOG_INFO("Smoke test for the SW-DV log interface, completed successfully!");
18+
19+
return true;
20+
}

0 commit comments

Comments
 (0)