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
11
#include "
sw/device/lib/dif/dif_spi_device.h
"
12
#include "
sw/device/lib/dif/dif_uart.h
"
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;
49
}
buffer_sink_t
;
50
51
/**
52
* Returns a function pointer to the spi device sink function.
53
*/
54
sink_func_ptr
get_spi_device_sink
(
void
);
55
56
/**
57
* Returns a function pointer to the uart sink function.
58
*/
59
sink_func_ptr
get_uart_sink
(
void
);
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. */
196
size_t
bytes_per_word
;
197
/** How many words (as defined above) per line of output. */
198
size_t
words_per_line
;
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];
205
}
base_hexdump_fmt_t
;
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
*/
280
size_t
base_fhexdump_with
(
buffer_sink_t
out,
base_hexdump_fmt_t
fmt,
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
*/
297
void
base_set_stdout
(
buffer_sink_t
out);
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_
sw
device
lib
runtime
print.h
Return to
OpenTitan Documentation