Conversation
model/riscv_insts_zilsd.sail
Outdated
| match ext_data_get_addr(rs1, offset, Read(Data), width_bytes) { | ||
| Ext_DataAddr_Error(e) => { ext_handle_data_check_error(e); RETIRE_FAIL }, | ||
| Ext_DataAddr_OK(vaddr) => | ||
| if check_misaligned(vaddr, width) | ||
| then { handle_mem_exception(vaddr, E_Load_Addr_Align()); RETIRE_FAIL } | ||
| else match translateAddr(vaddr, Read(Data)) { | ||
| TR_Failure(e, _) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, | ||
| TR_Address(paddr, _) => | ||
| match mem_read(Read(Data), paddr, 8, false, false, false) { | ||
| Ok(result) => { | ||
| X(rd) = result[31..0]; | ||
| X(rd + 1) = result[63..32]; | ||
| RETIRE_SUCCESS | ||
| }, | ||
| Err(e) => { handle_mem_exception(vaddr, e); RETIRE_FAIL }, | ||
| }, | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
I'm curious, wouldn't it make more sense to replace LOAD_RV32 (and STORE_RV32) with two sequential 32-bit load/store operations instead of one 64-bit load/store operation?
Most 32-bit systems have a 32-bit memory bus, so performing two 32-bit accesses would be more realistic than a single 64-bit access on such hardware.
This implementation would also allow us to test the more interesting case where interrupts could occur between the two operations, as explicitly permitted by the Zilsd specification.
There was a problem hiding this comment.
That's definitely a good idea, I didn't think of that
a979234 to
a28bd1b
Compare
model/riscv_insts_zilsd.sail
Outdated
| function clause extensionEnabled(Ext_Zilsd) = true & xlen == 32 | ||
|
|
||
| /* ****************************************************************** */ | ||
| union clause ast = LOAD_RV32 : (bits(12), regidx, regidx) |
There was a problem hiding this comment.
LOAD_DOUBLE might be a better name for the AST constructor than LOAD_RV32. It's unfortunate that the spec re-uses LOAD. (Could we ask the spec authors to change this before ratification?) Similarly for STORE_RV32.
There was a problem hiding this comment.
I saw your reply at riscvarchive/riscv-zilsd#64, so I update it to the format of EXT_INST(ZILSD_LD...).
|
how does this relate to #490? |
I didn't see it before. Currently, the code mainly has the following differences
|
d6533f5 to
d70a272
Compare
|
@trdthg Could you check with @christian-herber-nxp to make sure we're not missing anything from #490 and we get the appropriate co-authors? |
|
the author of the original PR should be clear from that, it is @simonacostinescu |
c1bff11 to
ea18ab9
Compare
UpdateI am trying to run act tests (there is already a PR, not merged yet), but encountered a few problems
I think you could review this after I finished those tests.
|
b7f8bbe to
5864d1a
Compare
|
Rebased. I also added two first-party tests. Since I need to specify specific config for these two tests, I changed the CMake a lot and introduced two python scripts:
Btw, I don't really understand how to properly write |
Timmmm
left a comment
There was a problem hiding this comment.
I've been really really really trying to avoid adding any Python, since it usually ends up being a complete nightmare. It's not quite so bad these days with uv but if we do add any we will have to do the whole pyproject.toml, Pyright, Pylint stuff.
My strong preference would be to use almost anything other than Python. Maybe Deno.
| function clause execute (ZCLSD_C_LD(uimm, rsc, rdc)) = { | ||
| let rd = creg2reg_idx(rdc); | ||
| let rs = creg2reg_idx(rsc); | ||
| execute(ZILSD_LD(zero_extend(uimm), rs, rd)) |
| function clause execute ZILSD_SD(imm, rs2, rs1) = { | ||
| let base_addr = X(rs1); | ||
| let rs2_val = X(rs2); | ||
| let rs2_pair_val = if rs2 != zreg then X(rs2+1) else rs2_val; |
| Some(e) => Memory_Exception(vaddr, e), | ||
| None() => { | ||
| let vaddr = Virtaddr(base_addr + sign_extend(imm + 4)); | ||
| match load_imm(vaddr, 4, rd+1) { |
There was a problem hiding this comment.
This is incorrect. It will write to x1 if you load into x0. I'd use X_pair here too.
| $[wavedrom "C.LDSP offset[5] dest offset[4:3|8:6] C2"] | ||
| mapping clause encdec_compressed = ZCLSD_C_LDSP(ui86 @ ui5 @ ui43 @ 0b000, rd) | ||
| <-> 0b011 @ ui5 : bits(1) @ encdec_reg(rd) @ ui43 : bits(2) @ ui86 : bits(3) @ 0b10 | ||
| when currentlyEnabled(Ext_Zclsd) |
There was a problem hiding this comment.
For C.LDSP, usage of x0 as the destination is reserved.
| $[wavedrom "C.SDSP offset[5:3|8:6] src C2"] | ||
| mapping clause encdec_compressed = ZCLSD_C_SDSP(ui86 @ ui53 @ 0b000, rs2) | ||
| <-> 0b111 @ ui53 : bits(3) @ ui86 : bits(3) @ encdec_reg(rs2) @ 0b10 | ||
| when currentlyEnabled(Ext_Zclsd) |
There was a problem hiding this comment.
These compressed encodings are missing the odd register check I think?
Also double check how we do it for the other instructions that only allow even registers (Zfinx). We have a config setting to configure that behaviour so we should make the code the same style at least.
config/config.json.in
Outdated
| "supported": true | ||
| }, | ||
| "Zilsd": { | ||
| "supported": true |
There was a problem hiding this comment.
I think this is only supported on RV32 so this should be
| "supported": true | |
| "supported": @CONFIG_XLEN_IS_32@ |
Also we should probably add a check to validate_config.sail to make sure you don't set this on RV64.
I think python is fine as long as it is limited to 3.8 (or whatever the version in RHEL8 is) with only the standard library. Otherwise I agree that it can be a dependency hell. |
| @@ -0,0 +1,38 @@ | |||
| #!/usr/bin/env python3 | |||
| import json | |||
There was a problem hiding this comment.
This script shouldn't be too difficult to write in CMake?
542c5b7 to
a5a5afe
Compare
Yeah but third party libraries always creep in so even in that case you need to start with a proper setup. If we do start using Python we're going to end up using at least Pydantic and Typer.
Deno is easier to install than Python + uv. It's literally one command. I don't think the avoidance of a single command is worth the pain of Python.
I think that's a good idea. |
|
Lean is not happy again. But this is a bit tricky because Zcf and Zclsd seem to be at the same level.
The error msg is but if you write Zcf > Zclsd It will become: |
Timmmm
left a comment
There was a problem hiding this comment.
Much better! The --config-override thing seems to be a lot simpler and nicer than I would have guessed. I think it needs to go in its own PR though.
248f935 to
a85d50f
Compare
ead8f1a to
79deb26
Compare
pmundkur
left a comment
There was a problem hiding this comment.
Looks pretty close; just minor fixes.
Co-authored-by: Simona Costinescu <simona.costinescu@nxp.com>
|
@trdthg i made some minor fixes, hope that's okay. I wonder what you think about the TODO I left. |
|
LGTM. For the alignment issue, my current thought is to either modify the function definitions directly or overload diff --git a/model/extensions/Zilsd/zilsd_insts.sail b/model/extensions/Zilsd/zilsd_insts.sail
index 60c7fd7b..4ea5f8a2 100644
--- a/model/extensions/Zilsd/zilsd_insts.sail
+++ b/model/extensions/Zilsd/zilsd_insts.sail
@@ -29,9 +29,10 @@ mapping clause encdec = ZILSD_LD(imm, rs1, rd)
function clause execute ZILSD_LD(imm, rs1, rd) = {
assert(xlen == 32);
let access = Load(Data);
- match vmem_read(rs1, sign_extend(imm), 4, access, false, false, false) {
+ let align_width = if true then 8 else 4;
+ match vmem_read(rs1, sign_extend(imm), 4, align_width, access, false, false, false) {
Ok(lo) => {
- match vmem_read(rs1, sign_extend(imm + 4), 4, access, false, false, false) {
+ match vmem_read(rs1, sign_extend(imm + 4), 4, align_width, access, false, false, false) {
Ok(hi) => { X_pair(rd) = hi @ lo; RETIRE_SUCCESS },
Err(e) => e,
}
diff --git a/model/sys/vmem_utils.sail b/model/sys/vmem_utils.sail
index a54d44f2..4dde6a74 100644
--- a/model/sys/vmem_utils.sail
+++ b/model/sys/vmem_utils.sail
@@ -130,14 +130,14 @@ private function access_causes_misaligned_exception(
// External API
-val vmem_read_addr : forall 'width, is_mem_width('width).
- (virtaddr, xlenbits, int('width), MemoryAccessType(mem_payload), bool, bool, bool)
+val vmem_read_addr_with_custom_align : forall 'width 'align_width, is_mem_width('width) & is_mem_width('align_width).
+ (virtaddr, xlenbits, int('width), int('align_width), MemoryAccessType(mem_payload), bool, bool, bool)
-> result(bits(8 * 'width), ExecutionResult)
-function vmem_read_addr(vaddr, offset, width, access, aq, rl, res) = {
+function vmem_read_addr_with_custom_align(vaddr, offset, width, align_width, access, aq, rl, res) = {
// "LR faults like a normal load, even though it's in the AMO major opcode space."
// - Andrew Waterman, isa-dev, 10 Jul 2018.
- if access_causes_misaligned_exception(vaddr, width, res)
+ if access_causes_misaligned_exception(vaddr, align_width, res)
then return Err(Memory_Exception(vaddr, E_Load_Addr_Align()));
// If the load is misaligned or an allowed misaligned access, split into `n`
@@ -180,6 +180,16 @@ function vmem_read_addr(vaddr, offset, width, access, aq, rl, res) = {
Ok(data)
}
+val vmem_read_addr_with_width_align : forall 'width, is_mem_width('width).
+ (virtaddr, xlenbits, int('width), MemoryAccessType(mem_payload), bool, bool, bool)
+ -> result(bits(8 * 'width), ExecutionResult)
+
+function vmem_read_addr_with_width_align(vaddr, offset, width, access, aq, rl, res) = {
+ vmem_read_addr_with_custom_align(vaddr, offset, width, width, access, aq, rl, res)
+}
+
+overload vmem_read_addr = { vmem_read_addr_with_width_align, vmem_read_addr_with_custom_align }
+
// This lets the Rocq extraction know why the repeat loop above terminates
termination_measure vmem_read_addr repeat n
@@ -252,11 +262,11 @@ function vmem_write_addr(vaddr, width, data, access, aq, rl, res) = {
// This lets the Rocq extraction know why the repeat loop above terminates
termination_measure vmem_write_addr repeat n
-val vmem_read : forall 'width, is_mem_width('width).
- (regidx, xlenbits, int('width), MemoryAccessType(mem_payload), bool, bool, bool)
+val vmem_read_with_custom_align : forall 'width 'align_width, is_mem_width('width) & is_mem_width('align_width).
+ (regidx, xlenbits, int('width), int('align_width), MemoryAccessType(mem_payload), bool, bool, bool)
-> result(bits(8 * 'width), ExecutionResult)
-function vmem_read(rs, offset, width, access, aq, rl, res) = {
+function vmem_read_with_custom_align(rs, offset, width, align_width, access, aq, rl, res) = {
// Get the address, X(rs1) + offset.
// Extensions might perform additional checks on address validity.
let vaddr : virtaddr = match ext_data_get_addr(rs, offset, access, width) {
@@ -264,9 +274,19 @@ function vmem_read(rs, offset, width, access, aq, rl, res) = {
Ext_DataAddr_Error(e) => return Err(Ext_DataAddr_Check_Failure(e)),
};
- vmem_read_addr(vaddr, offset, width, access, aq, rl, res)
+ vmem_read_addr_with_custom_align(vaddr, offset, width, align_width, access, aq, rl, res)
}
+val vmem_read_with_width_align : forall 'width, is_mem_width('width).
+ (regidx, xlenbits, int('width), MemoryAccessType(mem_payload), bool, bool, bool)
+ -> result(bits(8 * 'width), ExecutionResult)
+
+function vmem_read_with_width_align(rs, offset, width, access, aq, rl, res) = {
+ vmem_read_with_custom_align(rs, offset, width, width, access, aq, rl, res)
+}
+
+overload vmem_read = { vmem_read_with_custom_align, vmem_read_with_width_align }
+
val vmem_write : forall 'width, is_mem_width('width).
(regidx, xlenbits, int('width), bits(8 * 'width), MemoryAccessType(mem_payload), bool, bool, bool)
-> result(bool, ExecutionResult)Or we just add an extra alignment check for Zilsd? This would be the simplest approach. I personally prefer this option. :D |
|
I too prefer the simpler approach of an extra alignment check in Zilsd, and making it depend on a configuration option (something like |
spec: https://github.com/riscv/riscv-zilsd/blob/main/zilsd.adoc#insns-sd
function clause extensionEnabled(Ext_Zclsd) = true & xxxis a placeholder, waiting for config system