Software APIs
csr.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_BASE_CSR_H_
6#define OPENTITAN_SW_DEVICE_LIB_BASE_CSR_H_
7
8#include <assert.h>
9#include <stdbool.h>
10#include <stdint.h>
11
12#include "sw/device/lib/base/csr_registers.h"
15
16#ifdef __cplusplus
17extern "C" {
18#endif // __cplusplus
19
20/**
21 * @file
22 * @brief Ibex Control and Status Register (CSR) interface.
23 *
24 * A set of macros that provide both read and modify operations on Ibex CSRs.
25 * Compiling translation units that include this header file with `-DMOCK_CSR`
26 * will result in the CSR operations being replaced with a mocked
27 * implementation.
28 */
29
30/**
31 * Define the implementation macros.
32 *
33 * The implementation used depends on whether the CSR library is providing a
34 * real or a mocked interface.
35 */
36#ifndef OT_PLATFORM_RV32
37
38/**
39 * Macro to check that an argument is a constant expression at compile time.
40 *
41 * The real implementations of CSR operations require the CSR address to be
42 * a constant expression. Using this macro allows the same constraint to be
43 * applied when using the mocked implementations.
44 *
45 * Note: could also use a static assertion for this but an inline asm immediate
46 * constraint means the error for mocked and real implementation should be very
47 * similar.
48 */
49#define CSR_FORCE_CONST_EXPR(x) asm volatile("" ::"i"(x))
50
51uint32_t mock_csr_read(uint32_t addr);
52
53#define CSR_READ_IMPL(csr, dest) \
54 do { \
55 static_assert(sizeof(*dest) == sizeof(uint32_t), \
56 "dest must point to a 4-byte variable"); \
57 CSR_FORCE_CONST_EXPR(csr); \
58 *dest = mock_csr_read(csr); \
59 } while (false)
60
61void mock_csr_write(uint32_t addr, uint32_t value);
62
63#define CSR_WRITE_IMPL(csr, val) \
64 do { \
65 static_assert(sizeof(val) == sizeof(uint32_t), \
66 "val must be a 4-byte value"); \
67 CSR_FORCE_CONST_EXPR(csr); \
68 mock_csr_write(csr, val); \
69 } while (false)
70
71void mock_csr_set_bits(uint32_t addr, uint32_t mask);
72
73#define CSR_SET_BITS_IMPL(csr, mask) \
74 do { \
75 static_assert(sizeof(mask) == sizeof(uint32_t), \
76 "mask must be a 4-byte value"); \
77 CSR_FORCE_CONST_EXPR(csr); \
78 mock_csr_set_bits(csr, mask); \
79 } while (false)
80
81void mock_csr_clear_bits(uint32_t addr, uint32_t mask);
82
83#define CSR_CLEAR_BITS_IMPL(csr, mask) \
84 do { \
85 static_assert(sizeof(mask) == sizeof(uint32_t), \
86 "mask must be a 4-byte value"); \
87 CSR_FORCE_CONST_EXPR(csr); \
88 mock_csr_clear_bits(csr, mask); \
89 } while (false)
90
91#else // OT_PLATFORM_RV32
92
93#define CSR_READ_IMPL(csr, dest) \
94 do { \
95 static_assert(sizeof(*dest) == sizeof(uint32_t), \
96 "dest must point to a 4-byte variable"); \
97 asm volatile("csrr %0, %1;" : "=r"(*dest) : "i"(csr)); \
98 } while (false)
99
100#define CSR_WRITE_IMPL(csr, val) \
101 do { \
102 static_assert(sizeof(val) == sizeof(uint32_t), \
103 "val must be a 4-byte value"); \
104 asm volatile("csrw %0, %1;" ::"i"(csr), "r"(val)); \
105 } while (false)
106
107#define CSR_SET_BITS_IMPL(csr, mask) \
108 do { \
109 static_assert(sizeof(mask) == sizeof(uint32_t), \
110 "mask must be a 4-byte value"); \
111 asm volatile("csrs %0, %1;" ::"i"(csr), "r"(mask)); \
112 } while (false)
113
114#define CSR_CLEAR_BITS_IMPL(csr, mask) \
115 do { \
116 static_assert(sizeof(mask) == sizeof(uint32_t), \
117 "mask must be a 4-byte value"); \
118 asm volatile("csrc %0, %1;" ::"i"(csr), "r"(mask)); \
119 } while (false)
120
121#endif // OT_PLATFORM_RV32
122
123/**
124 * Read the value of a CSR and place the result into the location pointed to by
125 * dest.
126 *
127 * Equivalent to:
128 *
129 * `*dest = csr`
130 *
131 * @param csr The target register. MUST be a `CSR_REG_<name>` constant.
132 * @param[out] dest Pointer to a variable where the value of the named CSR will
133 * be written to.
134 */
135#define CSR_READ(csr, dest) CSR_READ_IMPL(csr, dest)
136
137/**
138 * Write a value to a CSR.
139 *
140 * Equivalent to:
141 *
142 * `csr = val`
143 *
144 * @param csr The target register. MUST be a `CSR_REG_<name>` constant.
145 * @param val The value to write to the named CSR.
146 */
147#define CSR_WRITE(csr, val) CSR_WRITE_IMPL(csr, val)
148
149/**
150 * Set masked bits in the CSR.
151 *
152 * Equivalent to:
153 *
154 * `csr |= mask`
155 *
156 * @param csr The target register. MUST be a `CSR_REG_<name>` constant.
157 * @param mask Mask containing the bits to set.
158 */
159#define CSR_SET_BITS(csr, mask) CSR_SET_BITS_IMPL(csr, mask)
160
161/**
162 * Clear masked bits in the CSR.
163 *
164 * Equivalent to:
165 *
166 * `csr &= ~mask`
167 *
168 * @param csr The target register. MUST be a `CSR_REG_<name>` constant.
169 * @param mask Mask containing the bits to clear.
170 */
171#define CSR_CLEAR_BITS(csr, mask) CSR_CLEAR_BITS_IMPL(csr, mask)
172
173#ifdef __cplusplus
174} // extern "C"
175#endif // __cplusplus
176
177#endif // OPENTITAN_SW_DEVICE_LIB_BASE_CSR_H_