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
17 extern "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 
51 uint32_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 
61 void 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 
71 void 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 
81 void 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_