Skip to content

Commit

Permalink
CVA6-DV : Add Zcmp extension instructions to CORE-DV (#1648)
Browse files Browse the repository at this point in the history
  • Loading branch information
AyoubJalali authored Nov 22, 2023
1 parent 30cf669 commit ef4971f
Show file tree
Hide file tree
Showing 6 changed files with 261 additions and 0 deletions.
8 changes: 8 additions & 0 deletions verif/env/corev-dv/custom/riscv_custom_instr_enum.sv
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,11 @@ C_ZEXT_H,
C_SEXT_H,
C_ZEXT_W,
C_NOT,

//Zcmp extension
CM_PUSH,
CM_POP,
CM_POPRET,
CM_POPRETZ,
CM_MVA01S,
CM_MVSA01,
226 changes: 226 additions & 0 deletions verif/env/corev-dv/custom/riscv_zcmp_instr.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// Copyright 2023 Thales DIS
// Copyright 2023 OpenHW Group
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
// ------------------------------------------------------------------------------ //

`ifndef __RISCV_ZCMP_INSTR_SV__
`define __RISCV_ZCMP_INSTR_SV__

/**
* This class describe Zcmp extension.
*/
class riscv_zcmp_instr_c extends riscv_instr;

`uvm_object_utils(riscv_zcmp_instr_c)

rand int stack_adj;

riscv_reg_t reg_list;
rand bit [3:0] rlist;

bit has_reglist = 1'b1;

function new(string name = "");
super.new(name);
rs1 = S0;
rs2 = S1;
is_compressed = 1'b1;
endfunction : new

constraint rvc_rx_c {
// Registers specified by the three-bit rs1’, rs2’, and rd’
if (instr_name inside {CM_MVA01S, CM_MVSA01}) {
if (has_rs1) {
rs1 inside {[S0:A5]};
}
if (has_rs2) {
rs2 inside {[S0:A5]};
}
if (has_rd) {
rd inside {[S0:A5]};
}
}
}

constraint reg_list_c {
if (instr_name inside {CM_PUSH, CM_POP, CM_POPRET, CM_POPRETZ}) {
// Set the stack_adj depends on the rlist field
if (rlist inside {[4:7]}) {
stack_adj == 16 + imm[5:4] * 16;
}
if (rlist inside {[8:11]}) {
stack_adj == 32 + imm[5:4] * 16;
}
if (rlist inside {[12:14]}) {
stack_adj == 48 + imm[5:4] * 16;
}
if (rlist == 15) {
stack_adj == 64 + imm[5:4] * 16;
}
}
if (instr_name inside {CM_MVA01S, CM_MVSA01}) {
// rs1 & rs2 should be a S-register & different
rs1 != rs2;
rs1 inside {S0, S1, [S2:S7]};
rs2 inside {S0, S1, [S2:S7]};
}
}

constraint zcmp_rlist_c {
// Constraint register number & imm field
if (instr_name inside {CM_PUSH, CM_POP, CM_POPRET, CM_POPRETZ}) {
!(rlist inside {[0:3]});
imm[31:6] == 0;
imm[3:0] == 0;
}
}

virtual function void set_imm_len();
if (instr_name inside {CM_PUSH, CM_POP, CM_POPRET, CM_POPRETZ}) begin
imm_len = 2;
end
endfunction : set_imm_len

// Convert the instruction to assembly code
virtual function string convert2asm(string prefix = "");
string asm_str;
asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN);
if (has_reglist) begin
if (rlist == 4) begin
case (instr_name)
CM_PUSH: asm_str = $sformatf("%0s{%0s}, %0d", asm_str, all_gpr[1].name(), -stack_adj);
CM_POP: asm_str = $sformatf("%0s{%0s}, %0d", asm_str, all_gpr[1].name(), stack_adj);
CM_POPRET: asm_str = $sformatf("%0s{%0s}, %0d", asm_str, all_gpr[1].name(), stack_adj);
CM_POPRETZ: asm_str = $sformatf("%0s{%0s}, %0d", asm_str, all_gpr[1].name(), stack_adj);
endcase
end
if (rlist == 5) begin
case (instr_name)
CM_PUSH: asm_str = $sformatf("%0s{%0s, %0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), -stack_adj);
CM_POP: asm_str = $sformatf("%0s{%0s, %0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), stack_adj);
CM_POPRET: asm_str = $sformatf("%0s{%0s, %0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), stack_adj);
CM_POPRETZ: asm_str = $sformatf("%0s{%0s, %0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), stack_adj);
endcase
end
if (rlist == 6) begin
case (instr_name)
CM_PUSH: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[9].name(), -stack_adj);
CM_POP: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[9].name(), stack_adj);
CM_POPRET: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[9].name(), stack_adj);
CM_POPRETZ: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[9].name(), stack_adj);
endcase
end
if (rlist > 6 && rlist != 15) begin
case (instr_name)
CM_PUSH: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[rlist+11].name(), -stack_adj);
CM_POP: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[rlist+11].name(), stack_adj);
CM_POPRET: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[rlist+11].name(), stack_adj);
CM_POPRETZ: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[rlist+11].name(), stack_adj);
endcase
end
if (rlist == 15) begin
case (instr_name)
CM_PUSH: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[27].name(), -stack_adj);
CM_POP: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[27].name(), stack_adj);
CM_POPRET: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[27].name(), stack_adj);
CM_POPRETZ: asm_str = $sformatf("%0s{%0s, %0s-%0s}, %0d", asm_str, all_gpr[1].name(), all_gpr[8].name(), all_gpr[27].name(), stack_adj);
endcase
end
end
else begin
case (instr_name)
CM_MVA01S: asm_str = $sformatf("%0s%0s, %0s", asm_str, rs1.name(), rs2.name());
CM_MVSA01: asm_str = $sformatf("%0s%0s, %0s", asm_str, rs1.name(), rs2.name());
endcase
end
return asm_str.tolower();
endfunction : convert2asm

// Convert the instruction to assembly code
virtual function string convert2bin(string prefix = "");
string binary;
case (instr_name) inside
CM_PUSH:
binary = $sformatf("0x%4h", {get_func6(), get_func2(), rlist, imm[5:4], get_c_opcode()});
CM_POP:
binary = $sformatf("0x%4h", {get_func6(), get_func2(), rlist, imm[5:4], get_c_opcode()});
CM_POPRET:
binary = $sformatf("0x%4h", {get_func6(), get_func2(), rlist, imm[5:4], get_c_opcode()});
CM_POPRETZ:
binary = $sformatf("0x%4h", {get_func6(), get_func2(), rlist, imm[5:4], get_c_opcode()});
CM_MVA01S:
binary = $sformatf("0x%4h", {get_func6(), rs1, 2'b11, rs2, get_c_opcode()});
CM_MVSA01:
binary = $sformatf("0x%4h", {get_func6(), rs1, 2'b01, rs2, get_c_opcode()});
default : `uvm_fatal(`gfn, $sformatf("Unsupported instruction %0s", instr_name.name()))
endcase
return {prefix, binary};
endfunction : convert2bin

virtual function bit [1:0] get_c_opcode();
case (instr_name) inside
CM_PUSH, CM_POP,
CM_POPRET, CM_POPRETZ,
CM_MVA01S, CM_MVSA01 : get_c_opcode = 2'b10;
endcase
endfunction

virtual function bit [5:0] get_func6();
case (instr_name) inside
CM_PUSH, CM_POP : get_func6 = 6'b101110;
CM_POPRET, CM_POPRETZ : get_func6 = 6'b101111;
CM_MVA01S, CM_MVSA01 : get_func6 = 6'b101011;
endcase
endfunction

virtual function bit [1:0] get_func2();
case (instr_name) inside
CM_POP, CM_POPRET : get_func2 = 2'b10;
CM_PUSH, CM_POPRETZ : get_func2 = 2'b00;
endcase
endfunction

virtual function void set_rand_mode();
case (instr_name) inside
CM_PUSH, CM_POP,
CM_POPRET, CM_POPRETZ : begin
has_rd = 1'b0;
has_rs1 = 1'b0;
has_rs2 = 1'b0;
end
CM_MVA01S, CM_MVSA01 : begin
has_rd = 1'b0;
has_imm = 1'b0;
has_reglist = 1'b0;
end
endcase
endfunction

function void pre_randomize();
rd.rand_mode(has_rd);
rs1.rand_mode(has_rs1);
rs2.rand_mode(has_rs2);
imm.rand_mode(has_imm);
rlist.rand_mode(has_reglist);
endfunction

virtual function bit is_supported(riscv_instr_gen_config cfg);
cva6_instr_gen_config_c cfg_cva6;
`DV_CHECK_FATAL($cast(cfg_cva6, cfg), "Could not cast cfg into cfg_cva6")
return cfg_cva6.enable_zcmp_extension && (
instr_name inside {
CM_PUSH, CM_POP,
CM_POPRET, CM_POPRETZ,
CM_MVA01S, CM_MVSA01
});
endfunction

endclass

`endif // __RISCV_ZCMP_INSTR_SV__
17 changes: 17 additions & 0 deletions verif/env/corev-dv/custom/rv32zcmp_instr.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2023 Thales DIS
// Copyright 2022 OpenHW Group
//
// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
// You may obtain a copy of the License at https://solderpad.org/licenses/
//
// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com)
// ------------------------------------------------------------------------------ //

`DEFINE_ZCMP_INSTR(CM_PUSH, R_FORMAT, ARITHMETIC, RV32X)
`DEFINE_ZCMP_INSTR(CM_POP, R_FORMAT, ARITHMETIC, RV32X)
`DEFINE_ZCMP_INSTR(CM_POPRET, R_FORMAT, ARITHMETIC, RV32X)
`DEFINE_ZCMP_INSTR(CM_POPRETZ, R_FORMAT, ARITHMETIC, RV32X)
`DEFINE_ZCMP_INSTR(CM_MVA01S, R_FORMAT, LOGICAL, RV32X)
`DEFINE_ZCMP_INSTR(CM_MVSA01, R_FORMAT, LOGICAL, RV32X)
5 changes: 5 additions & 0 deletions verif/env/corev-dv/cva6_defines.svh
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@
`define DEFINE_ZCB_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
class riscv_``instr_n``_instr extends riscv_zcb_instr_c; \
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)

// Zcmp extension instruction
`define DEFINE_ZCMP_INSTR(instr_n, instr_format, instr_category, instr_group, imm_tp = IMM) \
class riscv_``instr_n``_instr extends riscv_zcmp_instr_c; \
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
3 changes: 3 additions & 0 deletions verif/env/corev-dv/cva6_instr_gen_config.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class cva6_instr_gen_config_c extends riscv_instr_gen_config;
bit enable_same_reg;
bit enable_zicond_extension;
bit enable_zcb_extension;
bit enable_zcmp_extension;
int unsupported_instr_ratio;

constraint hazard_reg_c {
Expand All @@ -48,6 +49,7 @@ class cva6_instr_gen_config_c extends riscv_instr_gen_config;
`uvm_field_int(enable_same_reg, UVM_DEFAULT)
`uvm_field_int(enable_zicond_extension, UVM_DEFAULT)
`uvm_field_int(enable_zcb_extension, UVM_DEFAULT)
`uvm_field_int(enable_zcmp_extension, UVM_DEFAULT)
`uvm_field_int(unsupported_instr_ratio, UVM_DEFAULT)
`uvm_object_utils_end

Expand All @@ -59,6 +61,7 @@ class cva6_instr_gen_config_c extends riscv_instr_gen_config;
get_bool_arg_value("+enable_same_reg=", enable_same_reg);
get_bool_arg_value("+enable_zicond_extension=", enable_zicond_extension);
get_bool_arg_value("+enable_zcb_extension=", enable_zcb_extension);
get_bool_arg_value("+enable_zcmp_extension=", enable_zcmp_extension);
get_int_arg_value("+unsupported_instr_ratio=", unsupported_instr_ratio);
endfunction

Expand Down
2 changes: 2 additions & 0 deletions verif/env/corev-dv/cva6_instr_test_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ package cva6_instr_test_pkg;
`include "cvxif_custom_instr.sv"
`include "riscv_zicond_instr.sv"
`include "riscv_zcb_instr.sv"
`include "riscv_zcmp_instr.sv"
`include "rv32x_instr.sv"
`include "rv32zicond_instr.sv"
`include "rv32zcb_instr.sv"
`include "rv32zcmp_instr.sv"
`include "rv64zcb_instr.sv"

endpackage : cva6_instr_test_pkg;

0 comments on commit ef4971f

Please sign in to comment.