Skip to content

Commit

Permalink
Zbkx implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
munailwaqar committed Dec 20, 2024
1 parent b4a037d commit f8f03f4
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 5 deletions.
14 changes: 11 additions & 3 deletions core/alu.sv
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ module alu
logic [CVA6Cfg.XLEN-1:0] brev8_reversed;
logic [ 31:0] unzip_gen;
logic [ 31:0] zip_gen;
logic [CVA6Cfg.XLEN-1:0] xperm8_result;
logic [CVA6Cfg.XLEN-1:0] xperm4_result;
// bit reverse operand_a for left shifts and bit counting
generate
genvar k;
Expand Down Expand Up @@ -268,14 +270,18 @@ module alu

// ZKN gen block
if (CVA6Cfg.ZKN && CVA6Cfg.RVB) begin : zkn_gen_block
genvar i, m, n;
// Generate brev8_reversed by reversing bits within each byte
for (i = 0; i < (CVA6Cfg.XLEN / 8); i++) begin : brev8_gen
genvar i, m, n, q;
for (i = 0; i < (CVA6Cfg.XLEN / 8); i++) begin : brev8_xperm8_gen
assign xperm8_result[i << 3 +: 8] = (fu_data_i.operand_b[i << 3 +: 8] < (CVA6Cfg.XLEN / 8)) ? fu_data_i.operand_a[fu_data_i.operand_b[i << 3 +: 8] << 3 +: 8] : 8'b0;
// Generate brev8_reversed by reversing bits within each byte
for (m = 0; m < 8; m++) begin : reverse_bits
// Reversing the order of bits within a single byte
assign brev8_reversed[(i<<3)+m] = fu_data_i.operand_a[(i<<3)+(7-m)];
end
end
for (q = 0; q < (CVA6Cfg.XLEN / 4); q++) begin : xperm4_gen
assign xperm4_result[q << 2 +: 4] = (fu_data_i.operand_b[q << 2 +: 4] < (CVA6Cfg.XLEN / 4)) ? fu_data_i.operand_a[{2'b0, fu_data_i.operand_b[q << 2 +: 4]} << 2 +: 4] : 4'b0;
end
// Generate zip and unzip results
if (CVA6Cfg.IS_XLEN32) begin
for (n = 0; n < 16; n++) begin : zip_unzip_gen
Expand Down Expand Up @@ -392,6 +398,8 @@ module alu
PACK_H:
result_o = (CVA6Cfg.IS_XLEN32) ? ({16'b0, fu_data_i.operand_b[7:0], fu_data_i.operand_a[7:0]}) : ({48'b0, fu_data_i.operand_b[7:0], fu_data_i.operand_a[7:0]});
BREV8: result_o = brev8_reversed;
XPERM8: result_o = xperm8_result;
XPERM4: result_o = xperm4_result;
default: ;
endcase
if (fu_data_i.operation == PACK_W && CVA6Cfg.IS_XLEN64)
Expand Down
2 changes: 2 additions & 0 deletions core/decoder.sv
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,8 @@ module decoder
if (CVA6Cfg.ZKN) instruction_o.op = ariane_pkg::PACK_H; //packh
else illegal_instr_bm = 1'b1;
end
{7'b001_0100, 3'b100} : if (CVA6Cfg.ZKN) instruction_o.op = ariane_pkg::XPERM8; else illegal_instr_bm = 1'b1; // xperm8
{7'b001_0100, 3'b010} : if (CVA6Cfg.ZKN) instruction_o.op = ariane_pkg::XPERM4; else illegal_instr_bm = 1'b1; // xperm4
// Zero Extend Op RV32 encoding
{
7'b000_0100, 3'b100
Expand Down
5 changes: 4 additions & 1 deletion core/include/ariane_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,10 @@ package ariane_pkg;
BREV8,
// Zip instructions
UNZIP,
ZIP
ZIP,
// Xperm instructions
XPERM8,
XPERM4
} fu_op;

function automatic logic op_is_branch(input fu_op op);
Expand Down
86 changes: 86 additions & 0 deletions docs/01_cva6_user/RISCV_Instructions_RvZbkx.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
..
Copyright (c) 2023 OpenHW Group
Copyright (c) 2023 10xEngineers
SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1

.. Level 1
=======
Level 2
-------
Level 3
~~~~~~~
Level 4
^^^^^^^
.. _cva6_riscv_instructions_RV32Zbkx:

*Applicability of this chapter to configurations:*

.. csv-table::
:widths: auto
:align: left
:header: "Configuration", "Implementation"

"CV32A60AX", "Implemented extension"
"CV64A6_MMU", "Implemented extension"

=============================
RVZbkx: Crossbar permutation instructions
=============================

The following instructions comprise the Zbkx extension:

Xperm instructions
--------------------
The xperm instructions perform permutation operations on a register. They use indices extracted from rs2 to select data chunks (bytes for xperm8 or nibbles for xperm4) from rs1. The selected data is then placed into the destination register (rd) at positions corresponding to the extracted indices in rs2. If an index in rs2 is out of range, the corresponding chunk in rd is set to 0.

+-----------+-----------+-----------------------+
| RV32 | RV64 | Mnemonic |
+===========+===========+=======================+
||| xperm8 rd, rs1, rs2 |
+-----------+-----------+-----------------------+
||| xperm4 rd, rs1, rs2 |
+-----------+-----------+-----------------------+


RV32 and RV64 Instructions
~~~~~~~~~~~~~~~~~~~~~~~~~~


- **XPERM8**: Crossbar permutation (bytes)

**Format**: xperm8 rd, rs1, rs2

**Description**: The xperm8 instruction operates on bytes. The rs1 register contains a vector of XLEN/8 8-bit elements. The rs2 register contains a vector of XLEN/8 8-bit indexes. The result is each element in rs2 replaced by the indexed element in rs1, or zero if the index into rs2 is out of bounds.

**Pseudocode**: foreach (i from 0 to xlen by 8) {
if (rs2[i*8+:8]<(xlen/8))
X(rd)[i*8+:8] = rs1[rs2[i*8+:8]*8+:8];
else
X(rd)[i*8+:8] = 8'b0;
}

**Invalid values**: NONE

**Exception raised**: NONE

- **XPERM4**: Crossbar permutation (nibbles)

**Format**: xperm4 rd, rs1, rs2

**Description**: The xperm4 instruction operates on nibbles. The rs1 register contains a vector of XLEN/4 4-bit elements. The rs2 register contains a vector of XLEN/4 4-bit indexes. The result is each element in rs2 replaced by the indexed element in rs1, or zero if the index into rs2 is out of bounds.

**Pseudocode**: foreach (i from 0 to xlen by 4) {
if (rs2[i*4+:4]<(xlen/4))
X(rd)[i*4+:4] = rs1[rs2[i*4+:4]*4+:4];
else
X(rd)[i*4+:4] = 4'b0;
}

**Invalid values**: NONE

**Exception raised**: NONE
2 changes: 1 addition & 1 deletion verif/sim/cva6.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,7 @@ def load_config(args, cwd):
args.isa = "rv64gc_zba_zbb_zbs_zbc"
elif base in ("cv64a6_imafdc_sv39", "cv64a6_imafdc_sv39_hpdcache"):
args.mabi = "lp64d"
args.isa = "rv64gc_zba_zbb_zbs_zbc_zbkb"
args.isa = "rv64gc_zba_zbb_zbs_zbc_zbkb_zbkx"
elif base == "cv32a60x":
args.mabi = "ilp32"
args.isa = "rv32imc_zba_zbb_zbs_zbc"
Expand Down
10 changes: 10 additions & 0 deletions verif/tests/testlist_riscv-arch-test-cv64a6_imafdc_sv39.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -987,3 +987,13 @@ testlist:
<<: *common_test_config
iterations: 1
asm_tests: <path_var>/riscv-arch-test/riscv-test-suite/rv64i_m/K/src/brev8-01.S

- test: rv64i_m-xperm8-01
iterations: 1
<<: *common_test_config
asm_tests: <path_var>/riscv-arch-test/riscv-test-suite/rv64i_m/K/src/xperm8-01.S

- test: rv64i_m-xperm4-01
iterations: 1
<<: *common_test_config
asm_tests: <path_var>/riscv-arch-test/riscv-test-suite/rv64i_m/K/src/xperm4-01.S

0 comments on commit f8f03f4

Please sign in to comment.