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