diff --git a/cv32e40p/env/corev-dv/cv32e40p_instr_test_pkg.sv b/cv32e40p/env/corev-dv/cv32e40p_instr_test_pkg.sv index 023ee982b0..299bb1f8d2 100644 --- a/cv32e40p/env/corev-dv/cv32e40p_instr_test_pkg.sv +++ b/cv32e40p/env/corev-dv/cv32e40p_instr_test_pkg.sv @@ -103,6 +103,7 @@ package cv32e40p_instr_test_pkg; `include "instr_lib/cv32e40p_pulp_instr_lib.sv" `include "instr_lib/cv32e40p_pulp_hwloop_instr_lib.sv" `include "instr_lib/cv32e40p_float_instr_lib.sv" + `include "instr_lib/cv32e40p_instr_for_func_cvg_lib.sv" // directed streams to improve functional coverage holes in v2 // RISCV-DV class override definitions `include "cv32e40p_rand_instr_stream.sv" diff --git a/cv32e40p/env/corev-dv/instr_lib/cv32e40p_float_instr_lib.sv b/cv32e40p/env/corev-dv/instr_lib/cv32e40p_float_instr_lib.sv index 7c608cdc0f..f2fc246748 100644 --- a/cv32e40p/env/corev-dv/instr_lib/cv32e40p_float_instr_lib.sv +++ b/cv32e40p/env/corev-dv/instr_lib/cv32e40p_float_instr_lib.sv @@ -821,6 +821,15 @@ class cv32e40p_float_zfinx_base_instr_stream extends cv32e40p_base_instr_stream; end endfunction: insert_nop_instr + // add wfi + virtual function void insert_wfi_instr(); + riscv_instr wfi_instr = new riscv_instr::get_rand_instr( + .include_instr({WFI}) + ); + instr_list.push_back(wfi_instr); + instr_list[$].comment = {instr_list[$].comment, $sformatf(" [WFI Insertion] ")}; + endfunction: insert_wfi_instr + // for overriding direct instr operands with previous instruc rd/fd virtual function void f_use_prev_rd_on_next_operands( riscv_instr p_instr=null, diff --git a/cv32e40p/env/corev-dv/instr_lib/cv32e40p_instr_for_func_cvg_lib.sv b/cv32e40p/env/corev-dv/instr_lib/cv32e40p_instr_for_func_cvg_lib.sv new file mode 100644 index 0000000000..0c5b67e515 --- /dev/null +++ b/cv32e40p/env/corev-dv/instr_lib/cv32e40p_instr_for_func_cvg_lib.sv @@ -0,0 +1,183 @@ +/* + * Copyright 2023 Dolphin Design + * SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// [Dolphin Design updates] +// This file contains stream classes that use to generate streams that improve functional coverage holes + +// this stream is to improve func coverage for in uvme_interrupt_covg_v2 by cycle through all cv_* instructions multiple times for irq and wfi coverage purpose - START +class cv32e40p_cv_instrs_multi_loops_streams extends cv32e40p_float_zfinx_base_instr_stream; + + localparam TOTAL_INSTR_C_TYPE = 27; + localparam TOTAL_INSTR_X_TYPE = 304; + + bit include_wfi_insn = 0; + int unsigned insert_wfi_cnt = 0; + int unsigned loop_cnt = 0; + int unsigned total_instr = 0; + int unsigned loop_cnt_limit = 0; + int unsigned ignored_instr_cnt = 0; + + `uvm_object_utils(cv32e40p_cv_instrs_multi_loops_streams) + `uvm_object_new + + constraint ovr_c_others { + num_of_instr_per_stream == total_instr * loop_cnt_limit; + } + + // manipulate isns list that need to be covered in this stream + virtual function void init_rand_instr_entry(); + reset_rand_instr_entry(); + + include_group = new[1] ({RV32X}); + exclude_instr = new[9] ({CV_START, CV_STARTI, CV_END, CV_ENDI, CV_COUNT, CV_COUNTI, CV_SETUP, CV_SETUPI, CV_ELW}); // TBD: exclude hwloop and cluster insn from wfi cg + + // these already covered in all cvg, can be ignored meantime - Start (note: users can modify this to focus on insn list to b ecovered) + ignored_instr_cnt = 4; + exclude_instr = new[exclude_instr.size()+ignored_instr_cnt] ({exclude_instr, CV_MAX, CV_ADDN, CV_AVG_SCI_H, CV_SHUFFLEI3_SCI_B}); + // these already covered in all cvg, can be ignored meantime - End + + if (include_load_store_base_sp) begin // cover c_[s|l]wsp insn only + include_group = new[include_group.size()+1] ({include_group, RV32C}); + // these already covered in all cvg, can be ignored meantime - Start (note: users can modify this to focus on insn list to b ecovered) + exclude_instr = new[exclude_instr.size()+25] ({exclude_instr, C_LW, C_SW, C_ADDI4SPN, C_ADDI, C_LI, C_ADDI16SP, C_LUI, + C_SRLI, C_SRAI, C_ANDI, C_SUB, C_XOR, C_OR, C_AND, C_BEQZ, C_BNEZ, C_SLLI, C_MV, C_EBREAK, C_ADD, C_NOP, C_J, + C_JAL, C_JR, C_JALR}); + // these already covered in all cvg, can be ignored meantime - End + end + if (include_load_store_base_sp && !is_zfinx) begin // cover c_[fs|fl]wsp insn only + include_group = new[include_group.size()+1] ({include_group, RV32FC}); + exclude_instr = new[exclude_instr.size()+2] ({exclude_instr, C_FLW, C_FSW}); // these already covered in all cvg, can be ignored meantime + end + endfunction : init_rand_instr_entry + + virtual function void init_iteration_var(); + total_instr = 0; loop_cnt_limit = 0; + if (!include_wfi_insn) total_instr = 2; + else if (!include_load_store_base_sp) total_instr = TOTAL_INSTR_X_TYPE - exclude_instr.size(); + else if (include_load_store_base_sp && is_zfinx) total_instr = TOTAL_INSTR_X_TYPE + TOTAL_INSTR_C_TYPE - exclude_instr.size(); + else if (include_load_store_base_sp && !is_zfinx) total_instr = TOTAL_INSTR_X_TYPE + TOTAL_INSTR_C_TYPE + TOTAL_INSTR_FC_TYPE - exclude_instr.size(); + assert(total_instr > 0); + loop_cnt_limit = (include_wfi_insn) ? 1 : 3; + endfunction: init_iteration_var + + virtual function void update_current_instr_arg_list(int idx=0); + if (idx == 0) begin + loop_cnt++; assert (loop_cnt <= loop_cnt_limit); + end + else if (idx != 0 && idx%total_instr == 0) begin + loop_cnt++; assert (loop_cnt <= loop_cnt_limit); + init_rand_instr_entry(); // reinit for next loop + end + endfunction: update_current_instr_arg_list + + virtual function void update_next_instr_arg_list(riscv_instr prev_instr=null, int idx=0); + if (exclude_instr.size() > 0) begin + if (use_no_repetitive_instr_per_stream && prev_instr != null) begin + if (!(prev_instr.instr_name inside {exclude_instr})) + exclude_instr = new[exclude_instr.size()+1] ({exclude_instr, prev_instr.instr_name}); + // $display("exclude_instr size is %0d", exclude_instr.size()); + end + end + else assert(0); + endfunction: update_next_instr_arg_list + + function void pre_randomize(); + super.pre_randomize(); + use_fp_only_for_directed_instr = 0; + en_clr_fflags_af_instr = 0; + include_load_store_base_sp = 1; + use_no_repetitive_instr_per_stream = 1; // expanding exclude_instr per iteration + init_rand_instr_entry(); + init_iteration_var(); + endfunction: pre_randomize + + function void post_randomize(); + + riscv_instr instr; + riscv_fp_in_x_regs_instr instr_zfinx; + riscv_floating_point_instr instr_f; + + // print_stream_setting(); + for (int i = 0; i < num_of_instr_per_stream; i++) begin : GEN_N_MANIPULATE_INSTR + + if (include_wfi_insn) begin : INTERLEAVE_INSN_WITH_WFI + if (i == 0) begin + `SET_GPR_VALUE(gp_reg_scratch,32'h0000_0008) + // disable global mie + directed_csr_access(.instr_name(CSRRC), .rs1(gp_reg_scratch), .csr(12'h300)); + insert_wfi_cnt = $urandom_range(4, 12); + insert_wfi_instr(); insert_wfi_cnt--; + end + else if (i == num_of_instr_per_stream-1) begin + // enable global mie - flush all pending interrupts + directed_csr_access(.instr_name(CSRRS), .rs1(gp_reg_scratch), .csr(12'h300)); + insert_nop_instr(1); + end + else if (insert_wfi_cnt == 0) begin + // enable global mie - flush all pending interrupts + directed_csr_access(.instr_name(CSRRS), .rs1(gp_reg_scratch), .csr(12'h300)); + insert_nop_instr(1); + // disable global mie + directed_csr_access(.instr_name(CSRRC), .rs1(gp_reg_scratch), .csr(12'h300)); + insert_wfi_cnt = $urandom_range(4, 12); + insert_wfi_instr(); insert_wfi_cnt--; + end + else begin + insert_wfi_instr(); insert_wfi_cnt--; + end + end + else begin + /* do nothing */ + end + + update_current_instr_arg_list(i); + instr = new riscv_instr::get_rand_instr( + .include_instr(include_instr), + .exclude_instr(exclude_instr), + .include_category(include_category), + .exclude_category(exclude_category), + .include_group(include_group), + .exclude_group(exclude_group) + ); + update_next_instr_arg_list(instr, i); + + assert(instr.group inside {RV32C, RV32FC, RV32X}); // these are the intended groups in this stream + randomize_gpr(instr); + if (instr.instr_name inside {`STORE_INSTR_LIST, `FP_STORE_INSTR_LIST}) + store_instr_gpr_handling(instr); + + instr.comment = $sformatf(" Inserted %0s - idx[%0d]", get_name(), i); + instr_list.push_back(instr); + end // num_of_instr_per_stream + + endfunction: post_randomize + +endclass: cv32e40p_cv_instrs_multi_loops_streams + +class cv32e40p_cv_instrs_w_wfi_multi_loops_streams extends cv32e40p_cv_instrs_multi_loops_streams; + + `uvm_object_utils(cv32e40p_cv_instrs_w_wfi_multi_loops_streams) + `uvm_object_new + + function void pre_randomize(); + include_wfi_insn = 1; + super.pre_randomize(); + endfunction: pre_randomize + +endclass: cv32e40p_cv_instrs_w_wfi_multi_loops_streams +// this stream is to improve func coverage for in uvme_interrupt_covg_v2 by cycle through all cv_* instructions multiple times for irq and wfi coverage purpose - END + diff --git a/cv32e40p/regress/cv32e40pv2_for_func_cvg_improvement.yaml b/cv32e40p/regress/cv32e40pv2_for_func_cvg_improvement.yaml new file mode 100644 index 0000000000..005d6a84f6 --- /dev/null +++ b/cv32e40p/regress/cv32e40pv2_for_func_cvg_improvement.yaml @@ -0,0 +1,29 @@ +# Copyright 2023 Dolphin Design +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# Header +name: cv32e40pv2_for_func_cvg_improvement +description: regression for CV32E40Pv2, focused on improving the functional coverage holes + +# List of builds +# cfg is set to pulp by default but can be overriden by arg command to any cfg. +builds: + clean_fw: + cmd: make clean-bsp clean_test_programs + dir: cv32e40p/sim/uvmt + clean_corev-dv: + cmd: make clean_riscv-dv clone_riscv-dv + dir: cv32e40p/sim/uvmt + uvmt_cv32e40p: + cmd: make comp comp_corev-dv + dir: cv32e40p/sim/uvmt + cfg: pulp + +# List of tests +tests: + corev_directed_for_interrupt_covg_test: + build: uvmt_cv32e40p + description: This test is to improve func coverage holes in uvme_interrupt_covg_v2 + dir: cv32e40p/sim/uvmt + cmd: make gen_corev-dv test COREV=YES TEST=corev_directed_for_interrupt_covg_test CFG_PLUSARGS="+UVM_TIMEOUT=30000000" + num: 5 diff --git a/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/.gitignore b/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/.gitignore new file mode 100644 index 0000000000..0bf802f9a3 --- /dev/null +++ b/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/.gitignore @@ -0,0 +1 @@ +corev_*.* diff --git a/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/corev-dv.yaml b/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/corev-dv.yaml new file mode 100644 index 0000000000..9f3c259592 --- /dev/null +++ b/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/corev-dv.yaml @@ -0,0 +1,21 @@ +name: corev_directed_for_interrupt_covg_test +uvm_test: $(CV_CORE_LC)_instr_base_test +description: > + This test is to improve func coverage holes in uvme_interrupt_covg_v2 +plusargs: > + +instr_cnt=1000 + +num_of_sub_program=0 + +directed_instr_0=cv32e40p_cv_instrs_w_wfi_multi_loops_streams,1 + +directed_instr_1=cv32e40p_cv_instrs_multi_loops_streams,3000 + +enable_interrupt=1 + +enable_fast_interrupt_handler=1 + +no_fence=0 + +no_branch_jump=1 + +boot_mode=m + +no_csr_instr=0 + +no_wfi=1 + +no_dret=1 + +fix_sp=1 + +randomize_csr=1 + +test_override_riscv_instr_stream=1 + +test_override_riscv_instr_sequence=1 diff --git a/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/test.yaml b/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/test.yaml new file mode 100644 index 0000000000..3e522b8492 --- /dev/null +++ b/cv32e40p/tests/programs/corev-dv/corev_directed_for_interrupt_covg_test/test.yaml @@ -0,0 +1,10 @@ +# Copyright 2023 Dolphin Design +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 + +# Test definition YAML for random pulp instr test +name: corev_directed_for_interrupt_covg_test +uvm_test: uvmt_$(CV_CORE_LC)_firmware_test_c +description: > + This test is to improve func coverage holes in uvme_interrupt_covg_v2 +plusargs: > + +gen_irq_noise