-
Notifications
You must be signed in to change notification settings - Fork 214
Handle address translation for misaligned loads and stores better #861
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
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 awesome! Just a few comments
model/riscv_insts_base.sail
Outdated
match vmem_write(vaddr, width_bytes, data, aq, rl, false) { | ||
Ok(_) => RETIRE_SUCCESS, | ||
Err(vaddr, e) => { | ||
handle_mem_exception(vaddr, e); | ||
return RETIRE_FAIL | ||
} |
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.
match vmem_write(vaddr, width_bytes, data, aq, rl, false) { | |
Ok(_) => RETIRE_SUCCESS, | |
Err(vaddr, e) => { | |
handle_mem_exception(vaddr, e); | |
return RETIRE_FAIL | |
} | |
match vmem_write(vaddr, width_bytes, data, aq, rl, false) { | |
Ok(_) => RETIRE_SUCCESS, | |
Err(vaddr, e) => { handle_mem_exception(vaddr, e); return RETIRE_FAIL } |
To match model/riscv_insts_fext.sail and the rest.
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.
This will change anyway once I rebase on top of #755.
model/riscv_insts_fext.sail
Outdated
Err(vaddr, e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, | ||
Ok(result) => { F(rd) = nan_box(result); RETIRE_SUCCESS } |
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(vaddr, e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, | |
Ok(result) => { F(rd) = nan_box(result); RETIRE_SUCCESS } | |
Ok(result) => { F(rd) = nan_box(result); RETIRE_SUCCESS } | |
Err(vaddr, e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, |
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.
Thanks, done.
model/riscv_vmem_utils.sail
Outdated
function prop_access_within_is_aligned(addr : bits(32), bytes : bits(4)) -> bool = { | ||
let bytes = unsigned(zero_extend(32, 0b1) << unsigned(bytes)); | ||
if bytes > 0 then { | ||
access_within(addr, bytes, bytes) == (fmod_int(unsigned(addr), bytes) == 0) |
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.
What is fmod_int()
doing?
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.
Good question. It's integer modulus. I now notice there are two of these: emod_int
and fmod_int
. The first always returns a positive value, the second ('f' stands for 'floor' according to GMP docs) retains the sign of the divisor. Not sure the difference matters here. @Alasdair?
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.
fdiv
and fmod
are flooring, so they round down always. tdiv
and tmod
are truncating so they round towards zero. emod
and ediv
are euclidian division. Wikipedia has good summary of the differences here https://en.wikipedia.org/wiki/Modulo#Variants_of_the_definition
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.
The only reason we really have euclidian division is it's the definition used in the SMT integer theory
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.
Seems like since these are both positive, they’d all be the same? In which case we might as well use %
, which is already defined in the prelude to mean emod
.
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.
The SMT properties check out in both cases, so I'll switch it to %
when I rebase.
9323a72
to
a23d5fc
Compare
The last push rebased on master and refactored #467 to pull the As before, AMOs, fetch, and CBOs are untouched. There is a slight difference in alignment checks for LOADRES/STORECON in the read/write helpers. I'll try to clean it up before final merge. @Alasdair could you check if this breaks RVWMO modelling in any way? There's a comment in |
Hmm, the CI failure is odd. It's building locally (and passing tests) with Sail 0.19. |
Drat, I think this is triggering a bug in the smt backend of Sail, both 0.19 and the latest master. |
a23d5fc
to
d5ffd8c
Compare
066874c
to
fec2fa5
Compare
@bacam Could you take a look at this Rocq failure? Perhaps it's being triggered by 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.
Overall looking like an amazing simplification!
model/riscv_vmem_utils.sail
Outdated
|
||
// If the Zama16b extension is enabled, the region_width must be at least 16 | ||
let region_width = if currentlyEnabled(Ext_Zama16b) then { | ||
max_int(16, region_width) |
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.
max_int(16, region_width) | |
max(16, region_width) |
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.
Fixed.
See the [Virtual Memory Notes](./notes_Virtual_Memory.adoc) for | ||
details. | ||
|
||
- The `riscv_vmem_utils.sail` file provides a higher level interface |
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.
Might be worth adding a more detailed description to the notes_Virtual_Memory.adoc
file.
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'm not sure what can go in there in addition to what's already described in comments in riscv_vmem_utils.sail
.
fec2fa5
to
597d678
Compare
4fd40f9
to
50034c4
Compare
model/riscv_vmem_utils.sail
Outdated
/* If the load is misaligned or an allowed misaligned access, split into `n` | ||
(single-copy-atomic) memory operations, each of `bytes` width. If the load is | ||
aligned, then `n` = 1 and bytes will remain unchanged. */ | ||
let ('n, bytes) = split_misaligned(vaddr, width); |
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.
We can work around the Rocq problem by changing bytes
to 'bytes
- this gives data
a printable type that can be used in rewrites. (Rocq also needs a couple of termination measures, but I'll give those separately.)
For Rocq output we also need to add two termination measures to
Although it would be helpful if someone could check that |
50034c4
to
132308b
Compare
Yeah, I think Your suggestions fixed the build. Thanks! |
132308b
to
3c0a61a
Compare
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!
It would be great to prioritize and get this merged so work on the other PRs can move forward!
3c0a61a
to
677dab9
Compare
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 that the configuration issue has been resolved. This will be great to get in!
677dab9
to
e268359
Compare
I'll merge this tomorrow. |
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.
Do you mind waiting a day for me to take a more detailed look? Sorry I've been putting it off but I'll look tomorrow. I'd like to make sure it works for us and also with #866.
Also I think we really need to clean up the AccessType
system because the behaviour is kind of half split between AccessType
and the res
/aq
/con
flags. I kind of think we should remove those flags and move everything into AccessType
. (In future of course.)
e268359
to
4453ef4
Compare
4453ef4
to
8b7febc
Compare
Refactor the LOAD and STORE instruction so they split misaligned accesses into multiple sub-accesses and perform address translation separately. This means we should handle the case where a misaligned access straddles a page boundary in a sensible way, even if we don't yet cover the full range of possibilities allowed for any RISC-V implementation. There are options for the order in which misaligned happen, i.e. from high-to-low or from low-to-high as well as the granularity of the splitting, either all the way to bytes or to the largest aligned size. The splitting can also be disabled if an implementation supports misaligned accesses in hardware. In addition tidy up the implementation in a few ways: - Very long lines on the LOAD encdec were fixed by adding a helper - Add some linebreaks in the code so it reads as less claustrophobic - Ensure we use the same names for arguments in encdec/execute/assembly. Previously we used 'size' and 'width'. I opted for 'width' consistently. Primary author: Alasdair Armstrong <[email protected]> Co-authored-by: Alasdair Armstrong <[email protected]>
Add some comments on the API available from `vmem_utils`. Update Makefile.old for SMT properties. Update the ReadingGuide.
8b7febc
to
3477a6f
Compare
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.
Thanks, LGTM!
I think we will probably want to make this more configurable in future, but it at least fixes the page straddling problem which is currently totally broken... 🚀
Lean does not use termination measures for loops, so we need to guard their definitions. The problematic measures was introduced by #861.
Refactor the LOAD and STORE instruction so they split misaligned
accesses into multiple sub-accesses and perform address translation
separately. This means we should handle the case where a misaligned
access straddles a page boundary in a sensible way, even if we don't
yet cover the full range of possibilities allowed for any RISC-V
implementation.
There are options for the order in which misaligned happen, i.e. from
high-to-low or from low-to-high as well as the granularity of the splitting,
either all the way to bytes or to the largest aligned size. The splitting
can also be disabled if an implementation supports misaligned accesses in hardware.
In addition tidy up the implementation in a few ways:
Very long lines on the LOAD encdec were fixed by adding a helper
Add some linebreaks in the code so it reads as less claustrophobic
Ensure we use the same names for arguments in encdec/execute/assembly.
Previously we used 'size' and 'width'. I opted for 'width' consistently.
Co-authored-by: Alasdair Armstrong [email protected]