-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
riscv: add fallible functions #222
Conversation
We probably also want to cover the Wanted to submit the initial work to get feedback on the approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thank you so much. We can keep working in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks good to me. What do you think about more details in invalid values? Is it overcomplicating stuff maybe?
I've added suggested fixes as If you're happy with them, I'll squash them into their respective parent commits before a merge. I've also left conversations open to continue discussion on some of the style-related suggestions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is looking great! The only comments I have are:
- Adding an
InvalidVariant
error for those cases in which there are reserved values within a bitmask. - Updating "infallible" functions to use their "fallible" counterpart followed by an
unwrap()
. In this way, new panic messages will show a more comprehensive outcome.
7347b51
to
768f825
Compare
Ok, I added the next round of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far so good!
I was thinking about the correct location of the result
module and maybe we should consider moving it to riscv-pac
. Ideally, riscv-pac
will have way less activity and act as a dependency for all the riscv
ecosystem. Crates such as riscv
or riscv-peripheral
would re-export the result
module. Moving it to riscv-pac
will allow us to bump riscv
versions without breaking other crates, as there will not be version issues.
I'm not sure about the "correct" location for the I think the latter makes more sense, and follows with
We could still bump Maybe I'm misunderstanding the architecture, but I thought |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
You can get more information about the motivation of the You can think of Let us assume that we have the If we place the |
I think this makes sense. If you are planning to have In fact, if that's the plan, then moving A similar approach would still need to be taken for any additions to the I'll move it in a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
riscv/src/lib.rs
Outdated
@@ -40,6 +40,7 @@ pub(crate) mod bits; | |||
pub mod delay; | |||
pub mod interrupt; | |||
pub mod register; | |||
pub use riscv_pac::result; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be handy to reexport the riscv-pac
crate
pub use riscv_pac::result; | |
pub use riscv_pac::{self as pac, result}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... or even pub use riscv_pac::*
?
Adds the `result` module to contain types for fallible functions. For discussion, see: <rust-embedded#212 (comment)>
Adds fallible `try_` function variants to most `register` module macros.
Adds fallible access functions for `Mcounteren` HPM fields.
Adds fallible access functions for `Scounteren` HPM fields.
Adds fallible access functions for `Mcountinhibit` HPM fields.
Adds fallible access functions for `Satp` ASID and PPN fields.
Adds fallible conversion functions for `Pmpcfgx` permission and range fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I think this is done. The main new features are:
While there are other aspects to polish (e.g., modifying |
@rmsyn could you please update the |
Uses the new `Result` type for library traits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Now we need to update riscv-peripheral
😁
😅 I looked for current usage of the traits, and must have missed |
Uses the `riscv_pac::result::*` types for unsafe trait implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know what you think about my comments
riscv-pac/src/result.rs
Outdated
/// Invalid field value. | ||
InvalidValue { | ||
field: &'static str, | ||
value: usize, | ||
bitmask: usize, | ||
}, | ||
/// Invalid value of a register field that does not match any known variants. | ||
InvalidVariant { field: &'static str, value: usize }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could differentiate errors regarding fields of a register and errors regarding the whole register/value. The idea is avoiding defining the field
in the riscv-peripheral
examples, as I think it is not necessary.
/// Invalid field value. | |
InvalidValue { | |
field: &'static str, | |
value: usize, | |
bitmask: usize, | |
}, | |
/// Invalid value of a register field that does not match any known variants. | |
InvalidVariant { field: &'static str, value: usize }, | |
/// Invalid value of a register field. | |
InvalidFieldValue { | |
field: &'static str, | |
value: usize, | |
bitmask: usize, | |
}, | |
/// Invalid value of a register field that does not match any known variants. | |
InvalidFieldVariant { field: &'static str, value: usize }, | |
/// Invalid value. | |
InvalidValue { | |
value: usize, | |
bitmask: usize, | |
}, | |
/// Invalid value that does not match any known variants. | |
InvalidVariant(usize), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could differentiate errors regarding fields of a register and errors regarding the whole register/value.
This makes sense to me. The value covers the entire structure, so this separation could be useful in other cases without subfields.
riscv-peripheral/examples/e310x.rs
Outdated
if number > Self::MAX_HART_ID_NUMBER { | ||
Err(number) | ||
Err(Error::InvalidVariant { | ||
field: "hart_id", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding field
to these errors feels unnecessary to me.
Changes current `Invalid*` variants to `InvalidField*` variants to indicate their use for subfields in an outer struct. Adds the field-less counterparts for use in a context without subfields.
Added the recommended changes. Hopefully they cover the contexts you were concerned with. Agree that for contexts where the value covers the entire structure, we can get the necessary context from the conversion function, e.g. in a backtrace / panic dump. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know what you think of my review. It feels to me like the errors containing field names are not that necessary.
_ => Err(Error::InvalidFieldValue { | ||
field: "permission", | ||
value: val as usize, | ||
bitmask: 0b111, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_ => Err(Error::InvalidFieldValue { | |
field: "permission", | |
value: val as usize, | |
bitmask: 0b111, | |
_ => Err(Error::InvalidValue { | |
value: val as usize, | |
bitmask: 0b111, |
_ => Err(Error::InvalidFieldValue { | ||
field: "range", | ||
value: val as usize, | ||
bitmask: 0b11, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_ => Err(Error::InvalidFieldValue { | |
field: "range", | |
value: val as usize, | |
bitmask: 0b11, | |
_ => Err(Error::InvalidValue { | |
value: val as usize, | |
bitmask: 0b11, |
I can appreciate that reviews are incremental, but this could have been made clearer in the last set of changes. The It also clarifies situations where multiple fields could return/bubble-up an error. For instance, in a function parsing the |
Hey @rmsyn sorry if it annoyed you. After the last changes, I thought that backtracking would be enough to find out which field changed, with no need to add static strings to the binary. In any case, if you think that variants that indicate the invalid field are necessary/valuable, we can definitely leave them as is, I have no strong feelings against them. I will wait a couple of days in case anyone from @rust-embedded/riscv wants to leave their review and merge it to master. |
I think the If we did use an enum, or follow We could also just drop the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Let's leave the |
Adds fallible variants to all functions that explicitly panic in the
riscv
crate.Resolves: #212