@@ -140,7 +140,7 @@ macro_rules! clint_codegen {
140
140
/// This macro expects 2 different argument types:
141
141
///
142
142
/// - Base address (**MANDATORY**): base address of the PLIC peripheral of the target.
143
- /// - Per- HART contexts (**OPTIONAL**): a list of `ctx` contexts for easing access to per-HART PLIC contexts .
143
+ /// - HART map (**OPTIONAL**): a list of HART IDs and their corresponding numbers .
144
144
///
145
145
/// Check the examples below for more details about the usage and syntax of this macro.
146
146
///
@@ -153,8 +153,48 @@ macro_rules! clint_codegen {
153
153
///
154
154
/// riscv_peripheral::plic_codegen!(base 0x0C00_0000,); // do not forget the ending comma!
155
155
///
156
- /// let priorities = PLIC::priorities(); // Priorities registers
157
- /// let pendings = PLIC::pendings(); // Pendings registers
156
+ /// let plic = PLIC::new(); // Create a new PLIC peripheral
157
+ /// let priorities = plic.priorities(); // Priorities registers
158
+ /// let pendings = plic.pendings(); // Pendings registers
159
+ /// ```
160
+ ///
161
+ ///
162
+ /// ## Base address and per-HART context proxies
163
+ ///
164
+ /// ```
165
+ /// use riscv_pac::result::{Error, Result};
166
+ ///
167
+ /// /// HART IDs for the target CLINT peripheral
168
+ /// #[derive(Clone, Copy, Debug, Eq, PartialEq)]
169
+ /// pub enum HartId { H0 = 0, H1 = 1, H2 = 2 }
170
+ ///
171
+ /// // Implement `HartIdNumber` for `HartId`
172
+ /// unsafe impl riscv_peripheral::aclint::HartIdNumber for HartId {
173
+ /// const MAX_HART_ID_NUMBER: usize = Self::H2 as usize;
174
+ /// fn number(self) -> usize { self as _ }
175
+ /// fn from_number(number: usize) -> Result<Self> {
176
+ /// match number {
177
+ /// 0 => Ok(HartId::H0),
178
+ /// 1 => Ok(HartId::H1),
179
+ /// 2 => Ok(HartId::H2),
180
+ /// _ => Err(Error::InvalidVariant(number)),
181
+ /// }
182
+ /// }
183
+ /// }
184
+ ///
185
+ /// riscv_peripheral::plic_codegen!(
186
+ /// base 0x0C00_0000,
187
+ /// harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2], // do not forget the ending comma!
188
+ /// );
189
+ ///
190
+ /// let plic = PLIC::new(); // Create a new PLIC peripheral
191
+ /// let ctx0 = plic.ctx0(); // Context proxy for HART 0
192
+ /// let ctx1 = plic.ctx1(); // Context proxy for HART 1
193
+ /// let ctx2 = plic.ctx2(); // Context proxy for HART 2
194
+ ///
195
+ /// assert_eq!(ctx0, plic.ctx(HartId::H0));
196
+ /// assert_eq!(ctx1, plic.ctx(HartId::H1));
197
+ /// assert_eq!(ctx2, plic.ctx(HartId::H2));
158
198
/// ```
159
199
#[ macro_export]
160
200
macro_rules! plic_codegen {
@@ -166,84 +206,51 @@ macro_rules! plic_codegen {
166
206
/// PLIC peripheral
167
207
#[ allow( clippy:: upper_case_acronyms) ]
168
208
#[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
169
- pub struct PLIC ;
170
-
171
- unsafe impl $crate:: plic:: Plic for PLIC {
172
- const BASE : usize = $addr;
173
- }
209
+ pub struct PLIC ( $crate:: plic:: PLIC <Self >) ;
174
210
175
211
impl PLIC {
176
- /// Returns `true` if a machine external interrupt is pending.
177
- #[ inline]
178
- pub fn is_interrupting( ) -> bool {
179
- $crate:: riscv:: register:: mip:: read( ) . mext( )
180
- }
181
-
182
- /// Returns true if Machine External Interrupts are enabled.
183
- #[ inline]
184
- pub fn is_enabled( ) -> bool {
185
- $crate:: riscv:: register:: mie:: read( ) . mext( )
186
- }
187
-
188
- /// Enables machine external interrupts to allow the PLIC to trigger interrupts.
189
- ///
190
- /// # Safety
191
- ///
192
- /// Enabling the `PLIC` may break mask-based critical sections.
193
- #[ inline]
194
- pub unsafe fn enable( ) {
195
- $crate:: riscv:: register:: mie:: set_mext( ) ;
196
- }
197
-
198
- /// Disables machine external interrupts to prevent the PLIC from triggering interrupts.
212
+ /// Creates a new `CLINT` peripheral.
199
213
#[ inline]
200
- pub fn disable( ) {
201
- // SAFETY: it is safe to disable interrupts
202
- unsafe { $crate:: riscv:: register:: mie:: clear_mext( ) } ;
214
+ pub const fn new( ) -> Self {
215
+ Self ( $crate:: plic:: PLIC :: new( ) )
203
216
}
217
+ }
204
218
205
- /// Returns the priorities register of the PLIC.
206
- #[ inline]
207
- pub fn priorities( ) -> $crate:: plic:: priorities:: PRIORITIES {
208
- $crate:: plic:: PLIC :: <PLIC >:: priorities( )
209
- }
219
+ unsafe impl $crate:: plic:: Plic for PLIC {
220
+ const BASE : usize = $addr;
221
+ }
210
222
211
- /// Returns the pendings register of the PLIC.
212
- #[ inline]
213
- pub fn pendings( ) -> $crate:: plic:: pendings:: PENDINGS {
214
- $crate:: plic:: PLIC :: <PLIC >:: pendings( )
215
- }
223
+ impl core:: ops:: Deref for PLIC {
224
+ type Target = $crate:: plic:: PLIC <Self >;
216
225
217
- /// Returns the context proxy of a given PLIC HART context.
218
226
#[ inline]
219
- pub fn ctx< H : $crate :: plic :: HartIdNumber > ( hart_id : H ) -> $crate :: plic :: CTX < Self > {
220
- $crate :: plic :: PLIC :: < PLIC > :: ctx ( hart_id )
227
+ fn deref ( & self ) -> & Self :: Target {
228
+ & self . 0
221
229
}
230
+ }
222
231
223
- /// Returns the PLIC HART context for the current HART.
224
- ///
225
- /// # Note
226
- ///
227
- /// This function determines the current HART ID by reading the [`riscv::register::mhartid`] CSR.
228
- /// Thus, it can only be used in M-mode. For S-mode, use [`PLIC::ctx`] instead.
232
+ impl core:: ops:: DerefMut for PLIC {
229
233
#[ inline]
230
- pub fn ctx_mhartid ( ) -> $crate :: plic :: CTX < Self > {
231
- $crate :: plic :: PLIC :: < PLIC > :: ctx_mhartid ( )
234
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
235
+ & mut self . 0
232
236
}
233
237
}
238
+
234
239
$crate:: plic_codegen!( $( $tail) * ) ;
235
240
} ;
236
- ( ctxs [ $( $fn: ident = ( $ctx: expr , $sctx: expr) ) ,+] , $( $tail: tt) * ) => {
237
- impl PLIC {
238
- $(
239
- #[ doc = "Returns a PLIC context proxy for context of HART " ]
240
- #[ doc = $sctx]
241
- #[ doc = "." ]
242
- #[ inline]
243
- pub fn $fn( ) -> $crate:: plic:: CTX <Self > {
244
- Self :: ctx( $ctx)
245
- }
246
- ) *
241
+ ( harts [ $( $hart: expr => $num: literal) ,+] , $( $tail: tt) * ) => {
242
+ $crate:: macros:: paste! {
243
+ impl PLIC {
244
+ $(
245
+ #[ doc = "Returns a PLIC context proxy for context of HART " ]
246
+ #[ doc = stringify!( $hart) ]
247
+ #[ doc = "`]." ]
248
+ #[ inline]
249
+ pub fn [ <ctx $num>] ( & self ) -> $crate:: plic:: CTX <Self > {
250
+ self . ctx( $hart)
251
+ }
252
+ ) *
253
+ }
247
254
}
248
255
$crate:: plic_codegen!( $( $tail) * ) ;
249
256
} ;
0 commit comments