Skip to content

Commit dbb57e9

Browse files
0xllx0KushalMeghani1644
authored andcommitted
test: add unit test for miselect
Adds a basic unit test for the `miselect` CSR. asm: Improve documentation and code quality for RISC-V instructions - Remove redundant unimplemented!() calls on non-RISC-V targets since functions are already properly gated with cfg attributes - Add comprehensive safety documentation explaining when and why instructions are unsafe (ebreak, ecall) - Enhance behavior descriptions with practical use cases and performance considerations for fence operations - Add preserves_flags option to instructions that don't modify flags (nop, wfi, ebreak, ecall) - Fix sfence_vma() assembly template to use idiomatic {} syntax - Strengthen delay() function warnings about timing accuracy limitations and recommend proper timer peripherals for precise delays - Add examples for sfence_vma() showing ASID and address targeting - Improve multiprocessor considerations documentation for fence_i - Standardize documentation format with consistent Safety, Behavior, and Use Cases sections These changes maintain full backward compatibility while significantly improving developer experience and preventing common usage mistakes. Add CHANGELOG.md register: add dcsr CSR support Re-added unimplemented!(), and removed SAFETY comments Fixed CHANGELOG.md Resolve merge conflict Update CHANGELOG.md Resolve merge conflict Added back spaces Removed unneeded files Delete CHANGELOG.md Resolve merge conflict Fix indentations Refactor unimplemented!() calls and update documentation for EBREAK instruction. Added the initial sections of the CHANGELOG.md Added a changelog to document notable changes and adhere to versioning standards. Fix formatting in asm! macro usage Update CHANGELOG.md
1 parent 3dcea0e commit dbb57e9

File tree

3 files changed

+85
-30
lines changed

3 files changed

+85
-30
lines changed

riscv/CHANGELOG.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
- Improved assembly macro handling in asm.rs
11+
12+
### Added
13+
14+
- Add `miselect` CSR
15+
16+
## [v0.15.0] - 2025-09-08
17+
18+
19+
### Added
20+
21+
- Add `miselect` CSR
22+
- Improved assembly macro handling in asm.rs
23+
1024
## [v0.15.0] - 2025-09-08
1125

1226
### Added
@@ -112,6 +126,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
112126
- Export `riscv::register::macros` module macros for external use
113127
- Add `riscv::register::mcountinhibit` module for `mcountinhibit` CSR
114128
- Add `Mcounteren` in-memory update functions
129+
- Add `Mcounteren` in-memory update functions
115130
- Add `Mstatus` vector extension support
116131
- Add fallible counterparts to all functions that `panic`
117132
- Add `riscv-pac` as a dependency
@@ -279,4 +294,4 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
279294
[v0.7.0]: https://github.com/rust-embedded/riscv/compare/v0.6.0...v0.7.0
280295
[v0.6.0]: https://github.com/rust-embedded/riscv/compare/v0.5.6...v0.6.0
281296
[v0.5.6]: https://github.com/rust-embedded/riscv/compare/v0.5.5...v0.5.6
282-
[v0.5.5]: https://github.com/rust-embedded/riscv/compare/v0.5.4...v0.5.5
297+
[v0.5.5]: https://github.com/rust-embedded/riscv/compare/v0.5.4...v0.5.5

riscv/src/asm.rs

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,45 +20,70 @@ macro_rules! instruction {
2020
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
2121
unimplemented!();
2222
}
23-
);
23+
)
2424
}
2525

2626
instruction!(
27-
/// `nop` instruction wrapper
27+
/// `NOP` instruction wrapper
2828
///
2929
/// The `NOP` instruction does not change any architecturally visible state, except for
30-
/// advancing the pc and incrementing any applicable performance counters.
30+
/// advancing the PC and incrementing any applicable performance counters.
3131
///
3232
/// This function generates a no-operation; it's useful to prevent delay loops from being
3333
/// optimized away.
34-
, nop, "nop", options(nomem, nostack));
34+
, nop, "nop", options(nomem, nostack, preserves_flags));
3535

3636
instruction!(
3737
/// `WFI` instruction wrapper
3838
///
39-
/// Provides a hint to the implementation that the current hart can be stalled until an interrupt might need servicing.
40-
/// The WFI instruction is just a hint, and a legal implementation is to implement WFI as a NOP.
41-
, wfi, "wfi", options(nomem, nostack));
39+
/// Provides a hint to the implementation that the current hart can be stalled until an
40+
/// interrupt might need servicing. The WFI instruction is just a hint, and a legal
41+
/// implementation is to implement WFI as a NOP.
42+
///
43+
/// # Behavior
44+
///
45+
/// - May cause the hart to enter a low-power state
46+
/// - Will be interrupted by any enabled interrupt
47+
/// - No guarantee of actual power savings (implementation-dependent)
48+
,wfi, "wfi", options(nomem, nostack, preserves_flags));
4249

4350
instruction!(
4451
/// `EBREAK` instruction wrapper
4552
///
46-
/// Generates a breakpoint exception.
47-
, unsafe ebreak, "ebreak", options(nomem, nostack));
53+
/// Generates a breakpoint exception for use by debuggers.
54+
///
55+
/// # Behavior
56+
///
57+
/// When executed, this instruction causes a breakpoint exception to be raised,
58+
/// which will typically be handled by a debugger or exception handler.
59+
///
60+
/// # Safety
61+
///
62+
/// This function is unsafe because it unconditionally generates an exception,
63+
/// which can disrupt normal program flow. Only call this when you intend to
64+
/// trigger a breakpoint.
65+
, unsafe ebreak, "ebreak", options(nomem, nostack, preserves_flags));
4866

4967
instruction!(
5068
/// `ECALL` instruction wrapper
5169
///
52-
/// Generates an exception for a service request to the execution environment.
53-
/// When executed in U-mode, S-mode, or M-mode, it generates an environment-call-from-U-mode
54-
/// exception, environment-call-from-S-mode exception, or environment-call-from-M-mode exception,
55-
/// respectively, and performs no other operation.
70+
/// Generates an environment call exception for system services.
5671
///
57-
/// # Note
72+
/// # Behavior
5873
///
59-
/// The ECALL instruction will **NOT** save and restore the stack pointer, as it triggers an exception.
60-
/// The stack pointer must be saved and restored accordingly by the exception handler.
61-
, unsafe ecall, "ecall", options(nomem, nostack));
74+
/// When executed in different privilege modes:
75+
/// - U-mode: Generates environment-call-from-U-mode exception
76+
/// - S-mode: Generates environment-call-from-S-mode exception
77+
/// - M-mode: Generates environment-call-from-M-mode exception
78+
///
79+
/// # Safety
80+
///
81+
/// This function is unsafe because:
82+
/// - It unconditionally generates an exception
83+
/// - The stack pointer is **NOT** automatically saved/restored
84+
/// - The exception handler is responsible for proper context management
85+
/// - Improper use can crash the system
86+
, unsafe ecall, "ecall", options(nomem, nostack, preserves_flags));
6287

6388
instruction!(
6489
/// `SFENCE.VMA` instruction wrapper (all address spaces and page table levels)
@@ -118,8 +143,8 @@ instruction!(
118143
pub fn sfence_vma(asid: usize, addr: usize) {
119144
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
120145
unsafe {
121-
core::arch::asm!("sfence.vma {0}, {1}", in(reg) addr, in(reg) asid, options(nostack));
122-
};
146+
core::arch::asm!("sfence.vma {}, {}", in(reg) addr, in(reg) asid, options(nostack));
147+
}
123148
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
124149
unimplemented!();
125150
}
@@ -139,21 +164,19 @@ pub fn sfence_vma(asid: usize, addr: usize) {
139164
allow(unused_variables)
140165
)]
141166
pub fn delay(cycles: u32) {
142-
match () {
143-
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
144-
() => {
145-
let real_cyc = 1 + cycles / 2;
146-
unsafe {
147-
core::arch::asm!(
167+
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
168+
{
169+
let real_cyc = 1 + cycles / 2;
170+
unsafe {
171+
core::arch::asm!(
148172
"2:",
149173
"addi {0}, {0}, -1",
150174
"bne {0}, zero, 2b",
151175
inout(reg) real_cyc => _,
152176
options(nomem, nostack),
153-
);
154-
}
177+
);
155178
}
156-
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
157-
() => unimplemented!(),
158179
}
180+
#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
181+
unimplemented!();
159182
}

riscv/src/register/miselect.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,20 @@ read_write_csr_field! {
4545
/// and the relevant `mireg*` value.
4646
value: [0:62],
4747
}
48+
49+
#[cfg(test)]
50+
mod tests {
51+
use super::*;
52+
53+
#[test]
54+
fn test() {
55+
(0..=usize::BITS)
56+
.map(|r| ((1u128 << r) - 1) as usize)
57+
.for_each(|bits| {
58+
let mut miselect = Miselect::from_bits(bits);
59+
60+
test_csr_field!(miselect, is_custom);
61+
test_csr_field!(miselect, value: [0, usize::BITS - 2], 0);
62+
});
63+
}
64+
}

0 commit comments

Comments
 (0)