Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CVA6-DV : Add Zcmp extension instructions to CORE-DV #1648

Merged
merged 1 commit into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ([email protected])
// ------------------------------------------------------------------------------ //

`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 ([email protected])
// ------------------------------------------------------------------------------ //

`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;
Loading