|
| 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__) |
0 commit comments