1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
//! Utility macros for generating standard peripherals-related code in RISC-V PACs.
pub use paste;
/// Macro to create interfaces to CLINT peripherals in PACs.
/// The resulting struct will provide safe access to the CLINT registers.
///
/// This macro expects 5 different argument types:
///
/// - Visibility (**MANDATORY**): visibility of the `fn new()` function for creating a new CLINT.
/// It can be ``, `pub`, `pub(crate)`, or `pub(super)`. If empty, the function will be private.
/// - Peripheral name (**MANDATORY**): name of the resulting CLINT peripheral.
/// - Base address (**MANDATORY**): base address of the CLINT peripheral of the target.
/// - MTIME Frequency (**MANDATORY**): clock frequency (in Hz) of the `MTIME` register.
/// - HART map (**OPTIONAL**): a list of HART IDs and their corresponding numbers.
///
/// Check the examples below for more details about the usage and syntax of this macro.
///
/// # Example
///
/// ## Mandatory fields only, public `fn new()` function
///
/// ```
/// riscv_peripheral::clint_codegen!(pub CLINT, base 0x0200_0000, mtime_freq 32_768);
///
/// let clint = CLINT::new(); // Create a new CLINT peripheral (new is public)
/// let mswi = clint.mswi(); // MSWI peripheral
/// let mtimer = clint.mtimer(); // MTIMER peripheral
/// ```
///
/// ## Base address and per-HART mtimecmp registers, private `fn new()` function
///
/// ```
/// use riscv::result::{Error, Result};
///
/// /// HART IDs for the target CLINT peripheral
/// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// #[riscv::pac_enum(unsafe HartIdNumber)]
/// pub enum HartId { H0 = 0, H1 = 1, H2 = 2 }
///
/// riscv_peripheral::clint_codegen!(
/// Clint,
/// base 0x0200_0000,
/// mtime_freq 32_768,
/// harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2]
/// );
///
/// let clint = Clint::new(); // Create a new CLINT peripheral (new is private)
/// let mswi = clint.mswi(); // MSWI peripheral
/// let mtimer = clint.mtimer(); // MTIMER peripheral
///
/// let mtimecmp0 = clint.mtimecmp0(); // mtimecmp register for HART 0
/// let mtimecmp1 = clint.mtimecmp1(); // mtimecmp register for HART 1
/// let mtimecmp2 = clint.mtimecmp2(); // mtimecmp register for HART 2
///
/// let msip0 = clint.msip0(); // msip register for HART 0
/// let msip1 = clint.msip1(); // msip register for HART 1
/// let msip2 = clint.msip2(); // msip register for HART 2
/// ```
/// Macro to create interfaces to PLIC peripherals in PACs.
/// The resulting struct will be named `PLIC`, and will provide safe access to the PLIC registers.
///
/// This macro expects 4 different argument types:
///
/// - Visibility (**MANDATORY**): visibility of the `fn new()` function for creating a new PLIC.
/// It can be ``, `pub`, `pub(crate)`, or `pub(super)`. If empty, the function will be private.
/// - Peripheral name (**MANDATORY**): name of the resulting PLIC peripheral.
/// - Base address (**MANDATORY**): base address of the PLIC peripheral of the target.
/// - HART map (**OPTIONAL**): a list of HART IDs and their corresponding numbers.
///
/// Check the examples below for more details about the usage and syntax of this macro.
///
/// # Example
///
/// ## Base address only, public `fn new()` function
///
/// ```
/// use riscv_peripheral::clint_codegen;
///
/// riscv_peripheral::plic_codegen!(pub PLIC, base 0x0C00_0000);
///
/// let plic = PLIC::new(); // Create a new PLIC peripheral (new is public)
/// let priorities = plic.priorities(); // Priorities registers
/// let pendings = plic.pendings(); // Pendings registers
/// ```
///
/// ## Base address and per-HART context proxies, private `fn new()` function
///
/// ```
/// use riscv::result::{Error, Result};
///
/// /// HART IDs for the target CLINT peripheral
/// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
/// #[riscv::pac_enum(unsafe HartIdNumber)]
/// pub enum HartId { H0 = 0, H1 = 1, H2 = 2 }
///
/// riscv_peripheral::plic_codegen!(
/// Plic,
/// base 0x0C00_0000,
/// harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2]
/// );
///
/// let plic = Plic::new(); // Create a new PLIC peripheral (new is private)
/// let ctx0 = plic.ctx0(); // Context proxy for HART 0
/// let ctx1 = plic.ctx1(); // Context proxy for HART 1
/// let ctx2 = plic.ctx2(); // Context proxy for HART 2
///
/// assert_eq!(ctx0, plic.ctx(HartId::H0));
/// assert_eq!(ctx1, plic.ctx(HartId::H1));
/// assert_eq!(ctx2, plic.ctx(HartId::H2));
/// ```