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  */
35 typedef 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  */
46 typedef 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  */
117 size_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  */
136 size_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  */
150 size_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  */
165 size_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  */
189 size_t base_vfprintf(buffer_sink_t out, const char *format, va_list args);
190 
191 /**
192  * Configuration options for `base_hexdump` and friends.
193  */
194 typedef 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  */
210 extern 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  */
219 size_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  */
230 size_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  */
244 size_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  */
253 size_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  */
265 size_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  */
307 void 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  */
317 void base_uart_stdout(const dif_uart_t *uart);
318 
319 #endif // OPENTITAN_SW_DEVICE_LIB_RUNTIME_PRINT_H_