-
Notifications
You must be signed in to change notification settings - Fork 204
Zvkned: add infrastructure for Zvkned #752
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.
A few random low-level Sail comments (I know nothing about the actual spec).
Also how was it tested against QEMU exactly? It would be nice to integrate tests like that (in future; we don't have the infrastructure for it yet).
model/riscv_insts_zvkned.sail
Outdated
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | ||
let num_elem = get_num_elem(LMUL_pow, SEW); | ||
|
||
if (zvk_check_elements(VLEN, num_elem, LMUL, SEW) == false) |
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.
if (zvk_check_elements(VLEN, num_elem, LMUL, SEW) == false) | |
if not(zvk_check_elements(VLEN, num_elem, LMUL, SEW)) |
(And in the other places.)
model/riscv_insts_zvkned.sail
Outdated
|
||
val aes_rotword : bits(32) -> bits(32) | ||
function aes_rotword(x) = { | ||
let a0 : bits (8) = x[ 7.. 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.
I think I would just simplify this to
function aes_rotword(x) = x[7 .. 0] @ x[15 .. 8] @ x[23 .. 16] @ x[31 .. 24]
model/riscv_insts_zvkned.sail
Outdated
} else { | ||
let 'n = num_elem; | ||
let 'm = SEW; | ||
assert('m == 32); |
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.
Is this necessarily true? Definitely worth a comment explaining why at least.
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 spec declared that it should be 32 bits, and without that, the Sail compiler will chuck an error, because it won't know how many bits 'm
has.
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.
Hmm the spec says it is reserved. I think we should maybe raise an illegal instruction exception in that case (though we still need a proper policy on how to handle reserved behaviour).
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 haven't looked at the spec closely enough yet, but if it is reserved it seems like it would be best to catch it at the encdec stage if possible and just not decode it as this instruction. Then it would fall through to the existing illegal instruction catch-all.
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 probably makes sense.
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, but then bits('m) would need to be bits(32) for Sail to prove it.
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.
You could do something like this:
let 'SEW = get_sew();
let LMUL_pow = get_lmul_pow();
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow;
let 'num_elem = get_num_elem(LMUL_pow, SEW);
if 'SEW != 32 | not(zvk_check_elements(VLEN, num_elem, LMUL, SEW)) then {
handle_illegal();
RETIRE_FAIL
} else {
let vs2_val = read_vreg(num_elem, SEW, LMUL_pow, vs2);
let vd_val = read_vreg(num_elem, SEW, LMUL_pow, vd);
let eg_len = (unsigned(vl) / 'num_elem);
...
I think that will compile. Not 100% sure though.
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.
That works, thank you!
model/riscv_insts_zvkned.sail
Outdated
|
||
let eg_len = (unsigned(vl) / 'n); | ||
let eg_start = (unsigned(vstart) / 'n); | ||
let keyelem = if suffix == "vv" then 1 else 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.
I think we should avoid having behaviour encoded in strings. suffix
should be an enum, not strings.
model/riscv_insts_zvkned.sail
Outdated
assert(0 <= ((i * 4) + 3) & ((i * 4) + 3) < 'n); | ||
|
||
let vd_state = get_velem(vd_val, i); | ||
let vs2_key = get_velem(vs2_val, keyelem * i); |
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 this would be something like:
let vs2_key = get_velem(vs2_val, match suffix { something_VV => i, something_VS => 0 });
(I'll leave you to come up with suitable names for whatever VV and VS mean!)
model/riscv_insts_zvkned.sail
Outdated
let vs2_key = get_velem(vs2_val, keyelem * i); | ||
let sb : bitvector(128) = aes_subbytes_fwd(vd_state); | ||
let sr : bitvector(128) = aes_shift_rows_fwd(sb); | ||
let ark : bitvector(128) = sr ^ vs2_key; |
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.
bits
? Maybe before my time; is bitvector
an old version of bits
?
model/riscv_insts_zvkned.sail
Outdated
let sb : bitvector(128, dec) = aes_subbytes_fwd(vd_state); | ||
let sr : bitvector(128, dec) = aes_shift_rows_fwd(sb); | ||
let mix : bitvector(128, dec) = aes_mixcolumns_fwd(sr); | ||
let ark : bitvector(128, dec) = mix ^ vs2_key; |
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.
bits(128)
. You could just delete all these, though it may be appropriate for readability.
model/riscv_insts_zvkned.sail
Outdated
assert('m == 32); | ||
|
||
let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2); | ||
let vd_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd); |
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.
Remove , dec
- Sail doesn't support per-vector orders now.
You could just delete the type annotations (I would, but up to you).
model/riscv_insts_zvkned.sail
Outdated
/* VAESDM.VV */ | ||
|
||
mapping vaesdm_mnemonic : bits(7) <-> string = { | ||
0b1010001 <-> "vaesem.vv", | ||
0b1010011 <-> "vaesem.vs", | ||
} |
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.
Comment and mapping name states vaesdm
but the mapping itself is happening for vaesem.[vv, vs]
mnemonics.
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.
Also the rest of the model maps ast
to assembly; not the bits directly.
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.
Still need to take a look at the spec, but here are some initial comments.
model/riscv_insts_zvkned.sail
Outdated
function get_velem(v, i) = v[4 * i + 3] @ v[4 * i + 2] @ v[4 * i + 1] @ v[4 * i] | ||
|
||
val zvk_check_elements : (int, int, int, int) -> bool | ||
function zvk_check_elements(VLEN, num_elem, LMUL, SEW) = { |
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.
With simple function declarations like this, it’s usually easier to eliminate the val line and directly integrate the types into the function line.
model/riscv_extensions.sail
Outdated
@@ -23,6 +23,7 @@ enum clause extension = Ext_C | |||
enum clause extension = Ext_B | |||
// Vector Operations | |||
enum clause extension = Ext_V | |||
enum clause extension = Ext_Zvkned |
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.
Missing comment with long form name of the extension. This should also be moved down to be with the rest of the Z* extensions in a new Zv* section.
model/riscv_insts_zvkned.sail
Outdated
let current_round_key = get_velem(vs2_val, i); | ||
|
||
let round_key_b = get_velem(vs2_val, i); |
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.
Specification states:
let CurrentRoundKey[3:0] : bits(128) = get_velem(vs2, EGW=128, i);
let RoundKeyB[3:0] : bits(32) = get_velem(vd, EGW=128, i); // Previous round key
9826514
to
3161d3c
Compare
I think the issues raised by the review have been resolved so far. @Timmmm @jordancarlin Is there anything else wrong with my code? |
@KotorinMinami Sorry about the delay in reviewing this. I think it needs some modifications because of the recent type refactoring for registers. Once it is rebased I'll give it another look. Would be good to get this one in soon for RVA23. |
I think we can move forward with this. @jordancarlin |
model/riscv_insts_zvkned.sail
Outdated
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | ||
let 'num_elem = get_num_elem(LMUL_pow, SEW); | ||
|
||
if 'SEW != 32 | (not(zvk_check_elements(VLEN, num_elem, LMUL, SEW))) |
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 still need that? Its part of the encdec
clause already (get_sew() == 32
)
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 about even moving the zvk_check_elements
check into the encdec clause?
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.
Need. The Sail compiler cannot obtain specific SEW information here (even if proven in encdec). Without specifying SEW, it will fail type checking.
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.
If it's just to make the Sail compiler happy then how about using an assert?
model/riscv_insts_zvkned.sail
Outdated
|
||
/* VAESKF2.VI */ | ||
|
||
union clause ast = RISCV_VAESKF2_VI : (vregidx, bits(5), vregidx) |
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.
You can remove the RISCV_* from all instruction names.
union clause ast = RISCV_VAESKF2_VI : (vregidx, bits(5), vregidx) | |
union clause ast = VAESKF2_VI : (vregidx, bits(5), vregidx) |
model/riscv_insts_zvkned.sail
Outdated
|
||
mapping clause encdec = RISCV_VAESKF2_VI(vs2, rnd, vd) | ||
<-> 0b1010101 @ encdec_vreg(vs2) @ rnd @ 0b010 @ encdec_vreg(vd) @ 0b1110111 | ||
when extensionEnabled(Ext_Zvkned) & get_sew() == 32 |
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.
when extensionEnabled(Ext_Zvkned) & get_sew() == 32 | |
when extensionEnabled(Ext_Zvkned) & get_sew() == 32 |
Spaces
model/riscv_insts_zvkned.sail
Outdated
let 'SEW = get_sew(); | ||
let LMUL_pow = get_lmul_pow(); | ||
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | ||
let 'num_elem = get_num_elem(LMUL_pow, 'SEW); |
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.
Formatting
let 'SEW = get_sew(); | |
let LMUL_pow = get_lmul_pow(); | |
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | |
let 'num_elem = get_num_elem(LMUL_pow, 'SEW); | |
let 'SEW = get_sew(); | |
let LMUL_pow = get_lmul_pow(); | |
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | |
let 'num_elem = get_num_elem(LMUL_pow, SEW); |
model/riscv_insts_zvkned.sail
Outdated
if 'SEW != 32 | (not(zvk_check_elements(VLEN, num_elem, LMUL, 'SEW))) | ||
then { | ||
handle_illegal(); | ||
RETIRE_FAIL | ||
} else { | ||
var rnd_val : bits(4) = rnd[3..0]; | ||
let vs2_val = read_vreg(num_elem, SEW, LMUL_pow, vs2); | ||
let vd_val = read_vreg(num_elem, SEW, LMUL_pow, vd); |
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.
Is there a reason why you use 'SEW
and sometimes SEW
? Probably a typo?
model/riscv_extensions.sail
Outdated
@@ -100,6 +100,9 @@ enum clause extension = Ext_Zksed | |||
// Scalar & Entropy Source Instructions: ShangMi Suite: SM3 Hash Cipher Instructions | |||
enum clause extension = Ext_Zksh | |||
|
|||
// Vector Instructions: NIST Suite: Vector AES Block Cipher |
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’s put this with the existing Zvk extensions.
model/riscv_insts_zvkned.sail
Outdated
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | ||
let 'num_elem = get_num_elem(LMUL_pow, SEW); | ||
|
||
if 'SEW != 32 | (not(zvk_check_elements(VLEN, num_elem, LMUL, SEW))) |
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 about even moving the zvk_check_elements
check into the encdec clause?
model/riscv_insts_zvkned.sail
Outdated
let sr = aes_shift_rows_fwd(sb); | ||
let ark = sr ^ vs2_key; | ||
|
||
write_single_element(128, i, vd, ark); |
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.
Writing an element of size 128 is not possible. This will cause a runtime assertion failure.
write_single_element()
invokes read_single_vreg()
, which contains the assertion:
assert(8 <= SEW && SEW <= 64);
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, why does write_single_element
even allow 128-bit EEW? If it's going to trigger an assertion, the function definition shouldn't permit a 128-bit EEW (Element Effective Width) in the first place. If that's the case, then we'll just have to perform two 64-bit reads.
val write_single_element : forall 'm 'x, 8 <= 'm <= 128. (int('m), int('x), vregidx, bits('m)) -> unit
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 point. It looks like some of the type signatures on these helpers are insufficiently precise.
6e7e764
to
86fbdeb
Compare
model/riscv_insts_zvkned.sail
Outdated
function zvk_check_elements(VLEN : int, num_elem : int, LMUL : int, SEW : int) -> bool = { | ||
((unsigned(vl)%num_elem) != 0) | ((unsigned(vstart)%num_elem) != 0) | (LMUL*VLEN) < (num_elem*SEW) | ||
} | ||
|
||
function zvk_check_encdec() -> bool = { | ||
let SEW = get_sew(); | ||
let LMUL_pow = get_lmul_pow(); | ||
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | ||
let num_elem = get_num_elem(LMUL_pow, SEW); | ||
|
||
zvk_check_elements(VLEN, num_elem, LMUL, SEW) | ||
} |
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 really like the idea of zvk_check_encdec
! We can use this for the other Zvk* extensions too!
Personally, I prefer something like:
function zvk_check_elements(VLEN : int, num_elem : int, LMUL : int, SEW : int) -> bool = { | |
((unsigned(vl)%num_elem) != 0) | ((unsigned(vstart)%num_elem) != 0) | (LMUL*VLEN) < (num_elem*SEW) | |
} | |
function zvk_check_encdec() -> bool = { | |
let SEW = get_sew(); | |
let LMUL_pow = get_lmul_pow(); | |
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | |
let num_elem = get_num_elem(LMUL_pow, SEW); | |
zvk_check_elements(VLEN, num_elem, LMUL, SEW) | |
} | |
function zvk_check_encdec() -> bool = { | |
let LMUL_pow = get_lmul_pow(); | |
(unsigned(vl) % 4 == 0) & (unsigned(vstart) % 4 == 0) | (2 ^ LMUL_pow * VLEN) >= 128) | |
} |
The spec sets EGW=128
and EGS=4
The spec also says that vl
and vstart
must be multiples of 4 (=EGS), not num_elem
. This means we could have vl
= 8 and num_elem
= 8, which is valid, but the current check (vl % num_elem != 0
) would incorrectly be false when it should be true.
Additionally, the code currently takes the exponent of the current LMUL
(get_lmul_pow()
) but ignores negative exponents (!). Right now, if you check get_lmul_pow()
, the condition (LMUL*VLEN) < (num_elem*SEW)
effectively does:
LMUL_pow * VLEN < (2 ^ LMUL_pow * VLEN / SEW) * SEW
which simplifies to LMUL_pow < (2 ^ LMUL_pow)
Which is always true (for now).
What we really want is
2 * get_lmul_pow() * VLEN >= 128
(I assume that sail can deal with negative exponents)
Edit: It would probable make even more sense to have something like
function zvk_check_encdec(EGW : int, EGS: int)
because EGW for vsha2c[hl].vv
varies and is EGW = 4 * SEW
model/riscv_insts_zvkned.sail
Outdated
let eg_len = (unsigned(vl) / num_elem); | ||
let eg_start = (unsigned(vstart) / num_elem); |
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.
Same here for EGS = 4:
let eg_len = (unsigned(vl) / num_elem); | |
let eg_start = (unsigned(vstart) / num_elem); | |
let eg_len = (unsigned(vl) / 4); | |
let eg_start = (unsigned(vstart) / 4; |
I ran into cases where vl
= 4 and vstart
= 0, but num_elem
= 8 (which is valid). However, with the old code, we would incorrectly skip the following loop because eg_len
would be 0, even though it should be 1.
model/riscv_insts_zvkned.sail
Outdated
val set_velem : forall 'n 'm 'p, 'n > 0 & 'm > 0 & 'p >= 0 & 4 * 'p + 3 < 'n . (vector('n, bits('m)), bits(4 * 'm), int('p)) -> vector('n, bits('m)) | ||
function set_velem(s, v, i) = { | ||
let m = length(v) / 4; | ||
[s with | ||
(4 * i) = v[m - 1 .. 0], | ||
(4 * i + 1) = v[2 * m - 1 .. m], | ||
(4 * i + 2) = v[3 * m - 1 .. 2 * m], | ||
(4 * i + 3) = v[4 * m - 1 .. 3 * m], | ||
] | ||
} |
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.
For #819, I added my own version of the set_velem
function, but I actually prefer yours! One suggestion: instead of returning s, how about we write directly to vd within the function and then call write_vreg? Since it's a setter method, it might make more sense to do it that way and we would follow the spec.
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.
However, there's a problem: this approach results in multiple calls to write_vreg
, subsequently leading to redundant calls to write_single_vreg
, making it less efficient.
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 you are right its not really efficient but Sail's primary focus is readability.
Currently, Sail does not provide a function to write n
continuous elements starting from a specific position in a given vreg. The available functions for writing to a vreg are:
write_vreg()
write_single_vreg()
write_single_element()
The implementation I have is:
/* Divide the input bitvector into 4 equal slices and store them in vd starting at position 4*i */
val set_velem : forall 'p 'n 'm, 8 <= 'n <= 64 & 'm > 0 & 'p >= 0. (vregidx, int('n), bits('m), int('p)) -> unit
function set_velem(vd, SEW, input, i) = {
foreach(j from 0 to 3)
write_single_element(SEW, 4 * i + j, vd, slice(input, j * SEW, SEW));
}
This function enables direct writing (setting) of multiple continuous elements to a vreg without the need to return the value vector and to store it at some pointer later via write_vreg()
. Additionally, it could be further generalized to allow writing n
continuous elements instead of just four and it follows more the spec.
It might be helpful to get feedback from others as well. @pmundkur @jordancarlin
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 can add function like write_element_group
?
model/riscv_insts_zvkned.sail
Outdated
function zvk_check_encdec(EGW : int, EGS : int) -> bool = { | ||
let LMUL_pow = get_lmul_pow(); | ||
let LMUL = if LMUL_pow < 0 then 0 else LMUL_pow; | ||
|
||
(unsigned(vl) % EGS == 0) & (unsigned(vstart) % EGS == 0) & (2 ^ LMUL * VLEN >= 128) | ||
} |
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 more or less agreed on the same function but you use
2 ^ LMUL * VLEN >= 128
instead of
2 ^ LMUL_pow * VLEN >= 128
This essentially suggests that LMUL = 0.5 (mf2), 0.25 (mf4), 0.125 (mf8) cannot be used with this extension, which is incorrect (I still assume that Sail can handle negative exponents).
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.
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 noticed that too while testing it with the OCaml backend and it did not work, I was surprised that it worked with the C backend. Thats why I initially assumed its supported somehow.
I propose that we go ahead and merge the function as it is for now. We can then either update it after this is merged and the remaining vector crypto extensions are in, or modify it immediately.
Personally, I think it makes more sense to keep the current version and follow up with a separate PR that explicitly changes the function.
Edit: Actually it does not matter if we change the function now or do it after all the remaining vector crypto extension are in, I am happy with both
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 okay with both too, though we should file an issue with the details to track this. Is this a hole in the vector test suite that doesn't trigger this?
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.
No, because the vector test suite only generates test cases for valid configurations.
If you started reviewing the code, it’s ready for another look. @KotorinMinami and I worked together, and the code now structurally matches the other Vector Cryptography Extensions. |
To support the implementation of Zvkned extension in SAIL, this creates the necessary infrastructure(i.e., a file to hold it, and the extension macro), preparing the tree for the Zvkned implementation. Signed-off-by: Charalampos Mitrodimas <[email protected]> Co-authored-by: KotorinMinami <[email protected]>
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 pretty clean! Some minor fixes suggested.
model/riscv_zvk_utils.sail
Outdated
@@ -21,7 +21,7 @@ function zvk_check_encdec(EGW: int, EGS: int) -> bool = (unsigned(vl) % EGS == 0 | |||
* ---------------------------------------------------------------------- | |||
*/ | |||
|
|||
enum zvkfunct6 = {ZVK_VSHA2CH, ZVK_VSHA2CL} | |||
enum zvkfunct6 = {ZVK_VAESDFVV, ZVK_VAESDFVS, ZVK_VAESDMVV, ZVK_VAESDMVS, ZVK_VAESEFVV, ZVK_VAESEFVS, ZVK_VAESEMVV, ZVK_VAESEMVS, ZVK_VSHA2CH, ZVK_VSHA2CL} |
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.
enum zvkfunct6 = {ZVK_VAESDFVV, ZVK_VAESDFVS, ZVK_VAESDMVV, ZVK_VAESDMVS, ZVK_VAESEFVV, ZVK_VAESEFVS, ZVK_VAESEMVV, ZVK_VAESEMVS, ZVK_VSHA2CH, ZVK_VSHA2CL} | |
enum zvkfunct6 = {ZVK_VAESDF_VV, ZVK_VAESDF_VS, ZVK_VAESDM_VV, ZVK_VAESDM_VS, ZVK_VAESEF_VV, ZVK_VAESEF_VS, ZVK_VAESEM_VV, ZVK_VAESEM_VS, ZVK_VSHA2CH, ZVK_VSHA2CL} |
This will make it a bit easier to read and is closer to the mnemonic where .
is replaced by _
. Their uses will need to be updated as well.
model/riscv_insts_zvkned.sail
Outdated
|
||
function clause currentlyEnabled(Ext_Zvkned) = hartSupports(Ext_Zvkned) & currentlyEnabled(Ext_V) | ||
|
||
union clause ast = ZVKVAESDFTYPE : (zvkfunct6, vregidx, vregidx) |
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.
union clause ast = ZVKVAESDFTYPE : (zvkfunct6, vregidx, vregidx) | |
union clause ast = VAESDF : (zvkfunct6, vregidx, vregidx) |
Elsewhere in the PR there are ast nodes like VAESKF1_VI
, VAESZ_VS
and similar, which are easier to parse; this will make it more consistent.
model/riscv_insts_zvkned.sail
Outdated
RETIRE_SUCCESS | ||
} | ||
|
||
mapping vaesdf_mnemonic : zvkfunct6 <-> string = { |
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 is a partial mapping, since there are more elements in zvkfunct6
than just these two. mapping
s should be complete, otherwise use scattered mapping clause
s.
In this case, since there are only two valid funct6
values for VAESDF
and similar nodes , it might be best to split the big zvkfunct6
enumeration into {_VV, _VS}
pairs for each ast node. This will also help make the above if .. else
safer.
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.
If I understand correctly, do you mean something like
enum zvk_vaesdf_funct6 = {ZVK_VAESDF_VV, ZVK_VAESDF_VS}
enum zvk_vaesdm_funct6 = {ZVK_VAESDM_VV, ZVK_VAESDM_VS}
enum zvk_vaesef_funct6 = {ZVK_VAESEF_VV, ZVK_VAESEF_VS}
enum zvk_vaesem_funct6 = {ZVK_VAESEM_VV, ZVK_VAESEM_VS}
?
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, exactly.
model/riscv_insts_zvkned.sail
Outdated
mapping clause assembly = ZVKVAESDFTYPE(funct6, vs2, vd) | ||
<-> vaesdf_mnemonic(funct6) ^ sep() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) | ||
|
||
union clause ast = ZVKVAESDMTYPE : (zvkfunct6, vregidx, vregidx) |
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.
union clause ast = ZVKVAESDMTYPE : (zvkfunct6, vregidx, vregidx) | |
union clause ast = VAESDM : (zvkfunct6, vregidx, vregidx) |
model/riscv_insts_zvkned.sail
Outdated
RETIRE_SUCCESS | ||
} | ||
|
||
mapping vaesdm_mnemonic : zvkfunct6 <-> string = { |
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.
See above; make this into one complete mapping for zvkfunct6
.
model/riscv_insts_zvkned.sail
Outdated
mapping clause assembly = ZVKVAESDMTYPE(funct6, vs2, vd) | ||
<-> vaesdm_mnemonic(funct6) ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) | ||
|
||
union clause ast = ZVKVAESEFTYPE : (zvkfunct6, vregidx, vregidx) |
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.
union clause ast = ZVKVAESEFTYPE : (zvkfunct6, vregidx, vregidx) | |
union clause ast = VAESEF : (zvkfunct6, vregidx, vregidx) |
model/riscv_insts_zvkned.sail
Outdated
assert(i * 4 + 3 < num_elem); | ||
|
||
let state = get_velem_quad(vd_val, i); | ||
let rkey = if funct6 == ZVK_VAESDFVV |
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 if ... else
is safer if there are only possible values for funct6
. See below.
model/riscv_insts_zvkned.sail
Outdated
mapping clause assembly = ZVKVAESEFTYPE(funct6, vs2, vd) | ||
<-> vaesef_mnemonic(funct6) ^ spc() ^ vreg_name(vd) ^ spc() ^ vreg_name(vs2) | ||
|
||
union clause ast = ZVKVAESEMTYPE : (zvkfunct6, vregidx, vregidx) |
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.
union clause ast = ZVKVAESEMTYPE : (zvkfunct6, vregidx, vregidx) | |
union clause ast = VAESEM : (zvkfunct6, vregidx, vregidx) |
model/riscv_insts_zvkned.sail
Outdated
RETIRE_SUCCESS | ||
} | ||
|
||
mapping vaesef_mnemonic : zvkfunct6 <-> string = { |
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.
Splitting up zvkfunct6
will help make this mapping complete; right now, it isn't.
I've already made the corresponding changes. Since the |
The match is clearer, no needed to change. |
@@ -112,6 +112,7 @@ For booting operating system images, see the information under the | |||
- Zvbc extension for vector carryless multiplication, v1.0 | |||
- Zvkb extension for vector cryptography bit-manipulation, v1.0 | |||
- Zvknha and Zvknhb extensions for vector cryptography NIST Suite: Vector SHA-2 Secure Hash, v1.0 | |||
- Zvkned extension for vector cryptography NIST Suite: Vector AES Block Cipher, v1.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.
Is there a reason why you put Zvkned after Zvknha ? In the spec Zvknh[ab] comes after Zvkned
config/default.json
Outdated
"Zvkned": { | ||
"supported": true | ||
}, |
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.
Same here, why is Zvkned in between Zvknha and Zvknhb?
model/riscv_zvk_utils.sail
Outdated
enum zvk_vaesef_funct6 = {ZVK_VAESEF_VV, ZVK_VAESEF_VS} | ||
enum zvk_vaesem_funct6 = {ZVK_VAESEM_VV, ZVK_VAESEM_VS} | ||
|
||
function aes_rotword(x : bits(32)) -> bits(32) = x[7.. 0] @ x[31..24] @ x[23..16] @ x[15.. 8] |
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.
In my opinion this function should be part of riscv_types_kext.sail
function aes_rotword(x : bits(32)) -> bits(32) = x[7.. 0] @ x[31..24] @ x[23..16] @ x[15.. 8]
Co-authored-by: KotorinMinami <[email protected]>
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!
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.
Nice!
Implements the Zvkned (NIST Suite: Vector AES Block Cipher) extension, as of version Release 1.0.0.
The following instructions are included:
All instructions were tested with VLEN=128 and results were compared with QEMU results of each instruction.
Note
This PR was originally developed by @charmitro , and now the Vector AES Block Cipher has been released.