-
Notifications
You must be signed in to change notification settings - Fork 204
Better handling of misaligned accesses (take 2) #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
base: master
Are you sure you want to change the base?
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.
val split_misaligned : forall 'width, 'width > 0. | ||
(virtaddr, int('width)) -> {'n 'bytes, 'width == 'n * 'bytes & 'bytes > 0. (int('n), int('bytes))} |
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 am not sure if I overlooked that Sail feature, but I have not encountered it so far (is this new?). So essentially, it allows validating that the return values satisfy certain conditions?
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.
Yes, I think it's an existential type; it's mentioned in passing in the Sail manual (see the val div1
example). It's been around for a while I think.
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's not new. Not sure exactly what it's called (refinement type, liquid type, existential type, etc. take a guess!) but yeah it lets you add conditions to a type. I think we use them in some type aliases too; it doesn't have to be in the return position.
You can use them in argument positions too but we generally use the forall
syntax instead.
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
model/riscv_vmem_utils.sail
Outdated
let region_width = min(2 ^ pagesize_bits, sys_misaligned_allowed_within()); | ||
|
||
// If the Zama16b extension is enabled, the region_width must be at least 16 | ||
let region_width = if currentlyEnabled(Ext_Zama16b) then { |
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 interaction between Zama16b
and allowed_within
still needs to be resolved: #860 (comment). As discussed in that issue, I think Zama16b should not directly impact this function. Once we have configuration validation set up, we can have an assertion that if Zama16b is supported then allowed_within >= 16. For this PR, I think I would be in favor of just dropping the Zama16b configuration option altogether.
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, makes sense to add Zama16b on top of this later. Removed.
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!
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.
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!
This is a rebased version of #467.
The first commit is essentially the same as #467, except rebased and made to work with the config system.
The second commit uses the new
vmem_{read,write}
helpers in the floating point and vector extensions.The AMO instructions are intact, since they don't fit nicely into the assumptions of the helpers. So are the
zicboz
andzicbom
; they are low-level anyway so should not use a high-level helper. Fetch is untouched, left for future.I tested variations of the new config parameters to ensure the upstream riscv-tests and vector tests still pass (or have no regressions, in the case of vector).