Repository: riscv/sail-riscv
Pull request #550: Add zvbc extension
Author: login: rez5427
Labels: name: will be merged
description: Scheduled to be merged soon if nobody objects
name: extension
description: Adds support for a RISC-V extension
Created: 2024-09-15T21:17:29Z | Merged: 2025-03-31T16:00:30Z



Diff:
diff --git a/README.md b/README.md
index 5aed55638b..3af40d5f84 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,7 @@ Supported RISC-V ISA features
 - Zkr extension for entropy source, v1.0
 - V extension for vector operations, v1.0
 - Zvbb extension for vector basic bit-manipulation, v1.0
+- Zvbc extension for vector carryless multiplication, v1.0
 - Zvkb extension for vector cryptography bit-manipulation, v1.0
 - Machine, Supervisor, and User modes
 - Smcntrpmf extension for cycle and instret privilege mode filtering, v1.0
diff --git a/model/CMakeLists.txt b/model/CMakeLists.txt
index 4fb889c026..cc12b1581f 100644
--- a/model/CMakeLists.txt
+++ b/model/CMakeLists.txt
@@ -79,6 +79,7 @@ foreach (xlen IN ITEMS 32 64)
                 "riscv_insts_zicbom.sail"
                 "riscv_insts_zicboz.sail"
                 "riscv_insts_zvbb.sail"
+                "riscv_insts_zvbc.sail"
                 # Zimop and Zcmop should be at the end so they can be overridden by earlier extensions
                 "riscv_insts_zimop.sail"
                 "riscv_insts_zcmop.sail"
diff --git a/model/riscv_extensions.sail b/model/riscv_extensions.sail
index 8d3f39b3e5..e3bfb275f9 100644
--- a/model/riscv_extensions.sail
+++ b/model/riscv_extensions.sail
@@ -111,6 +111,8 @@ enum clause extension = Ext_Zhinx
 enum clause extension = Ext_Zvbb
 // Vector Cryptography Bit-manipulation
 enum clause extension = Ext_Zvkb
+// Vector Carryless Multiplication
+enum clause extension = Ext_Zvbc
 
 // Count Overflow and Mode-Based Filtering
 enum clause extension = Ext_Sscofpmf
diff --git a/model/riscv_insts_zvbc.sail b/model/riscv_insts_zvbc.sail
new file mode 100644
index 0000000000..48201e24d9
--- /dev/null
+++ b/model/riscv_insts_zvbc.sail
@@ -0,0 +1,151 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+
+  let 'n = get_num_elem(LMUL_pow, SEW);
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask('n, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result('n, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to ('n - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg('n, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+
+  let 'n = get_num_elem(LMUL_pow, SEW);
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask('n, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result('n, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to ('n - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
+    };
+  };
+  write_vreg('n, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> "vclmulh.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+
+  let 'n = get_num_elem(LMUL_pow, SEW);
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask('n, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result('n, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to ('n - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 1 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] >> (SEW - n));
+    };
+  };
+  write_vreg('n, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMULH_VX (vm, vs2, rs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VX (vm, vs2, rs1, vd)
+  <-> "vclmulh.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+
+  let 'n = get_num_elem(LMUL_pow, SEW);
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask('n, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg('n, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result('n, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to ('n - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 1 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val >> (SEW - n));
+    };
+  };
+  write_vreg('n, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
diff --git a/model/riscv_sys_regs.sail b/model/riscv_sys_regs.sail
index 0f4eec438b..11ce9bf228 100644
--- a/model/riscv_sys_regs.sail
+++ b/model/riscv_sys_regs.sail
@@ -121,6 +121,8 @@ val sys_enable_zicboz = pure "sys_enable_zicboz" : unit -> bool
 // Is the Zvkb extension supported.
 val sys_enable_zvkb = pure "sys_enable_zvkb" : unit -> bool
 
+// Is the Zvbc extension supported.
+function sys_enable_zvbc() -> bool = true
 // Is the Sstc stimecmp extension supported.
 val sys_enable_sstc = pure "sys_enable_sstc" : unit -> bool
 


Reviews:
user: login: jordancarlin
body: I haven't compared this with the spec yet, but here are some initial comments on the Sail syntax. The extension also needs to be added to the list in the README.
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-22T07:20:32Z
user: login: jordancarlin
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-22T07:21:34Z
user: login: rez5427
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-22T07:35:41Z
user: login: jordancarlin
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-22T07:47:26Z
user: login: nadime15
body: Okay, I verified the implementation against the vector test suite, and all tests passed successfully.

Besides the formatting, there is just one thing to change for now.

From the spec:
 > These instructions are only defined for SEW=64.

You could add an assert to check for this.

I just noticed that Crypto Vector extensions have dependencies on Zve32x and Zve64x (which are not implemented yet).
In the case of Zvbc, it's Zve64x, but we can ignore this for now.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-24T09:06:32Z
user: login: nadime15
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-24T11:23:49Z
user: login: jordancarlin
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-25T13:48:21Z
user: login: nadime15
body: Almost done!
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-25T14:09:10Z
user: login: pmundkur
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-25T14:17:02Z
user: login: jordancarlin
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-25T14:26:29Z
user: login: nadime15
body: Awesome, looks good!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-25T15:11:05Z
user: login: jordancarlin
body: LGTM now!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-25T21:43:36Z
user: login: pmundkur
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-26T21:36:53Z
user: login: nadime15
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T21:46:07Z
user: login: jordancarlin
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-26T22:58:28Z
user: login: rez5427
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T10:08:59Z
user: login: nadime15
body: Make sure to remove all code related to the switch from the .cpp and .h files.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T11:43:53Z
user: login: jordancarlin
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-27T12:18:44Z
user: login: jordancarlin
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-27T12:23:23Z
user: login: pmundkur
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-28T12:22:00Z
user: login: Timmmm
body: Some minor comments, otherwise LGTM.
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-28T13:40:07Z
user: login: Timmmm
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-31T14:39:08Z
user: login: Timmmm
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-31T14:39:58Z
user: login: Timmmm
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-31T14:41:18Z
user: login: Timmmm
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-31T15:08:41Z
user: login: jordancarlin
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-31T15:25:38Z

Review comments:
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: Move the extension enum clause to `riscv_extensions.sail`.
created_at: 2025-03-20T18:22:18Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
+  0b0 <-> "0",
+  0b1 <-> "1"
+}
+
+union clause ast = VCLMUL_VV : (bits(1), regidx, regidx, regidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd) if extensionEnabled(Ext_Zvbc)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111 if extensionEnabled(Ext_Zvbc)
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ sep() ^ vm_name(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  var mask    : vector('n, dec, bool)     = undefined;
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, 0b00000);
+  let vd_val  : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+      write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+    };
+};
+  vstart = zeros();
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), regidx, regidx, regidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd) if extensionEnabled(Ext_Zvbc)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111 if extensionEnabled(Ext_Zvbc)
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: This can be simplified to the following with Sail 0.19 (we are in the process of changing it everywhere else):
```
mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
  when extensionEnabled(Ext_Zvbc)
```
created_at: 2025-03-22T06:56:00Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: I think you should be able to use the existing `maybe_vmask` function instead of defining this new one. This one also doesn't match the assembly from the isa manual.
created_at: 2025-03-22T07:13:47Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
+  0b0 <-> "0",
+  0b1 <-> "1"
+}
+
+union clause ast = VCLMUL_VV : (bits(1), regidx, regidx, regidx)
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: These should use `vregidx` for vector register arguments instead of `regidx`.
created_at: 2025-03-22T07:15:36Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
+  0b0 <-> "0",
+  0b1 <-> "1"
+}
+
+union clause ast = VCLMUL_VV : (bits(1), regidx, regidx, regidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd) if extensionEnabled(Ext_Zvbc)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111 if extensionEnabled(Ext_Zvbc)
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ sep() ^ vm_name(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  var mask    : vector('n, dec, bool)     = undefined;
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: I don't think this line is necessary. It should be sufficient to define mask with the let statement below.
created_at: 2025-03-22T07:17:42Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
+  0b0 <-> "0",
+  0b1 <-> "1"
+}
+
+union clause ast = VCLMUL_VV : (bits(1), regidx, regidx, regidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd) if extensionEnabled(Ext_Zvbc)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111 if extensionEnabled(Ext_Zvbc)
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ sep() ^ vm_name(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  var mask    : vector('n, dec, bool)     = undefined;
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, 0b00000);
+  let vd_val  : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: ```suggestion
  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
```

Sail no longer supports different ordering for individual vectors, so this is unnecessary. This change needs to be made for all of the vectors declared in this file.
created_at: 2025-03-22T07:18:55Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
+  0b0 <-> "0",
+  0b1 <-> "1"
+}
+
+union clause ast = VCLMUL_VV : (bits(1), regidx, regidx, regidx)
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: This one is also why CI is failing.
created_at: 2025-03-22T07:21:33Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
+  0b0 <-> "0",
+  0b1 <-> "1"
+}
+
+union clause ast = VCLMUL_VV : (bits(1), regidx, regidx, regidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd) if extensionEnabled(Ext_Zvbc)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111 if extensionEnabled(Ext_Zvbc)
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ sep() ^ vm_name(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  var mask    : vector('n, dec, bool)     = undefined;
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, 0b00000);
+  let vd_val  : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let vs1_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, dec, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+      write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+    };
+};
+  vstart = zeros();
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), regidx, regidx, regidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd) if extensionEnabled(Ext_Zvbc)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111 if extensionEnabled(Ext_Zvbc)
path: model/riscv_insts_zvbc.sail
user: login: rez5427
body: thanks for noticing
created_at: 2025-03-22T07:35:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -113,6 +113,7 @@ Supported RISC-V ISA features
 - V extension for vector operations, v1.0
 - Zvbb extension for vector basic bit-manipulation, v1.0
 - Zvkb extension for vector cryptography bit-manipulation, v1.0
+- Zvbc extension for vector carryless multiplication, v1.0
path: README.md
user: login: jordancarlin
body: Move this up after Zvbb before Zvkb (and the same in riscv_extensions.sail)
created_at: 2025-03-22T07:44:14Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,163 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+enum clause extension = Ext_Zvbc
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: You should be able to delete this function now that you're no longer using it.
created_at: 2025-03-22T07:44:41Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,158 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = true
+
+mapping vm_name : bits(1) <-> string = {
+  0b0 <-> "0",
+  0b1 <-> "1"
+}
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111 when extensionEnabled(Ext_Zvbc)
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, 0b00000);
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: ```suggestion
  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
```
created_at: 2025-03-22T07:45:48Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,153 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = true
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111 when extensionEnabled(Ext_Zvbc)
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+      write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+    };
+};
+  vstart = zeros();
+  RETIRE_SUCCESS
path: model/riscv_insts_zvbc.sail
user: login: nadime15
body: ```suggestion
  foreach (i from 0 to (num_elem - 1)) {
    if mask[i] == bitone then {
      foreach (n from 0 to (SEW - 1))
        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
    };
  };
  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
  vstart = zeros();
  RETIRE_SUCCESS
```
created_at: 2025-03-24T08:54:54Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = true
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111 when extensionEnabled(Ext_Zvbc)
path: model/riscv_insts_zvbc.sail
user: login: nadime15
body: ```suggestion
mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
  when extensionEnabled(Ext_Zvbc)
```

See #809 
created_at: 2025-03-24T11:23:20Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = true
path: model/riscv_insts_zvbc.sail
user: login: nadime15
body: Either we remove the switch to enable Zvbc or we change it to: 
```suggestion
function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc()
```
Zvbb is also activated by default and does not have a switch. In my opinion, we could remove the switch for Zvbc (`sys_enable_zvbc()`) and keep it set to true.

created_at: 2025-03-24T11:23:24Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc()
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  vstart = zeros();
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: ```suggestion
  set_vstart(zeros());
```

This ensures V context is dirtied at the end of the instruction. See #816.
created_at: 2025-03-25T13:48:13Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc()
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m)                  = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
+      write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+    };
+  };
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
path: model/riscv_insts_zvbc.sail
user: login: nadime15
body: ```suggestion
  foreach (i from 0 to (num_elem - 1)) {
    if mask[i] == bitone then {
      foreach (n from 0 to (SEW - 1))
        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
    };
  };
  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
  set_vstart(zeros());
  RETIRE_SUCCESS
}
```

Please do this for each instruction.
created_at: 2025-03-25T14:05:58Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc()
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m)                  = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
+      write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+    };
+  };
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> "vclmulh.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VV(vm, vs2, vs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] >> (SEW - n));
+      write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+    };
+  };
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMULH_VX (vm, vs2, rs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VX (vm, vs2, rs1, vd)
+  <-> "vclmulh.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VX(vm, vs2, rs1, vd)) = {
+  let SEW                     = get_sew();
+  let LMUL_pow                = get_lmul_pow();
+  let num_elem                = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n)                  = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m)                  = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
path: model/riscv_insts_zvbc.sail
user: login: nadime15
body: Please fix the formatting for each function as well.
created_at: 2025-03-25T14:06:42Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc()
path: model/riscv_insts_zvbc.sail
user: login: nadime15
body: Would it actually make sense for all crypto vector extension to check if the Vector Extension is enabled? I would say so.

@pmundkur, @jordancarlin 
created_at: 2025-03-25T14:08:24Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc()
path: model/riscv_insts_zvbc.sail
user: login: pmundkur
body: Makes sense to me.
created_at: 2025-03-25T14:17:02Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,157 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc()
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: From the spec:
> The Zvknhb and Zvbc Vector Crypto Extensions --and accordingly the composite extensions Zvkn, Zvknc, Zvkng, and Zvksc -- require a Zve64x base, or application ("V") base Vector Extension.
> 
> All of the other Vector Crypto Extensions can be built on any embedded (Zve*) or application ("V") base Vector Extension.

Right now we only have the `V` extension in the model. We need to go through and fix support for all of the other `Zve*` vector extensions (we have the bulk of the code for all of them already, we just need to fix what is enabled when). #785 does a little bit of this. For now, it seems reasonable to have this require `V`, but we'll need to refactor all of the vector extensionEnabled logic soon, so I don't think it's a big deal. 
created_at: 2025-03-25T14:26:29Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
path: model/riscv_insts_zvbc.sail
user: login: nadime15
body: Just one last question, do we want to keep this switch here? I think we could remove it.
@pmundkur, @jordancarlin 
```suggestion
function clause extensionEnabled(Ext_Zvbc) = extensionEnabled(Ext_V)
```
created_at: 2025-03-26T21:46:02Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: I’d say with #758 almost ready to merge, we should avoid adding new command line switches that will be replaced by configuration flags. Either keep `sys_enable_zvbc()` but hardcode it to true or drop it entirely for now. 
created_at: 2025-03-26T22:58:27Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
path: model/riscv_insts_zvbc.sail
user: login: rez5427
body: should I remove all `sys_enable_zvbc` related code? or is ok for now@jordancarlin @nadime15 
created_at: 2025-03-27T10:08:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -121,6 +121,9 @@ val sys_enable_zicboz = pure "sys_enable_zicboz" : unit -> bool
 // Is the Zvkb extension supported.
 val sys_enable_zvkb = pure "sys_enable_zvkb" : unit -> bool
 
+// Is the Zvbc extension supported.
+val sys_enable_zvbc = pure "sys_enable_zvbc" : unit -> bool
+
path: model/riscv_sys_regs.sail
user: login: nadime15
body: I think what you could do is: 
```suggestion
// Is the Zvbc extension supported.
function sys_enable_zvbc -> bool = true
```
created_at: 2025-03-27T11:41:18Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() | extensionEnabled(Ext_V)
path: model/riscv_insts_zvbc.sail
user: login: jordancarlin
body: ```suggestion
function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
```
created_at: 2025-03-27T12:17:16Z
author_association: COLLABORATOR
diff_hunk: @@ -144,6 +145,7 @@ static struct option options[] = {
     {"enable-zicbom",               no_argument,       0, OPT_ENABLE_ZICBOM       },
     {"enable-zicboz",               no_argument,       0, OPT_ENABLE_ZICBOZ       },
     {"enable-zvkb",                 no_argument,       0, OPT_ENABLE_ZVKB         },
+    {"enable-zvbc",                 no_argument,       0, OPT_ENABLE_ZVBC         },
path: c_emulator/riscv_sim.cpp
user: login: jordancarlin
body: All of the changes in this file should be removed.
created_at: 2025-03-27T12:17:58Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> "vclmulh.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
path: model/riscv_insts_zvbc.sail
user: login: Timmmm
body: This should be `from 1 to`. Technically doesn't make a difference since 0 will always result in `result[i] = result[i] ^ 0` but they used 1 in the original pseudocode so it probably makes sense here too.

Ditto for line 148.
created_at: 2025-03-28T13:35:51Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> "vclmulh.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
path: model/riscv_insts_zvbc.sail
user: login: Timmmm
body: Maybe just delete these and the explicit type annotations? Or if we keep the type annotations then don't have two variables for the same thing. You can do

```
let 'n = get_num_elem(...
```
created_at: 2025-03-28T13:37:15Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
path: model/riscv_insts_zvbc.sail
user: login: Timmmm
body: I feel like it would make sense to extract this into `clmul[h]` functions like in the original psuedocode. Easier to test and then it can also be shared with the scalar code.

We could maybe do that in a future PR though.
created_at: 2025-03-28T13:39:32Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
path: model/riscv_insts_zvbc.sail
user: login: Timmmm
body: Will do this in a future PR so the scalar code can use it too.
created_at: 2025-03-31T14:39:08Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> "vclmulh.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
path: model/riscv_insts_zvbc.sail
user: login: Timmmm
body: Apparently all the other vector code is in this style too so leave it for now and we can update them all at once.
created_at: 2025-03-31T14:39:58Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,155 @@
+/*=======================================================================================*/
+/*  This Sail RISC-V architecture model, comprising all files and                        */
+/*  directories except where otherwise noted is subject the BSD                          */
+/*  two-clause license in the LICENSE file.                                              */
+/*                                                                                       */
+/*  SPDX-License-Identifier: BSD-2-Clause                                                */
+/*=======================================================================================*/
+
+function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
+
+union clause ast = VCLMUL_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VV (vm, vs2, vs1, vd)
+  <-> "vclmul.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (vs1_val[i] << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMUL_VX : (bits(1), vregidx, regidx, vregidx)
+
+mapping clause encdec = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> 0b001100 @ vm @ encdec_vreg(vs2) @ encdec_reg(rs1) @ 0b110 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMUL_VX (vm, vs2, rs1, vd)
+  <-> "vclmul.vx" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ reg_name(rs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMUL_VX(vm, vs2, rs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+
+  let rs1_val : bits('m) = get_scalar(rs1, SEW);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
+        if vs2_val[i][n] == bitone then result[i] = result[i] ^ (rs1_val << n);
+    };
+  };
+  write_vreg(num_elem, SEW, LMUL_pow, vd, result);
+  set_vstart(zeros());
+  RETIRE_SUCCESS
+}
+
+union clause ast = VCLMULH_VV : (bits(1), vregidx, vregidx, vregidx)
+
+mapping clause encdec = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> 0b001101 @ vm @ encdec_vreg(vs2) @ encdec_vreg(vs1) @ 0b010 @ encdec_vreg(vd) @ 0b1010111
+  when extensionEnabled(Ext_Zvbc) & get_sew() == 64
+
+mapping clause assembly = VCLMULH_VV (vm, vs2, vs1, vd)
+  <-> "vclmulh.vv" ^ spc() ^ vreg_name(vd) ^ sep() ^ vreg_name(vs2) ^ sep() ^ vreg_name(vs1) ^ maybe_vmask(vm)
+
+function clause execute (VCLMULH_VV(vm, vs2, vs1, vd)) = {
+  let SEW       = get_sew();
+  let LMUL_pow  = get_lmul_pow();
+  let num_elem  = get_num_elem(LMUL_pow, SEW);
+
+  let 'n = num_elem;
+  let 'm = SEW;
+
+  let vm_val  : bits('n) = read_vmask(num_elem, vm, zvreg);
+  let vd_val  : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vd);
+  let vs1_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs1);
+  let vs2_val : vector('n, bits('m)) = read_vreg(num_elem, SEW, LMUL_pow, vs2);
+
+  let (initial_result, mask) = init_masked_result(num_elem, SEW, LMUL_pow, vd_val, vm_val);
+  var result = initial_result;
+
+  foreach (i from 0 to (num_elem - 1)) {
+    if mask[i] == bitone then {
+      foreach (n from 0 to (SEW - 1))
path: model/riscv_insts_zvbc.sail
user: login: Timmmm
body: Just discussed this in the meeting; good to go after this is done.
created_at: 2025-03-31T14:41:18Z
author_association: COLLABORATOR

PR comments:
user: login: github-actions[bot]
created_at: 2024-09-15T21:40:41Z
body: ## Test Results
398 tests  ±0   398 ✅ ±0   1m 19s ⏱️ ±0s
  1 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit b765c2ff. ± Comparison against base commit e7821d6c.

[test-results]:data:application/gzip;base64,H4sIAIa66mcC/13MyQ6CMBSF4VchXbvoYCdfxpTSJjcCNR1WxHe3IKPL7z/JmZCH3iX0aMitQalA3tGVaDKEsVLq6rrkeWNabXqmYu1/esG7JrwHb6C/BBdjiGuJZTw+Z1wvf+V4XHw6XHz+s2EYIFegVgpuqfeGYcU7TY0kHFOqtCD67hxvBVMKG4Y+X7z+at4EAQAA

:recycle: This comment has been updated with latest results.
author_association: NONE
user: login: jrtc27
created_at: 2024-09-15T22:31:50Z
body: Why did you close https://github.com/riscv/sail-riscv/pull/549? Please don't create new PRs when the existing one can be updated just fine...
author_association: COLLABORATOR
user: login: rez5427
created_at: 2024-09-16T07:21:44Z
body: > Why did you close #549? Please don't create new PRs when the existing one can be updated just fine...

Sorry...
author_association: CONTRIBUTOR
user: login: rez5427
created_at: 2024-09-16T10:29:47Z
body: I followed the instructions from the [riscv-vector-tests](https://github.com/chipsalliance/riscv-vector-tests) repository and used the nightly version of the riscv-gnu-toolchain to generate code with the ZVBC extension. I ran six tests from the riscv-vector-tests, all of which successfully passed.
![test](https://github.com/user-attachments/assets/c9ac0766-be45-423a-8f21-1e4d5cb575d1)

author_association: CONTRIBUTOR
user: login: nadime15
created_at: 2025-03-18T22:46:37Z
body: Hi @rez5427, your PR looks nearly complete. Would you like to rebase your code? Once that’s done, we can review it again. 
author_association: COLLABORATOR
user: login: rez5427
created_at: 2025-03-18T22:57:28Z
body: > Hi @rez5427, your PR looks nearly complete. Would you like to rebase your code? Once that’s done, we can review it again. 

Sure) I'll finish it in 2 days
author_association: CONTRIBUTOR
user: login: rez5427
created_at: 2025-03-22T07:45:06Z
body: I should install sail 0.19
author_association: CONTRIBUTOR
user: login: rez5427
created_at: 2025-03-24T10:41:26Z
body: @nadime15 maybe like this? `assert(SEW == 64, "Only SEW=64 supported for zvbc");`
author_association: CONTRIBUTOR
user: login: jordancarlin
created_at: 2025-03-24T12:40:56Z
body: > @nadime15 maybe like this? `assert(SEW == 64, "Only SEW=64 supported for zvbc");`

It looks like right now this assertion is reachable because there is nothing in the model stopping you from executing this instruction with a different SEW. We want to avoid reachable assertions because they cause the model to stop if they fail.

Since the instruction is only defined for SEW = 64, it would be better to encode this directly in the `encdec` clause so the instruction is not even decoded if SEW is not 64. Something like `when extensionEnabled(Ext_Zvbc) & get_sew() == 64`.
author_association: COLLABORATOR
user: login: rez5427
created_at: 2025-03-25T14:25:39Z
body: @nadime15 @jrtc27 maybe this is ok
author_association: CONTRIBUTOR
user: login: nibrunie
created_at: 2025-03-29T16:52:43Z
body: > Okay, I verified the implementation against the vector test suite, and all tests passed successfully.
> 
> Besides the formatting, there is just one thing to change for now.
> 
> From the spec:
> 
> > These instructions are only defined for SEW=64.
> 
> You could add an assert to check for this.
> 
> I just noticed that Crypto Vector extensions have dependencies on Zve32x and Zve64x (which are not implemented yet). In the case of Zvbc, it's Zve64x, but we can ignore this for now.

Shouldn't a comment be added in the code, maybe around
```
function clause extensionEnabled(Ext_Zvbc) = sys_enable_zvbc() & extensionEnabled(Ext_V)
```
to highlight that this will need to be fixed once `Ext_Zve*` are declared to make sure the proper dependency is checked here ?

author_association: NONE
user: login: Timmmm
created_at: 2025-03-31T15:09:28Z
body: Ah looks like there's a small conflict that needs to be resolved...
author_association: COLLABORATOR