-
Notifications
You must be signed in to change notification settings - Fork 747
Rename matches_any()
to any_matching_bits_set()
, implement new matches_any()
#3336
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
Conversation
Need to update readme. |
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 good except for the pending README update. Thanks @hudson-ayers!
3939b1f
to
e761468
Compare
README updated |
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.
Fixing this is a little confusing.
If we look at what is probably a very old use of this API (in SAM4L USART), it makes it more clear what matches_any()
was trying to do do:
let ints_active = self.registers.imr.matches_any(
Interrupt::RXBUFF::SET
+ Interrupt::TXEMPTY::SET
+ Interrupt::TIMEOUT::SET
+ Interrupt::PARE::SET
+ Interrupt::FRAME::SET
+ Interrupt::OVRE::SET
+ Interrupt::TXRDY::SET
+ Interrupt::RXRDY::SET,
);
...
if !(rx_active || tx_active || ints_active || is_panic) {
pm::disable_clock(self.clock);
}
Beside my point about matches_all()
no longer being consistent, do we actually want two functions? It seems like what we want from an API point of view is the new matches_any()
, and to update all current uses to the new version.
For example, this code in apollo3 stimer looks suspicious:
fn is_running(&self) -> bool {
let regs = self.registers;
regs.stcfg.any_matching_bits_set(STCFG::CLKSEL::XTAL_DIV2)
}
Particularly when given what start() does:
fn start(&self) -> Result<(), ErrorCode> {
// Set the clock source
self.registers.stcfg.write(STCFG::CLKSEL::XTAL_DIV2);
Ok(())
}
Shouldn't the is_running() check be regs.stcfg.matches_all([STCFG::CLKSEL::XTAL_DIV2])
?
I can see an efficiency argument for including any_matching_bits_set()
, but I'm worried that if we can't restrict it to only single bit fields then it can be used in ways it shouldn't be and lead to very strange behavior.
fn matches_any(&self, field: FieldValue<Self::T, Self::R>) -> bool { | ||
field.matches_any(self.get()) | ||
fn any_matching_bits_set(&self, field: FieldValue<Self::T, Self::R>) -> bool {< 8000 /span> | ||
field.any_matching_bits_set(self.get()) | ||
} | ||
|
||
#[inline] | ||
/// Check if all specified parts of a field match | ||
fn matches_all(&self, field: FieldValue<Self::T, Self::R>) -> bool { | ||
field.matches_all(self.get()) |
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 seems like matches_all()
needs to change as well. This is now all_matching_bits_set()
, right?
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.
matches_all()
is actually already correct -- since it was already checking for an exact match across the entire passed FieldValue
, it works correctly for multi-bit fields and for matching on cleared bits as well as set bits.
For convenience here are the two implementations:
/// Check if any of the bits covered by the mask for this
/// `FieldValue` are set in the passed value
#[inline]
pub fn any_matching_bits_set(&self, val: T) -> bool {
val & self.mask != T::zero()
}
/// Check if all specified parts of a field match
#[inline]
pub fn matches_all(&self, val: T) -> bool {
val & self.mask == self.value
}
matches_all()
actually looks at self.value()
and makes sure that the passed value, when masked, matches it. So the problem in #3311 does not apply.
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.
Ok good point. Seems like if
8000
there is only one FieldValue, then it should be .matches()
.
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.
Yeah, that makes sense to me, but I don't think the current name is really wrong ... not sure how to balance that with a desire not to modify the API of tock-registers more than needed, especially since it is the one library with non-Tock downstream users
Yeah, good call, this is incorrect, because CLKSEL is a multi-bit field.
For the interfaces currently defined in this PR, the correct change would be either
Yeah, the reason I included it is for efficiency -- when just matching on a bunch of single bit fields, it is much more efficient than the new |
e761468
to
00c1595
Compare
Pushed an update to fix that stimer example (which was broken before this PR, to be clear) |
I would be onboard with removing // current approach
// let any_bits_set_efficient = self.regs.srp.any_matching_bits_set(TX::INT::SET + RX::INT::SET);
// new approach if we remove `any_matching_bits_set()`
let any_bits_set_efficient = self.regs.srp.get() & (TX::INT::SET + RX::INT::SET).mask() != 0; |
Any thoughts on these two approaches? I personally am in favor of what is currently in the PR, but don't feel too strongly |
What I still feel like is swapping one quirk for another is that Can we #[inline]
pub fn any_matching_bits_set(&self, val: T) -> bool {
val & self.mask & self.value != T::zero()
} We could also call it if interrupts.any_set(
Status::BUSERR::SET
+ Status::SMBPECERR::SET
+ Status::SMBTOUT::SET
+ Status::ORUN::SET
+ Status::URUN::SET,
) {...} |
Yeah, I think that seems like a reasonable approach. We will have to re-write the unit tests for the function, as this change breaks the current unit tests, but I find the current unit tests somewhat incomprehensible anyway |
@bradjc I mean, presumably we could override the bitwise-OR operator for
Although this may also make it more confusing, as we don't know specifically which values we're using (presumably this would be
Not a fan of that as long as we're accepting any |
Yeah, I think that overriding the bitwise OR operator is probably going to make things more confusing, I would vote against that.
In practice, I think it was a mistake to make most of the functions in |
Yes, I agree with that. This function seem destined for misunderstanding their implementation and do not constrain the input types well to limit it to a reasonable subset of possible behaviors.
I like As a side note, something that made me skittish when seeing the example above was the use of the |
00c1595
to
52d20eb
Compare
The current implementation of matches_any() does not implement the functionality the name implies. This commit renames the existing implementation to a name which better describes its functionality, and introduces a new matches_any() function (with a different interface) that actually correctly implements the functionality suggested by the name. This commit also adds several tests to the tock-registers test suite to verify the new version works as expected, and removes a feature gate on a feature that no longer exists for the crate which was preventing some of the tock-registers teste suite from being run as part of `cargo test`.
52d20eb
to
480ee65
Compare
I rebased this PR, and made the following updates: I did not make the following changes:
|
ping? @lschuermann @bradjc |
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.
I've stood in the way long enough!
bors r+ |
Build succeeded:
|
Pull Request Overview
The current implementation of
matches_any()
does not implement the functionality the name implies. This PR renames the existing implementation to a name which better describes its functionality, and introduces a newmatches_any()
function (with a different interface) that actually correctly implements the functionality suggested by the name.This PR also adds several tests to the tock-registers test suite to verify the new version works as expected, and removes a feature gate on a feature that no longer exists for the crate which was preventing some of the tock-registers test suite from being run as part of
cargo test
.#3311 (comment) contains a complete description of the issues with the current method.
Fixes #3311
Testing Strategy
This pull request was tested by
cargo test
.TODO or Help Wanted
This pull request still needs feedback on method names
Documentation Updated
README.md
updated.Formatting
make prepush
.