Software APIs
print.h
Go to the documentation of this file.
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#ifndef OPENTITAN_SW_DEVICE_LIB_RUNTIME_PRINT_H_
6#define OPENTITAN_SW_DEVICE_LIB_RUNTIME_PRINT_H_
7
8#include <stdarg.h>
9#include <stddef.h>
10
13
14/**
15 * @file
16 * @brief Libc-like printing facilities.
17 *
18 * This header provides libc-like printing facilities, which is agnostic of the
19 * underlying hardware printing mechanism.
20 *
21 * We avoid using libc names here, since we do not support the full suite of
22 * format specifier syntax, and use a different character sink type instead of
23 * the traditional `FILE *`.
24 *
25 * All functions in this file should be machine word size agnostic, that is, the
26 * same code should work correctly on both 32-bit and 64-bit machines, though
27 * formatting, where the exact format style is unspecified, is allowed to vary
28 * slightly on machine word size.
29 */
30
31/**
32 * Function pointer type for data sink.
33 * The function should return the number of bytes actually written.
34 */
35typedef size_t (*sink_func_ptr)(void *data, const char *buf, size_t len);
36
37/**
38 * A buffer_sink_t represents a place to write bytes to, implemented as a
39 * C-style "closure".
40 *
41 * It consists of a generic data pointer, which can hold instance-specific
42 * information, and a sink function, which takes the data pointer, a buffer, and
43 * that buffer's length.
44 *
45 */
46typedef struct buffer_sink {
47 void *data;
48 sink_func_ptr sink;
50
51/**
52 * Returns a function pointer to the spi device sink function.
53 */
55
56/**
57 * Returns a function pointer to the uart sink function.
58 */
60
61/**
62 * Prints out a message to stdout, formatted according to the format string
63 * `format`.
64 *
65 * The definition of "stdout" is not provided by this library; rather, it must
66 * be initialized using `base_set_stdout()`.
67 *
68 * This function supports a subset of the format specifiers provided by standard
69 * C `printf`. Those are, namely:
70 * - %%, which prints a percent sign.
71 * - %c, which prints the lowest byte of a uint32_t as a character.
72 * - %s, which prints a NUL-terminated string.
73 * - %d and %i, which print a signed decimal uint32_t.
74 * - %u, which prints an unsigned decimal uint32_t.
75 * - %o, which prints an unsigned octal uint32_t.
76 * - %x and %X, which print an unsigned hex uint32_t.
77 * - %p, which prints a pointer in a consistent but unspecified way.
78 *
79 * Additionally, three SystemVerilog format specifiers are supported:
80 * - %h and %H, which are aliases for %x and %X, respectively.
81 * - %b, which prints an unsigned binary uint32_t.
82 *
83 * Finally, additional nonstandard format specifiers is supported:
84 * - %C prints a 'FourCC' style uint32_t (ASCII bytes in little-endian order).
85 * - %!s, which takes a size_t followed by a pointer to a buffer, and prints
86 * out that many characters from the buffer.
87 * - %!x, %!X, %!y, and %!Y, which are like %!s but print out a hex dump
88 * instead; casing is as with %x, and %!x will print in big-endian order
89 * (i.e., last byte printed first) while %!y will print in little-endian
90 * order (i.e., first byte printed first). This makes sure %!x is consistent
91 * with %x.
92 * - %!b, which takes a bool and prints either true or false.
93 * - %r, which takes a status_t and prints the status, argument and module ID.
94 * - %!r, which takes a status_t and prints the status, argument and module ID
95 * as JSON.
96 *
97 * When compiled for a DV testbench, this function will not read any pointers,
98 * and as such the specifiers %s, %!s, %!x, %!X, %!y, and %!Y will behave as if
99 * they were printing garbage, and are, as such, unsupported.
100 *
101 * This function furthermore supports width modifiers for integer specifiers,
102 * such as `%010d`. It does not support dynamic widths like `%*d`. If the width
103 * specifier starts with a `0`, it is padded with zeroes; otherwise, it is
104 * padded with spaces, consistent with the standard C behavior.
105 *
106 * Of course, providing arguments for formatting which are incompatible with a
107 * given format specifier is Undefined Behavior.
108 *
109 * Note that for logging in DV, the following script updates the format
110 * specifiers supported in C above and changes them to match the SystemVerilog
111 * language semantics: util/device_sw_utils/extract_sw_logs.py
112 * It also makes fixes as needed for custom specifiers such as %!s.
113 *
114 * @param format the format spec.
115 * @param ... values to interpolate in the format spec.
116 */
117size_t base_printf(const char *format, ...);
118
119/**
120 * Prints out a message to stdout, formatted according to the format string
121 * `format`.
122 *
123 * This function is identical to `base_printf`, except in that it takes a
124 * `va_list` instead of having a vararg parameter. This function plays a role
125 * analogous to `base_vfprintf`, for functions that wish to use the currently
126 * set `stdout`.
127 *
128 * This function *does not* take ownership of `args`; callers are responsible
129 * for calling `va_end`.
130 *
131 * See `base_printf()` for the semantics of the format specification.
132 *
133 * @param format the format spec.
134 * @param args values to interpolate in the format spec.
135 */
136size_t base_vprintf(const char *format, va_list args);
137
138/*
139 * Prints a message to the buffer `buf`, capped at a given length.
140 *
141 * It goes without saying that the caller must ensure the given buffer is large
142 * enough; failure to do so is Undefined Behavior.
143 *
144 * See `base_printf()` for the semantics of the format specification.
145 *
146 * @param buf a buffer to print to.
147 * @param format the format spec.
148 * @param ... values to interpolate in the format spec.
149 */
150size_t base_snprintf(char *buf, size_t len, const char *format, ...);
151
152/**
153 * Prints a message to the sink `out`.
154 *
155 * If `out.sink` is `NULL`, writes are treated as-if they were written to a
156 * UNIX-like /dev/null: writes succeed, but the actual bytes are not printed
157 * anywhere.
158 *
159 * See `base_printf()` for the semantics of the format specification.
160 *
161 * @param out a sink to print to.
162 * @param format the format spec.
163 * @param ... values to interpolate in the format spec.
164 */
165size_t base_fprintf(buffer_sink_t out, const char *format, ...);
166
167/**
168 * Prints a message to the sink `out`.
169 *
170 * This function is identical to `base_fprintf`, except in that it takes a
171 * `va_list` instead of having a vararg parameter. This function is provided
172 * not for calling directly, but rather for being called by functions that
173 * already take a variable number of arguments, and wish to make use of
174 * formatting facilities.
175 *
176 * This function *does not* take ownership of `args`; callers are responsible
177 * for calling `va_end`.
178 *
179 * If `out.sink` is `NULL`, writes are treated as-if they were written to a
180 * UNIX-like /dev/null: writes succeed, but the actual bytes are not printed
181 * anywhere.
182 *
183 * See `base_printf()` for the semantics of the format specification.
184 *
185 * @param out a sink to print to.
186 * @param format the format spec.
187 * @param args values to interpolate in the format spec.
188 */
189size_t base_vfprintf(buffer_sink_t out, const char *format, va_list args);
190
191/**
192 * Configuration options for `base_hexdump` and friends.
193 */
194typedef struct base_hexdump_fmt {
195 /** How many bytes to print per word of output. */
197 /** How many words (as defined above) per line of output. */
199 /**
200 * The alphabet to use for char-ifying a byte.
201 *
202 * These characters will be written as-is to the sink.
203 */
204 const char (*alphabet)[256];
206
207/**
208 * The default alphabet used by `base_hexdump()` functions.
209 */
210extern const char kBaseHexdumpDefaultFmtAlphabet[256];
211
212/**
213 * Dumps `hex` in an xxd-style hexdump to stdout, using default formatting
214 * options.
215 *
216 * @param buf the buffer to dump.
217 * @param len the number of bytes to dump from hex.
218 */
219size_t base_hexdump(const char *buf, size_t len);
220
221/**
222 * Dumps `hex` in an xxd-style hexdump to the buffer `buf`, capped at the given
223 * length, using default formatting options.
224 *
225 * @param out a buffer to print to.
226 * @param out_len the length of the output buffer.
227 * @param buf the buffer to dump.
228 * @param len the number of bytes to dump from hex.
229 */
230size_t base_snhexdump(char *out, size_t out_len, const char *buf, size_t len);
231
232/**
233 * Dumps `hex` in an xxd-style hexdump to `out`, using default formatting
234 * options.
235 *
236 * If `out.sink` is `NULL`, writes are treated as-if they were written to a
237 * UNIX-like /dev/null: writes succeed, but the actual bytes are not printed
238 * anywhere.
239 *
240 * @param out a sink to print to.
241 * @param buf the buffer to dump.
242 * @param len the number of bytes to dump from hex.
243 */
244size_t base_fhexdump(buffer_sink_t out, const char *buf, size_t len);
245
246/**
247 * Dumps `hex` in an xxd-style hexdump to stdout.
248 *
249 * @param fmt the format for dumping.
250 * @param buf the buffer to dump.
251 * @param len the number of bytes to dump from hex.
252 */
253size_t base_hexdump_with(base_hexdump_fmt_t fmt, const char *buf, size_t len);
254
255/**
256 * Dumps `hex` in an xxd-style hexdump to the buffer `buf`, capped at the given
257 * length.
258 *
259 * @param out a buffer to print to.
260 * @param out_len the length of the output buffer.
261 * @param fmt the format for dumping.
262 * @param buf the buffer to dump.
263 * @param len the number of bytes to dump from hex.
264 */
265size_t base_snhexdump_with(char *out, size_t out_len, base_hexdump_fmt_t fmt,
266 const char *buf, size_t len);
267
268/**
269 * Dumps `hex` in an xxd-style hexdump to `out`.
270 *
271 * If `out.sink` is `NULL`, writes are treated as-if they were written to a
272 * UNIX-like /dev/null: writes succeed, but the actual bytes are not printed
273 * anywhere.
274 *
275 * @param out a sink to print to.
276 * @param fmt the format for dumping.
277 * @param buf the buffer to dump.
278 * @param len the number of bytes to dump from hex.
279 */
281 const char *buf, size_t len);
282
283/**
284 * Sets what the "stdout" sink is, which is used by `base_printf()`.
285 *
286 * The default sink behaves like /dev/null on a standard UNIX system: writes
287 * are treated as successful, but the contents of buffers are ignored.
288 *
289 * As such, this function must be called for printed messages to wind up
290 * somewhere.
291 *
292 * Passing in `NULL` instead of a real function pointer will reset stdout to
293 * the default /dev/null behavior.
294 *
295 * @param out the sink to use for "default" printing.
296 */
298
299/**
300 * Configures SPI device stdout for `base_print.h` to use.
301 *
302 * Note that this function will save `spi_device` in a global variable, so the
303 * pointer must have static storage duration.
304 *
305 * @param spi_device The SPI device handle to use for stdout.
306 */
307void base_spi_device_stdout(const dif_spi_device_handle_t *spi_device);
308
309/**
310 * Configures UART stdout for `base_print.h` to use.
311 *
312 * Note that this function will save `uart` in a global variable, so the pointer
313 * must have static storage duration.
314 *
315 * @param uart The UART handle to use for stdout.
316 */
317void base_uart_stdout(const dif_uart_t *uart);
318
319#endif // OPENTITAN_SW_DEVICE_LIB_RUNTIME_PRINT_H_