@@ -140,7 +140,7 @@ macro_rules! clint_codegen {
140140/// This macro expects 2 different argument types:
141141///
142142/// - 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 .
144144///
145145/// Check the examples below for more details about the usage and syntax of this macro.
146146///
@@ -153,8 +153,48 @@ macro_rules! clint_codegen {
153153///
154154/// riscv_peripheral::plic_codegen!(base 0x0C00_0000,); // do not forget the ending comma!
155155///
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));
158198/// ```
159199#[ macro_export]
160200macro_rules! plic_codegen {
@@ -166,84 +206,51 @@ macro_rules! plic_codegen {
166206 /// PLIC peripheral
167207 #[ allow( clippy:: upper_case_acronyms) ]
168208 #[ 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 >) ;
174210
175211 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.
199213 #[ 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( ) )
203216 }
217+ }
204218
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+ }
210222
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 >;
216225
217- /// Returns the context proxy of a given PLIC HART context.
218226 #[ 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
221229 }
230+ }
222231
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 {
229233 #[ 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
232236 }
233237 }
238+
234239 $crate:: plic_codegen!( $( $tail) * ) ;
235240 } ;
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+ }
247254 }
248255 $crate:: plic_codegen!( $( $tail) * ) ;
249256 } ;
0 commit comments