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