Skip to content

Commit c7f157b

Browse files
nadime15charmitropmundkur
committed
Add support for Zvksed extension
Co-authored-by: Charalampos Mitrodimas <[email protected]> Co-authored-by: Prashanth Mundkur <[email protected]>
1 parent 1d4c2b4 commit c7f157b

7 files changed

+203
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ Supported RISC-V ISA features
119119
- Zvbb extension for vector basic bit-manipulation, v1.0
120120
- Zvbc extension for vector carryless multiplication, v1.0
121121
- Zvkb extension for vector cryptography bit-manipulation, v1.0
122+
- Zvksed extension for vector cryptography ShangMi Suite: SM4 Block Cipher, v1.0
122123
- Machine, Supervisor, and User modes
123124
- Smcntrpmf extension for cycle and instret privilege mode filtering, v1.0
124125
- Sscofpmf extension for Count Overflow and Mode-Based Filtering, v1.0

config/default.json

+3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@
7474
"Zvbc" : {
7575
"supported" : true
7676
},
77+
"Zvksed" : {
78+
"supported" : true
79+
},
7780
"Sstc" : {
7881
"supported" : false
7982
}

model/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ foreach (xlen IN ITEMS 32 64)
8888
"riscv_insts_zicboz.sail"
8989
"riscv_insts_zvbb.sail"
9090
"riscv_insts_zvbc.sail"
91+
"riscv_insts_zvksed.sail"
9192
# Zimop and Zcmop should be at the end so they can be overridden by earlier extensions
9293
"riscv_insts_zimop.sail"
9394
"riscv_insts_zcmop.sail"
@@ -180,6 +181,7 @@ foreach (xlen IN ITEMS 32 64)
180181
${sail_vm_srcs}
181182
# Shared/common code for the cryptography extension.
182183
"riscv_types_kext.sail"
184+
"riscv_zvk_utils.sail"
183185
)
184186

185187
if (variant STREQUAL "rvfi")

model/riscv_extensions.sail

+3
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ function clause hartSupports(Ext_Zvkb) = config extensions.Zvkb.supported
137137
// Vector Carryless Multiplication
138138
enum clause extension = Ext_Zvbc
139139
function clause hartSupports(Ext_Zvbc) = config extensions.Zvbc.supported
140+
// ShangMi Suite: SM4 Block Cipher
141+
enum clause extension = Ext_Zvksed
142+
function clause hartSupports(Ext_Zvksed) = config extensions.Zvksed.supported
140143

141144
// Count Overflow and Mode-Based Filtering
142145
enum clause extension = Ext_Sscofpmf

model/riscv_insts_vext_utils.sail

+10
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,16 @@ function get_scalar(rs1, SEW) = {
172172
}
173173
}
174174

175+
val get_velem_quad_vec : forall 'n 'm 'p, 'n > 0 & 8 <= 'm <= 64 & 'p >= 0 & 4 * 'p + 3 < 'n. (vector('n, bits('m)), int('p)) -> vector(4, bits('m))
176+
function get_velem_quad_vec(v, i) = [ v[4 * i + 3], v[4 * i + 2], v[4 * i + 1], v[4 * i] ]
177+
178+
179+
val write_velem_quad_vec : forall 'p 'n, 8 <= 'n <= 64 & 'p >= 0. (vregidx, int('n), vector(4, bits('n)), int('p)) -> unit
180+
function write_velem_quad_vec(vd, SEW, input, i) = {
181+
foreach(j from 0 to 3)
182+
write_single_element(SEW, 4 * i + j, vd, input[j]);
183+
}
184+
175185
/* Get the starting element index from csr vtype */
176186
val get_start_element : unit -> nat
177187
function get_start_element() = {

model/riscv_insts_zvksed.sail

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*=======================================================================================*/
2+
/* This Sail RISC-V architecture model, comprising all files and */
3+
/* directories except where otherwise noted is subject the BSD */
4+
/* two-clause license in the LICENSE file. */
5+
/* */
6+
/* SPDX-License-Identifier: BSD-2-Clause */
7+
/*=======================================================================================*/
8+
9+
function clause currentlyEnabled(Ext_Zvksed) = hartSupports(Ext_Zvksed) & currentlyEnabled(Ext_V)
10+
11+
union clause ast = VSM4K_VI : (vregidx, bits(5), vregidx)
12+
13+
mapping clause encdec = VSM4K_VI(vs2, uimm, vd)
14+
<-> 0b1000011 @ encdec_vreg(vs2) @ uimm @ 0b010 @ encdec_vreg(vd) @ 0b1110111
15+
when currentlyEnabled(Ext_Zvksed) & get_sew() == 32 & zvk_check_encdec(128, 4)
16+
17+
mapping clause assembly = VSM4K_VI(vs2, uimm, vd)
18+
<-> "vsm4k.vi" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ hex_bits_5(uimm)
19+
20+
function clause execute (VSM4K_VI(vs2, uimm, vd)) = {
21+
let SEW = get_sew();
22+
let LMUL_pow = get_lmul_pow();
23+
let num_elem = get_num_elem(LMUL_pow, SEW);
24+
25+
assert(SEW == 32);
26+
27+
let vs2_val = read_vreg(num_elem, SEW, LMUL_pow, vs2);
28+
29+
let rnd = unsigned(uimm[2..0]);
30+
31+
let eg_len = (unsigned(vl) / 4);
32+
let eg_start = (unsigned(vstart) / 4);
33+
34+
foreach (i from eg_start to (eg_len - 1)) {
35+
assert(i * 4 + 3 < num_elem);
36+
37+
let rk_in : vector(4, bits(32)) = get_velem_quad_vec(vs2_val, i);
38+
var rk_out : vector(4, bits(32)) = vector_init(zeros());
39+
40+
var B = rk_in[1] ^ rk_in[2] ^ rk_in[3] ^ zvksed_sm4_sbox(4 * rnd);
41+
var S = sm4_subword(B);
42+
rk_out[0] = round_key(rk_in[0], S);
43+
44+
B = rk_in[2] ^ rk_in[3] ^ rk_out[0] ^ zvksed_sm4_sbox(4 * rnd + 1);
45+
S = sm4_subword(B);
46+
rk_out[1] = round_key(rk_in[1], S);
47+
48+
B = rk_in[3] ^ rk_out[0] ^ rk_out[1] ^ zvksed_sm4_sbox(4 * rnd + 2);
49+
S = sm4_subword(B);
50+
rk_out[2] = round_key(rk_in[2], S);
51+
52+
B = rk_out[0] ^ rk_out[1] ^ rk_out[2] ^ zvksed_sm4_sbox(4 * rnd + 3);
53+
S = sm4_subword(B);
54+
rk_out[3] = round_key(rk_in[3], S);
55+
56+
write_velem_quad_vec(vd, SEW, rk_out, i);
57+
};
58+
59+
set_vstart(zeros());
60+
RETIRE_SUCCESS
61+
}
62+
63+
union clause ast = ZVKSM4RTYPE : (zvkfunct6, vregidx, vregidx)
64+
65+
mapping clause encdec = ZVKSM4RTYPE(ZVK_VSM4RVV, vs2, vd)
66+
<-> 0b1010001 @ encdec_vreg(vs2) @ 0b10000 @ 0b010 @ encdec_vreg(vd) @ 0b1110111
67+
when currentlyEnabled(Ext_Zvksed) & get_sew() == 32 & zvk_check_encdec(128, 4)
68+
69+
mapping clause encdec = ZVKSM4RTYPE(ZVK_VSM4RVS, vs2, vd)
70+
<-> 0b1010011 @ encdec_vreg(vs2) @ 0b10000 @ 0b010 @ encdec_vreg(vd) @ 0b1110111
71+
when currentlyEnabled(Ext_Zvksed) & get_sew() == 32 & zvk_check_encdec(128, 4) & zvk_valid_reg_overlap(vs2, vd, get_lmul_pow())
72+
73+
mapping vsm4r_mnemonic : zvkfunct6 <-> string = {
74+
ZVK_VSM4RVV <-> "vsm4r.vv",
75+
ZVK_VSM4RVS <-> "vsm4r.vs",
76+
}
77+
78+
mapping clause assembly = ZVKSM4RTYPE(funct6, vs2, vd)
79+
<-> vsm4r_mnemonic(funct6) ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2)
80+
81+
function clause execute (ZVKSM4RTYPE(funct6, vs2, vd)) = {
82+
let SEW = get_sew();
83+
let LMUL_pow = get_lmul_pow();
84+
let num_elem = get_num_elem(LMUL_pow, SEW);
85+
86+
assert(SEW == 32);
87+
88+
let vs2_val = read_vreg(num_elem, SEW, LMUL_pow, vs2);
89+
let vd_val = read_vreg(num_elem, SEW, LMUL_pow, vd);
90+
91+
let eg_len = (unsigned(vl) / 4);
92+
let eg_start = (unsigned(vstart) / 4);
93+
94+
foreach (i from eg_start to (eg_len - 1)) {
95+
assert(i * 4 + 3 < num_elem);
96+
97+
let rk_in : vector(4, bits(32)) = if funct6 == ZVK_VSM4RVV
98+
then get_velem_quad_vec(vs2_val, i)
99+
else get_velem_quad_vec(vs2_val, 0);
100+
101+
let x_in : vector(4, bits(32)) = get_velem_quad_vec(vd_val, i);
102+
var x_out : vector(4, bits(32)) = vector_init(zeros());
103+
104+
var B = x_in[1] ^ x_in[2] ^ x_in[3] ^ rk_in[0];
105+
var S = sm4_subword(B);
106+
x_out[0] = sm4_round(x_in[0], S);
107+
108+
B = x_in[2] ^ x_in[3] ^ x_out[0] ^ rk_in[1];
109+
S = sm4_subword(B);
110+
x_out[1] = sm4_round(x_in[1], S);
111+
112+
B = x_in[3] ^ x_out[0] ^ x_out[1] ^ rk_in[2];
113+
S = sm4_subword(B);
114+
x_out[2] = sm4_round(x_in[2], S);
115+
116+
B = x_out[0] ^ x_out[1] ^ x_out[2] ^ rk_in[3];
117+
S = sm4_subword(B);
118+
x_out[3] = sm4_round(x_in[3], S);
119+
120+
write_velem_quad_vec(vd, SEW, x_out, i);
121+
};
122+
123+
set_vstart(zeros());
124+
RETIRE_SUCCESS
125+
}

model/riscv_zvk_utils.sail

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
/*=======================================================================================*/
3+
/* This Sail RISC-V architecture model, comprising all files and */
4+
/* directories except where otherwise noted is subject the BSD */
5+
/* two-clause license in the LICENSE file. */
6+
/* */
7+
/* SPDX-License-Identifier: BSD-2-Clause */
8+
/*=======================================================================================*/
9+
10+
val zvk_valid_reg_overlap : (vregidx, vregidx, int) -> bool
11+
function zvk_valid_reg_overlap(rs, rd, emul_pow) = {
12+
let reg_group_size = if emul_pow > 0 then 2 ^ emul_pow else 1;
13+
let rs_int = unsigned(vregidx_bits(rs));
14+
let rd_int = unsigned(vregidx_bits(rd));
15+
(rs_int + reg_group_size <= rd_int) | (rd_int + reg_group_size <= rs_int)
16+
}
17+
18+
function zvk_check_encdec(EGW: int, EGS: int) -> bool = (unsigned(vl) % EGS == 0) & (unsigned(vstart) % EGS == 0) & (2 ^ get_lmul_pow() * VLEN) >= EGW
19+
20+
/*
21+
* Utility functions for Zvksed
22+
* ----------------------------------------------------------------------
23+
*/
24+
25+
enum zvkfunct6 = {ZVK_VSM4RVV, ZVK_VSM4RVS}
26+
27+
val round_key : (bits(32), bits(32)) -> bits(32)
28+
function round_key(X, S) = X ^ (S ^ (S <<< 13) ^ (S <<< 23))
29+
30+
val sm4_round : (bits(32), bits(32)) -> bits(32)
31+
function sm4_round(X, S) = X ^ (S ^ (S <<< 2) ^ (S <<< 10) ^ (S <<< 18) ^ (S <<< 24))
32+
33+
// SM4 Constant Key (CK)
34+
let zvksed_ck : vector(32, bits(32)) = [
35+
0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269,
36+
0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9,
37+
0xE0E7EEF5, 0xFC030A11, 0x181F262D, 0x343B4249,
38+
0x50575E65, 0x6C737A81, 0x888F969D, 0xA4ABB2B9,
39+
0xC0C7CED5, 0xDCE3EAF1, 0xF8FF060D, 0x141B2229,
40+
0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9299,
41+
0xA0A7AEB5, 0xBCC3CAD1, 0xD8DFE6ED, 0xF4FB0209,
42+
0x10171E25, 0x2C333A41, 0x484F565D, 0x646B7279
43+
]
44+
45+
val zvksed_box_lookup : (bits(5), vector(32, bits(32))) -> bits(32)
46+
function zvksed_box_lookup(x, table) = {
47+
table[31 - unsigned(x)]
48+
}
49+
50+
val zvksed_sm4_sbox : (int) -> bits(32)
51+
function zvksed_sm4_sbox(x) = zvksed_box_lookup(to_bits(5, x), zvksed_ck)
52+
53+
val sm4_subword : bits(32) -> bits(32)
54+
function sm4_subword(x) = {
55+
sm4_sbox(x[31..24]) @
56+
sm4_sbox(x[23..16]) @
57+
sm4_sbox(x[15.. 8]) @
58+
sm4_sbox(x[ 7.. 0])
59+
}

0 commit comments

Comments
 (0)