Skip to content

Commit 4aba650

Browse files
committed
Improved macros
1 parent 769da06 commit 4aba650

File tree

6 files changed

+82
-74
lines changed

6 files changed

+82
-74
lines changed

riscv-peripheral/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1515
- Rework of PLIC peripherals to use methods instead of associated functions.
1616
This change follows the `svd2rust` pattern, making the ecosystem more consistent.
1717
- Simplify `plic_codegen!` macro using the `Deref` trait.
18+
- Macros allow now to customize the struct name for CLINT and PLIC.
19+
- Macros allow now to customize the visibility of the `new` function for CLINT and PLIC.
1820

1921
### Removed
2022

riscv-peripheral/examples/e310x.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,30 @@ pub enum Priority {
7979
P7 = 7,
8080
}
8181

82+
// We can define CLINT::new() as a public, safe function
8283
riscv_peripheral::clint_codegen!(
84+
pub CLINT,
8385
base 0x0200_0000,
8486
mtime_freq 32_768,
85-
harts [HartId::H0 => 0],
87+
harts [HartId::H0 => 0]
8688
);
8789

90+
// We can define PLIC::new() as a private, safe function...
8891
riscv_peripheral::plic_codegen!(
92+
PLIC,
8993
base 0x0C00_0000,
90-
harts [HartId::H0 => 0],
94+
harts [HartId::H0 => 0]
9195
);
9296

93-
fn main() {}
97+
// ... and then implement a public, unsafe function to steal the PLIC instance
98+
// Usually, this function is implemented by svd2rust, but we do it manually here
99+
impl PLIC {
100+
pub unsafe fn steal() -> Self {
101+
PLIC::new()
102+
}
103+
}
104+
105+
fn main() {
106+
let _clint = CLINT::new();
107+
let _plic = unsafe { PLIC::steal() };
108+
}

riscv-peripheral/src/aclint.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@ pub(crate) mod test {
9999
fn check_clint() {
100100
// Call CLINT macro with a base address and a list of mtimecmps for easing access to per-HART mtimecmp regs.
101101
crate::clint_codegen!(
102+
CLINT,
102103
base 0x0200_0000,
103104
mtime_freq 32_768,
104-
harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2],
105+
harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2]
105106
);
106107

107108
let clint = CLINT::new();

riscv-peripheral/src/common.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,13 @@ bitwise_reg!(i128);
177177
bitwise_reg!(isize);
178178

179179
/// Macro to provide atomic bit-wise operations to integer number registers.
180+
#[cfg(any(
181+
target_has_atomic = "8",
182+
target_has_atomic = "16",
183+
target_has_atomic = "32",
184+
target_has_atomic = "64",
185+
target_has_atomic = "ptr"
186+
))]
180187
macro_rules! bitwise_atomic_reg {
181188
($TYPE: ty, $ATOMIC: ty) => {
182189
impl<A: Read + Write> Reg<$TYPE, A> {

riscv-peripheral/src/macros.rs

Lines changed: 51 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
pub use paste::paste;
44

55
/// Macro to create interfaces to CLINT peripherals in PACs.
6-
/// The resulting struct will be named `CLINT`, and will provide safe access to the CLINT registers.
6+
/// The resulting struct will provide safe access to the CLINT registers.
77
///
8-
/// This macro expects 3 different argument types:
8+
/// This macro expects 5 different argument types:
99
///
10+
/// - Visibility (**MANDATORY**): visibility of the `fn new()` function for creating a new CLINT.
11+
/// It can be ``, `pub`, `pub(crate)`, or `pub(super)`. If empty, the function will be private.
12+
/// - Peripheral name (**MANDATORY**): name of the resulting CLINT peripheral.
1013
/// - Base address (**MANDATORY**): base address of the CLINT peripheral of the target.
1114
/// - MTIME Frequency (**MANDATORY**): clock frequency (in Hz) of the `MTIME` register.
1215
/// - HART map (**OPTIONAL**): a list of HART IDs and their corresponding numbers.
@@ -15,17 +18,17 @@ pub use paste::paste;
1518
///
1619
/// # Example
1720
///
18-
/// ## Mandatory fields only
21+
/// ## Mandatory fields only, public `fn new()` function
1922
///
2023
/// ```
21-
/// riscv_peripheral::clint_codegen!(base 0x0200_0000, mtime_freq 32_768,); // do not forget the ending comma!
24+
/// riscv_peripheral::clint_codegen!(pub CLINT, base 0x0200_0000, mtime_freq 32_768);
2225
///
23-
/// let clint = CLINT::new(); // Create a new CLINT peripheral
26+
/// let clint = CLINT::new(); // Create a new CLINT peripheral (new is public)
2427
/// let mswi = clint.mswi(); // MSWI peripheral
2528
/// let mtimer = clint.mtimer(); // MTIMER peripheral
2629
/// ```
2730
///
28-
/// ## Base address and per-HART mtimecmp registers
31+
/// ## Base address and per-HART mtimecmp registers, private `fn new()` function
2932
///
3033
/// ```
3134
/// use riscv_pac::result::{Error, Result};
@@ -36,12 +39,13 @@ pub use paste::paste;
3639
/// pub enum HartId { H0 = 0, H1 = 1, H2 = 2 }
3740
///
3841
/// riscv_peripheral::clint_codegen!(
42+
/// Clint,
3943
/// base 0x0200_0000,
4044
/// mtime_freq 32_768,
41-
/// harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2], // do not forget the ending comma!
45+
/// harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2]
4246
/// );
4347
///
44-
/// let clint = CLINT::new(); // Create a new CLINT peripheral
48+
/// let clint = Clint::new(); // Create a new CLINT peripheral (new is private)
4549
/// let mswi = clint.mswi(); // MSWI peripheral
4650
/// let mtimer = clint.mtimer(); // MTIMER peripheral
4751
///
@@ -55,97 +59,87 @@ pub use paste::paste;
5559
/// ```
5660
#[macro_export]
5761
macro_rules! clint_codegen {
58-
() => {
59-
#[allow(unused_imports)]
60-
use CLINT as _; // assert that the CLINT struct is defined
61-
};
62-
(base $addr:literal, mtime_freq $freq:literal, $($tail:tt)*) => {
62+
($vis:vis $name:ident, base $addr:literal, mtime_freq $freq:literal) => {
6363
/// CLINT peripheral
6464
#[allow(clippy::upper_case_acronyms)]
6565
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
66-
pub struct CLINT($crate::aclint::CLINT<Self>);
66+
pub struct $name($crate::aclint::CLINT<Self>);
6767

68-
impl CLINT {
68+
impl $name {
6969
/// Creates a new `CLINT` peripheral.
7070
#[inline]
71-
pub const fn new() -> Self {
71+
$vis const fn new() -> Self {
7272
Self($crate::aclint::CLINT::new())
7373
}
7474
}
7575

76-
unsafe impl $crate::aclint::Clint for CLINT {
76+
unsafe impl $crate::aclint::Clint for $name {
7777
const BASE: usize = $addr;
7878
const MTIME_FREQ: usize = $freq;
7979
}
8080

81-
impl core::ops::Deref for CLINT {
81+
impl core::ops::Deref for $name {
8282
type Target = $crate::aclint::CLINT<Self>;
8383

8484
#[inline]
8585
fn deref(&self) -> &Self::Target {
8686
&self.0
8787
}
8888
}
89-
90-
impl core::ops::DerefMut for CLINT {
91-
#[inline]
92-
fn deref_mut(&mut self) -> &mut Self::Target {
93-
&mut self.0
94-
}
95-
}
96-
97-
$crate::clint_codegen!($($tail)*);
9889
};
99-
(harts [$($hart:expr => $num:literal),+], $($tail:tt)*) => {
90+
($vis:vis $name:ident, base $addr:literal, mtime_freq $freq:literal, harts [$($hart:expr => $num:literal),+]) => {
91+
$crate::clint_codegen!($vis $name, base $addr, mtime_freq $freq);
10092
$crate::macros::paste! {
101-
impl CLINT {
93+
impl $name {
10294
$(
103-
#[doc = "Returns the `msip` register for HART [`"]
104-
#[doc = stringify!($hart)]
105-
#[doc = "`]."]
95+
#[doc = "Returns the `msip` register for HART "]
96+
#[doc = stringify!($num)]
97+
#[doc = "."]
10698
#[inline]
10799
pub fn [<msip $num>](&self) -> $crate::aclint::mswi::MSIP {
108100
self.mswi().msip($hart)
109101
}
110-
#[doc = "Returns the `mtimecmp` register for HART [`"]
111-
#[doc = stringify!($hart)]
112-
#[doc = "`]."]
102+
#[doc = "Returns the `mtimecmp` register for HART "]
103+
#[doc = stringify!($num)]
104+
#[doc = "."]
113105
#[inline]
114106
pub fn [<mtimecmp $num>](&self) -> $crate::aclint::mtimer::MTIMECMP {
115107
self.mtimer().mtimecmp($hart)
116108
}
117109
)*
118110
}
119111
}
120-
$crate::clint_codegen!($($tail)*);
121112
};
122113
}
123114

124115
/// Macro to create interfaces to PLIC peripherals in PACs.
125116
/// The resulting struct will be named `PLIC`, and will provide safe access to the PLIC registers.
126117
///
127-
/// This macro expects 2 different argument types:
118+
/// This macro expects 4 different argument types:
128119
///
120+
/// - Visibility (**MANDATORY**): visibility of the `fn new()` function for creating a new PLIC.
121+
/// It can be ``, `pub`, `pub(crate)`, or `pub(super)`. If empty, the function will be private.
122+
/// - Peripheral name (**MANDATORY**): name of the resulting PLIC peripheral.
129123
/// - Base address (**MANDATORY**): base address of the PLIC peripheral of the target.
130124
/// - HART map (**OPTIONAL**): a list of HART IDs and their corresponding numbers.
131125
///
132126
/// Check the examples below for more details about the usage and syntax of this macro.
133127
///
134128
/// # Example
135129
///
136-
/// ## Base address only
130+
/// ## Base address only, public `fn new()` function
137131
///
138132
/// ```
139133
/// use riscv_peripheral::clint_codegen;
140134
///
141-
/// riscv_peripheral::plic_codegen!(base 0x0C00_0000,); // do not forget the ending comma!
135+
/// riscv_peripheral::plic_codegen!(pub PLIC, base 0x0C00_0000);
142136
///
143-
/// let plic = PLIC::new(); // Create a new PLIC peripheral
137+
/// let plic = PLIC::new(); // Create a new PLIC peripheral (new is public)
144138
/// let priorities = plic.priorities(); // Priorities registers
145139
/// let pendings = plic.pendings(); // Pendings registers
146140
/// ```
147141
///
148-
/// ## Base address and per-HART context proxies
142+
/// ## Base address and per-HART context proxies, private `fn new()` function
149143
///
150144
/// ```
151145
/// use riscv_pac::result::{Error, Result};
@@ -156,11 +150,12 @@ macro_rules! clint_codegen {
156150
/// pub enum HartId { H0 = 0, H1 = 1, H2 = 2 }
157151
///
158152
/// riscv_peripheral::plic_codegen!(
153+
/// Plic,
159154
/// base 0x0C00_0000,
160-
/// harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2], // do not forget the ending comma!
155+
/// harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2]
161156
/// );
162157
///
163-
/// let plic = PLIC::new(); // Create a new PLIC peripheral
158+
/// let plic = Plic::new(); // Create a new PLIC peripheral (new is private)
164159
/// let ctx0 = plic.ctx0(); // Context proxy for HART 0
165160
/// let ctx1 = plic.ctx1(); // Context proxy for HART 1
166161
/// let ctx2 = plic.ctx2(); // Context proxy for HART 2
@@ -171,60 +166,47 @@ macro_rules! clint_codegen {
171166
/// ```
172167
#[macro_export]
173168
macro_rules! plic_codegen {
174-
() => {
175-
#[allow(unused_imports)]
176-
use PLIC as _; // assert that the PLIC struct is defined
177-
};
178-
(base $addr:literal, $($tail:tt)*) => {
169+
($vis:vis $name:ident, base $addr:literal) => {
179170
/// PLIC peripheral
180171
#[allow(clippy::upper_case_acronyms)]
181172
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
182-
pub struct PLIC($crate::plic::PLIC<Self>);
173+
pub struct $name($crate::plic::PLIC<Self>);
183174

184-
impl PLIC {
185-
/// Creates a new `CLINT` peripheral.
175+
impl $name {
176+
/// Creates a new `PLIC` peripheral.
186177
#[inline]
187-
pub const fn new() -> Self {
178+
$vis const fn new() -> Self {
188179
Self($crate::plic::PLIC::new())
189180
}
190181
}
191182

192-
unsafe impl $crate::plic::Plic for PLIC {
183+
unsafe impl $crate::plic::Plic for $name {
193184
const BASE: usize = $addr;
194185
}
195186

196-
impl core::ops::Deref for PLIC {
187+
impl core::ops::Deref for $name {
197188
type Target = $crate::plic::PLIC<Self>;
198189

199190
#[inline]
200191
fn deref(&self) -> &Self::Target {
201192
&self.0
202193
}
203194
}
204-
205-
impl core::ops::DerefMut for PLIC {
206-
#[inline]
207-
fn deref_mut(&mut self) -> &mut Self::Target {
208-
&mut self.0
209-
}
210-
}
211-
212-
$crate::plic_codegen!($($tail)*);
213195
};
214-
(harts [$($hart:expr => $num:literal),+], $($tail:tt)*) => {
196+
($vis:vis $name:ident, base $addr:literal, harts [$($hart:expr => $num:literal),+]) => {
197+
$crate::plic_codegen!($vis $name, base $addr);
215198
$crate::macros::paste! {
216-
impl PLIC {
199+
impl $name {
217200
$(
218-
#[doc = "Returns a PLIC context proxy for context of HART [`"]
219-
#[doc = stringify!($hart)]
220-
#[doc = "`]."]
201+
#[doc = "Returns a PLIC context proxy for context of HART "]
202+
#[doc = stringify!($num)]
203+
#[doc = "."]
221204
#[inline]
222205
pub fn [<ctx $num>](&self) -> $crate::plic::CTX<Self> {
223206
self.ctx($hart)
224207
}
225208
)*
226209
}
227210
}
228-
$crate::plic_codegen!($($tail)*);
229211
};
230212
}

riscv-peripheral/src/plic.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,9 @@ pub(crate) mod test {
193193
#[test]
194194
fn check_plic() {
195195
crate::plic_codegen!(
196+
PLIC,
196197
base 0x0C00_0000,
197-
harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2],
198+
harts [HartId::H0 => 0, HartId::H1 => 1, HartId::H2 => 2]
198199
);
199200

200201
let plic = PLIC::new();

0 commit comments

Comments
 (0)