mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 13:07:46 -04:00
Update google_riscv-dv to google/riscv-dv@ace2805
Update code from upstream repository https://github.com/google/riscv- dv to revision ace2805b63100f46c3dcd02b4fcf6a7184582110 * Fix vector instruction randomization (google/riscv-dv#560) (taoliug) * Change generate_instr_stream to a virtual function (google/riscv- dv#559) (taoliug) * fix bug with compressed ebreak generation (google/riscv-dv#557) (udinator) * update PMP exception handlers to 'fix' config CSRs (google/riscv- dv#546) (udinator) * Add bitmanip doc (google/riscv-dv#555) (weicaiyang) * specify physical pmp addresses from cmdline (Udi Jonnalagadda) * Fix branch hit coverage issue (google/riscv-dv#551) (taoliug) * B extension coverage part2 (google/riscv-dv#548) (weicaiyang) * B extension coverage part1 (google/riscv-dv#542) (weicaiyang) * Fix typo in riscv_instr_test_lib (google/riscv-dv#545) (ANIL SHARMA) * Add target rv64imcb (google/riscv-dv#543) (weicaiyang) Signed-off-by: Udi <udij@google.com>
This commit is contained in:
parent
b72d263eac
commit
e1ec5b63f8
19 changed files with 1321 additions and 94 deletions
2
vendor/google_riscv-dv.lock.hjson
vendored
2
vendor/google_riscv-dv.lock.hjson
vendored
|
@ -9,6 +9,6 @@
|
|||
upstream:
|
||||
{
|
||||
url: https://github.com/google/riscv-dv
|
||||
rev: 42264b7782a10848935e995063c212893820e561
|
||||
rev: ace2805b63100f46c3dcd02b4fcf6a7184582110
|
||||
}
|
||||
}
|
||||
|
|
82
vendor/google_riscv-dv/docs/source/extension_support.rst
vendored
Normal file
82
vendor/google_riscv-dv/docs/source/extension_support.rst
vendored
Normal file
|
@ -0,0 +1,82 @@
|
|||
Extension Support
|
||||
=================
|
||||
|
||||
Bit Manipulation Extension
|
||||
--------------------------------------------------------
|
||||
Setup RISCV-GCC compiler toolchain and ISS simulator
|
||||
--------------------------------------------------------
|
||||
|
||||
1. Install `riscv-gcc`_ toolchain
|
||||
|
||||
- Download the repo and add " --enable-commitlog" at the end of line 6 in
|
||||
`build_file`_ as it's not enabled by default
|
||||
- Follow the `steps`_ to install GCC and spike
|
||||
|
||||
2. Update environment variable RISCV_GCC to the RISC-V gcc executable
|
||||
executable. (example: <install_dir>/bin/riscv64-unknown-elf-gcc)
|
||||
3. Update environment variable RISCV_OBJCOPY to RISC-V objcopy executable
|
||||
executable. (example: <install_dir>/bin/riscv64-unknown-elf-objcopy)
|
||||
4. Update environment variable SPIKE_PATH to the directory of the spike binary
|
||||
5. Update `riscv-ovpsim`_ to Nov 26, 2019 or later version
|
||||
|
||||
.. _steps: https://github.com/riscv/riscv-bitmanip/tree/master/tools#building-tools-with-draft-b-extension-instructions-support
|
||||
.. _riscv-gcc: https://github.com/riscv/riscv-bitmanip
|
||||
.. _build_file: https://github.com/riscv/riscv-bitmanip/blob/master/tools/riscv-isa-sim-build.sh
|
||||
.. _riscv-ovpsim: https://github.com/riscv/riscv-ovpsim
|
||||
|
||||
Sample .bashrc setup::
|
||||
|
||||
export RISCV_TOOLCHAIN=<riscv_gcc_install_path>
|
||||
export RISCV_GCC="$RISCV_TOOLCHAIN/bin/riscv64-unknown-elf-gcc"
|
||||
export RISCV_OBJCOPY="$RISCV_TOOLCHAIN/bin/riscv64-unknown-elf-objcopy"
|
||||
export SPIKE_PATH="$RISCV_TOOLCHAIN/bin"
|
||||
|
||||
Run bitmanip simulation
|
||||
------------------------
|
||||
|
||||
Bit manipulation tests are added in target "rv32imcb" or "rv64imcb". Here is the
|
||||
example to run bitmanip test with both ISS (spike and ovpsim). The instruction
|
||||
trace from these ISS will be cross compared::
|
||||
|
||||
run --target rv32imcb --test riscv_b_ext_test --iss spike,ovpsim
|
||||
|
||||
In `bitmanip testlist`_, there are a few bitmanip tests. Run option
|
||||
"+enable_b_extension=1" enables it and "+enable_bitmanip_groups=zbb,zbt"
|
||||
allows user to only enable one or some groups of bit manipulation instructions.
|
||||
|
||||
.. _bitmanip testlist: https://github.com/google/riscv-dv/blob/master/target/rv32imcb/testlist.yaml
|
||||
|
||||
Functional Coverage Support For Bitmanip
|
||||
-----------------------------------------
|
||||
|
||||
The functional covergroup is defined in `riscv_instr_cover_group.sv`_.
|
||||
It includes below major categories:
|
||||
|
||||
- If the operand is a register, cover all possible reg values for each operand::
|
||||
|
||||
cp_rs1 : coverpoint instr.rs1;
|
||||
cp_rs2 : coverpoint instr.rs2;
|
||||
cp_rd : coverpoint instr.rd;
|
||||
|
||||
- If the operand is an integer value and the amount of these possible values is
|
||||
less than XLEN*2, cover all the values::
|
||||
|
||||
// Cover all the count values of leading/Trailing zeros (0:XLEN-1) for clz, ctz
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(clz)
|
||||
`CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
// Cover all the shift values (0:XLEN-1) for slo
|
||||
`B_R_INSTR_CG_BEGIN(slo)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
- Hazard conditions
|
||||
|
||||
Before this `issue`_ is resolved, functional coverage can only be run with OVPsim::
|
||||
|
||||
cov --dir out/ovpsim_sim --iss ovpsim --target rv32imc
|
||||
|
||||
|
||||
.. _riscv_instr_cover_group.sv: https://github.com/google/riscv-dv/blob/master/src/riscv_instr_cover_group.sv
|
||||
.. _issue: https://github.com/riscv/riscv-bitmanip/issues/60
|
1
vendor/google_riscv-dv/docs/source/index.rst
vendored
1
vendor/google_riscv-dv/docs/source/index.rst
vendored
|
@ -13,6 +13,7 @@ Welcome to riscv-dv's documentation!
|
|||
overview
|
||||
getting_started
|
||||
configuration
|
||||
extension_support
|
||||
end_to_end_simulation
|
||||
generator_flow
|
||||
coverage_model
|
||||
|
|
3
vendor/google_riscv-dv/run.py
vendored
3
vendor/google_riscv-dv/run.py
vendored
|
@ -784,6 +784,9 @@ def load_config(args, cwd):
|
|||
elif args.target == "rv64imc":
|
||||
args.mabi = "lp64"
|
||||
args.isa = "rv64imc"
|
||||
elif args.target == "rv64imcb":
|
||||
args.mabi = "lp64"
|
||||
args.isa = "rv64imcb"
|
||||
elif args.target == "rv64gc":
|
||||
args.mabi = "lp64"
|
||||
args.isa = "rv64gc"
|
||||
|
|
64
vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
vendored
64
vendor/google_riscv-dv/src/isa/riscv_b_instr.sv
vendored
|
@ -20,27 +20,6 @@ class riscv_b_instr extends riscv_instr;
|
|||
rand riscv_reg_t rs3;
|
||||
bit has_rs3 = 1'b0;
|
||||
|
||||
constraint single_bit_shift_c {
|
||||
if (category == SHIFT) {
|
||||
imm inside {[0:31]};
|
||||
}
|
||||
}
|
||||
|
||||
constraint shuffle_c {
|
||||
if (instr_name inside {SHFLI, UNSHFLI}) {
|
||||
imm inside {[0:15]};
|
||||
}
|
||||
}
|
||||
|
||||
constraint or_combine_c {
|
||||
if (instr_name inside {GORCI}) {
|
||||
imm inside {[0:31]};
|
||||
}
|
||||
if (instr_name inside {GORCIW}) {
|
||||
imm inside {[0:63]};
|
||||
}
|
||||
}
|
||||
|
||||
`uvm_object_utils(riscv_b_instr)
|
||||
|
||||
function new(string name = "");
|
||||
|
@ -51,6 +30,13 @@ class riscv_b_instr extends riscv_instr;
|
|||
super.set_rand_mode();
|
||||
has_rs3 = 1'b0;
|
||||
case (format) inside
|
||||
R_FORMAT: begin
|
||||
if (instr_name inside {CLZW, CTZW, PCNTW, SEXT_B, SEXT_H, CLZ, CTZ, PCNT, BMATFLIP,
|
||||
CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CRC32_D,
|
||||
CRC32C_D}) begin
|
||||
has_rs2 = 1'b0;
|
||||
end
|
||||
end
|
||||
R4_FORMAT: begin
|
||||
has_imm = 1'b0;
|
||||
has_rs3 = 1'b1;
|
||||
|
@ -75,25 +61,19 @@ class riscv_b_instr extends riscv_instr;
|
|||
|
||||
if (format inside {I_FORMAT}) begin
|
||||
if (category inside {SHIFT, LOGICAL}) begin
|
||||
imm_len = 7;
|
||||
|
||||
if (group == RV64B) begin
|
||||
imm_len = 5;
|
||||
if (instr_name inside {SLLIU_W}) begin
|
||||
imm_len = 6;
|
||||
end
|
||||
end
|
||||
|
||||
if ((group == RV32B) && (imm_type == UIMM)) begin
|
||||
imm_len = 6;
|
||||
if (group == RV64B && !(instr_name inside {SLLIU_W})) begin
|
||||
imm_len = $clog2(XLEN) - 1;
|
||||
end else begin
|
||||
imm_len = $clog2(XLEN);
|
||||
end
|
||||
end
|
||||
|
||||
if ((category inside {ARITHMETIC}) && (group == RV32B)) begin
|
||||
imm_len = 5;
|
||||
// ARITHMETIC RV32B
|
||||
if (instr_name inside {SHFLI, UNSHFLI}) begin
|
||||
imm_len = $clog2(XLEN) - 1;
|
||||
end
|
||||
|
||||
if ((category inside {ARITHMETIC}) && (group == RV64B)) begin
|
||||
// ARITHMETIC RV64B
|
||||
if (instr_name inside {ADDIWU}) begin
|
||||
imm_len = 12;
|
||||
end
|
||||
end
|
||||
|
@ -115,9 +95,7 @@ class riscv_b_instr extends riscv_instr;
|
|||
end
|
||||
|
||||
R_FORMAT: begin //instr rd rs1
|
||||
if (instr_name inside {CLZW, CTZW, PCNTW, SEXT_B, SEXT_H, CLZ, CTZ, PCNT, BMATFLIP,
|
||||
CRC32_B, CRC32_H, CRC32_W, CRC32C_B, CRC32C_H, CRC32C_W, CRC32_D,
|
||||
CRC32C_D}) begin
|
||||
if (!has_rs2) begin
|
||||
asm_str_final = $sformatf("%0s%0s, %0s", asm_str, rd.name(), rs1.name());
|
||||
end
|
||||
end
|
||||
|
@ -473,9 +451,9 @@ class riscv_b_instr extends riscv_instr;
|
|||
virtual function bit is_supported(riscv_instr_gen_config cfg);
|
||||
return cfg.enable_b_extension && (
|
||||
(ZBB inside {cfg.enable_bitmanip_groups} && instr_name inside {
|
||||
CLZ, CTZ, PCNT,
|
||||
CLZ, CTZ, CLZW, CTZW, PCNT, PCNTW,
|
||||
SLO, SLOI, SLOW, SLOIW,
|
||||
SRO, SLOI, SROW, SLOIW,
|
||||
SRO, SROI, SROW, SROIW,
|
||||
MIN, MINU, MAX, MAXU,
|
||||
ADDWU, ADDIWU, SUBWU,
|
||||
ADDU_W, SUBU_W,
|
||||
|
@ -497,7 +475,9 @@ class riscv_b_instr extends riscv_instr;
|
|||
}) ||
|
||||
(ZBE inside {cfg.enable_bitmanip_groups} && instr_name inside {
|
||||
BEXT, BEXTW,
|
||||
BDEP, BDEPW
|
||||
BDEP, BDEPW,
|
||||
// TODO, spec 0.92 doesn't categorize these 2 instr in any group, put in ZBE for now
|
||||
SEXT_B, SEXT_H
|
||||
}) ||
|
||||
(ZBF inside {cfg.enable_bitmanip_groups} && instr_name inside {BFP, BFPW}) ||
|
||||
(ZBC inside {cfg.enable_bitmanip_groups} && instr_name inside {
|
||||
|
|
|
@ -111,8 +111,8 @@ class riscv_instr extends uvm_object;
|
|||
riscv_instr instr_inst;
|
||||
if (instr_name inside {unsupported_instr}) continue;
|
||||
instr_inst = create_instr(instr_name);
|
||||
if (!instr_inst.is_supported(cfg)) continue;
|
||||
instr_template[instr_name] = instr_inst;
|
||||
if (!instr_inst.is_supported(cfg)) continue;
|
||||
// C_JAL is RV32C only instruction
|
||||
if ((XLEN != 32) && (instr_name == C_JAL)) continue;
|
||||
if ((SP inside {cfg.reserved_regs}) && (instr_name inside {C_ADDI16SP})) begin
|
||||
|
@ -181,7 +181,8 @@ class riscv_instr extends uvm_object;
|
|||
if (!cfg.no_ebreak) begin
|
||||
basic_instr = {basic_instr, EBREAK};
|
||||
foreach (riscv_instr_pkg::supported_isa[i]) begin
|
||||
if (RV32C inside {riscv_instr_pkg::supported_isa[i]}) begin
|
||||
if (RV32C inside {riscv_instr_pkg::supported_isa[i]} &&
|
||||
!cfg.disable_compressed_instr) begin
|
||||
basic_instr = {basic_instr, C_EBREAK};
|
||||
break;
|
||||
end
|
||||
|
|
|
@ -196,20 +196,12 @@ class riscv_vector_instr extends riscv_floating_point_instr;
|
|||
if (allowed_va_variants.size() > 0) begin
|
||||
has_va_variant = 1;
|
||||
end
|
||||
case (format) inside
|
||||
VA_FORMAT : begin
|
||||
if (va_variant inside {WI, VI, VIM}) begin
|
||||
has_imm = 1'b1;
|
||||
has_vs1 = 1'b0;
|
||||
end else if (va_variant inside {WX, VX, VXM}) begin
|
||||
has_rs1 = 1'b1;
|
||||
has_vs1 = 1'b0;
|
||||
end else if (va_variant inside {VF, VFM}) begin
|
||||
has_fs1 = 1'b1;
|
||||
has_vs1 = 1'b0;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
// Set the rand mode based on the superset of all VA variants
|
||||
if (format == VA_FORMAT) begin
|
||||
has_imm = 1'b1;
|
||||
has_rs1 = 1'b1;
|
||||
has_fs1 = 1'b1;
|
||||
end
|
||||
endfunction : set_rand_mode
|
||||
|
||||
endclass : riscv_vector_instr
|
||||
|
|
|
@ -1048,6 +1048,11 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
string instr[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, INSTR_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
if (cfg.pmp_cfg.enable_pmp_exception_handler) begin
|
||||
cfg.pmp_cfg.gen_pmp_exception_routine({cfg.gpr, cfg.scratch_reg, cfg.pmp_reg},
|
||||
INSTRUCTION_ACCESS_FAULT,
|
||||
instr);
|
||||
end
|
||||
pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr);
|
||||
instr.push_back("mret");
|
||||
gen_section(get_label("instr_fault_handler", hart), instr);
|
||||
|
@ -1058,6 +1063,11 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
string instr[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, LOAD_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
if (cfg.pmp_cfg.enable_pmp_exception_handler) begin
|
||||
cfg.pmp_cfg.gen_pmp_exception_routine({cfg.gpr, cfg.scratch_reg, cfg.pmp_reg},
|
||||
LOAD_ACCESS_FAULT,
|
||||
instr);
|
||||
end
|
||||
pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr);
|
||||
instr.push_back("mret");
|
||||
gen_section(get_label("load_fault_handler", hart), instr);
|
||||
|
@ -1068,6 +1078,11 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
string instr[$];
|
||||
gen_signature_handshake(instr, CORE_STATUS, STORE_FAULT_EXCEPTION);
|
||||
gen_signature_handshake(.instr(instr), .signature_type(WRITE_CSR), .csr(MCAUSE));
|
||||
if (cfg.pmp_cfg.enable_pmp_exception_handler) begin
|
||||
cfg.pmp_cfg.gen_pmp_exception_routine({cfg.gpr, cfg.scratch_reg, cfg.pmp_reg},
|
||||
STORE_AMO_ACCESS_FAULT,
|
||||
instr);
|
||||
end
|
||||
pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, cfg.sp, cfg.tp, instr);
|
||||
instr.push_back("mret");
|
||||
gen_section(get_label("store_fault_handler", hart), instr);
|
||||
|
|
|
@ -20,8 +20,10 @@ class riscv_instr_cov_item extends riscv_instr;
|
|||
NORMAL_VAL, MIN_VAL, MAX_VAL, ZERO_VAL
|
||||
} special_val_e;
|
||||
|
||||
rand riscv_reg_t rs3;
|
||||
rand bit [XLEN-1:0] rs1_value;
|
||||
rand bit [XLEN-1:0] rs2_value;
|
||||
rand bit [XLEN-1:0] rs3_value;
|
||||
rand bit [XLEN-1:0] rd_value;
|
||||
rand riscv_fpr_t fs1;
|
||||
rand riscv_fpr_t fs2;
|
||||
|
@ -42,6 +44,7 @@ class riscv_instr_cov_item extends riscv_instr;
|
|||
div_result_e div_result;
|
||||
operand_sign_e rs1_sign;
|
||||
operand_sign_e rs2_sign;
|
||||
operand_sign_e rs3_sign;
|
||||
operand_sign_e fs1_sign;
|
||||
operand_sign_e fs2_sign;
|
||||
operand_sign_e fs3_sign;
|
||||
|
@ -52,6 +55,7 @@ class riscv_instr_cov_item extends riscv_instr;
|
|||
hazard_e lsu_hazard;
|
||||
special_val_e rs1_special_val;
|
||||
special_val_e rs2_special_val;
|
||||
special_val_e rs3_special_val;
|
||||
special_val_e rd_special_val;
|
||||
special_val_e imm_special_val;
|
||||
compare_result_e compare_result;
|
||||
|
@ -67,6 +71,7 @@ class riscv_instr_cov_item extends riscv_instr;
|
|||
unaligned_pc = (pc[1:0] != 2'b00);
|
||||
rs1_sign = get_operand_sign(rs1_value);
|
||||
rs2_sign = get_operand_sign(rs2_value);
|
||||
rs3_sign = get_operand_sign(rs3_value);
|
||||
rd_sign = get_operand_sign(rd_value);
|
||||
fs1_sign = get_operand_sign(fs1_value);
|
||||
fs2_sign = get_operand_sign(fs2_value);
|
||||
|
@ -76,6 +81,7 @@ class riscv_instr_cov_item extends riscv_instr;
|
|||
rs1_special_val = get_operand_special_val(rs1_value);
|
||||
rd_special_val = get_operand_special_val(rd_value);
|
||||
rs2_special_val = get_operand_special_val(rs2_value);
|
||||
rs3_special_val = get_operand_special_val(rs3_value);
|
||||
if ((format != R_FORMAT) && (format != CR_FORMAT)) begin
|
||||
imm_special_val = get_imm_special_val(imm);
|
||||
end
|
||||
|
@ -195,12 +201,12 @@ class riscv_instr_cov_item extends riscv_instr;
|
|||
case(instr_name)
|
||||
BEQ : is_branch_hit = (rs1_value == rs2_value);
|
||||
C_BEQZ : is_branch_hit = (rs1_value == 0);
|
||||
BNE : is_branch_hit = (rs1_value == rs2_value);
|
||||
BNE : is_branch_hit = (rs1_value != rs2_value);
|
||||
C_BNEZ : is_branch_hit = (rs1_value != 0);
|
||||
BLT : is_branch_hit = ($signed(rs1_value) < $signed(rs2_value));
|
||||
BGE : is_branch_hit = ($signed(rs1_value) > $signed(rs2_value));
|
||||
BGE : is_branch_hit = ($signed(rs1_value) >= $signed(rs2_value));
|
||||
BLTU : is_branch_hit = (rs1_value < rs2_value);
|
||||
BGEU : is_branch_hit = (rs1_value > rs2_value);
|
||||
BGEU : is_branch_hit = (rs1_value >= rs2_value);
|
||||
default: `uvm_error(get_name(), $sformatf("Unexpected instr %0s", instr_name.name()))
|
||||
endcase
|
||||
return is_branch_hit;
|
||||
|
|
|
@ -92,6 +92,12 @@
|
|||
cp_imm_sign : coverpoint instr.imm_sign; \
|
||||
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
|
||||
|
||||
`define B_I_INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
`INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
cp_rs1 : coverpoint instr.rs1; \
|
||||
cp_rd : coverpoint instr.rd; \
|
||||
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
|
||||
|
||||
`define U_INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
`INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
cp_rd : coverpoint instr.rd; \
|
||||
|
@ -257,6 +263,38 @@
|
|||
cp_fd_sign : coverpoint instr.fd_sign; \
|
||||
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
|
||||
|
||||
`define B_R_INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
`INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
cp_rs1 : coverpoint instr.rs1; \
|
||||
cp_rs2 : coverpoint instr.rs2; \
|
||||
cp_rd : coverpoint instr.rd; \
|
||||
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
|
||||
|
||||
`define B_R_INSTR_NO_RS2_CG_BEGIN(INSTR_NAME) \
|
||||
`INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
cp_rs1 : coverpoint instr.rs1; \
|
||||
cp_rd : coverpoint instr.rd; \
|
||||
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
|
||||
|
||||
`define B_R4_INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
`INSTR_CG_BEGIN(INSTR_NAME) \
|
||||
cp_rs1 : coverpoint instr.rs1; \
|
||||
cp_rs2 : coverpoint instr.rs2; \
|
||||
cp_rs3 : coverpoint instr.rs3; \
|
||||
cp_rd : coverpoint instr.rd; \
|
||||
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
|
||||
|
||||
|
||||
// only enable the coverpoint for a particular XLEN (32, 64, 128)
|
||||
`define ENABLE_CP_BY_XLEN(XLEN_VAL) \
|
||||
option.weight = (XLEN == XLEN_VAL); \
|
||||
type_option.weight = (XLEN == XLEN_VAL); \
|
||||
|
||||
`define CP_VALUE_RANGE(NAME, VAL, START, END) \
|
||||
cp_``NAME``: coverpoint VAL{ \
|
||||
bins values[] = {[START:END]}; \
|
||||
}
|
||||
|
||||
`define CG_END endgroup
|
||||
|
||||
`define CG_SELECTOR_BEGIN(CG_ISA) \
|
||||
|
@ -554,6 +592,398 @@ class riscv_instr_cover_group;
|
|||
`FP_R4_INSTR_CG_BEGIN(fnmsub_s)
|
||||
`CG_END
|
||||
|
||||
// B extension
|
||||
// Count Leading/Trailing Zeros (clz, ctz)
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(clz)
|
||||
`CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(ctz)
|
||||
`CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(clzw)
|
||||
`CP_VALUE_RANGE(num_leading_zeros, instr.rd_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(ctzw)
|
||||
`CP_VALUE_RANGE(num_trailing_zeros, instr.rd_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
// Count Bits Set (pcnt)
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(pcnt)
|
||||
`CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(pcntw)
|
||||
`CP_VALUE_RANGE(num_set_bits, instr.rd_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
// Logic-with-negate (andn, orn, xnor)
|
||||
`B_R_INSTR_CG_BEGIN(andn)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(orn)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(xnor)
|
||||
`CG_END
|
||||
|
||||
// Pack two words in one register (pack, packu, packh)
|
||||
`B_R_INSTR_CG_BEGIN(pack)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(packu)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(packh)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(packw)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(packuw)
|
||||
`CG_END
|
||||
|
||||
// Min/max instructions (min, max, minu, maxu)
|
||||
`B_R_INSTR_CG_BEGIN(min)
|
||||
cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
|
||||
cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
|
||||
bins equal = {1};
|
||||
}
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(max)
|
||||
cp_rs1_gt_rs2 : coverpoint (longint'(instr.rs1_value) > longint'(instr.rs2_value));
|
||||
cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
|
||||
bins equal = {1};
|
||||
}
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(minu)
|
||||
cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value);
|
||||
cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
|
||||
bins equal = {1};
|
||||
}
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(maxu)
|
||||
cp_rs1_gt_rs2 : coverpoint (instr.rs1_value > instr.rs2_value);
|
||||
cp_rs1_eq_rs2 : coverpoint (instr.rs1_value == instr.rs2_value) {
|
||||
bins equal = {1};
|
||||
}
|
||||
`CG_END
|
||||
|
||||
// Sign-extend instructions (sext.b, sext.h)
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(sext_b)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(sext_h)
|
||||
`CG_END
|
||||
|
||||
// Single-bit instructions (sbset, sbclr, sbinv, sbext)
|
||||
`B_R_INSTR_CG_BEGIN(sbset)
|
||||
`CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(sbclr)
|
||||
`CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(sbinv)
|
||||
`CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(sbext)
|
||||
`CP_VALUE_RANGE(bit_location, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbseti)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbclri)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbinvi)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sbexti)
|
||||
`CP_VALUE_RANGE(bit_location, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
// Shift Ones (Left/Right) (slo, sloi, sro, sroi)
|
||||
`B_R_INSTR_CG_BEGIN(slo)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(sro)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sloi)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sroi)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(slow)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(srow)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sloiw)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(sroiw)
|
||||
`CP_VALUE_RANGE(num_ones_shift, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
// Rotate (Left/Right) (rol, ror, rori)
|
||||
`B_R_INSTR_CG_BEGIN(ror)
|
||||
`CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(rol)
|
||||
`CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(rori)
|
||||
`CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(rorw)
|
||||
`CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(rolw)
|
||||
`CP_VALUE_RANGE(num_bit_rotate, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(roriw)
|
||||
`CP_VALUE_RANGE(num_bit_rotate, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
// Generalized Reverse (grev, grevi, rev)
|
||||
`B_R_INSTR_CG_BEGIN(grev)
|
||||
`CP_VALUE_RANGE(reverse_mode, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(grevi)
|
||||
`CP_VALUE_RANGE(reverse_mode, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(grevw)
|
||||
`CP_VALUE_RANGE(reverse_mode, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(greviw)
|
||||
`CP_VALUE_RANGE(reverse_mode, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
// Generalized Shuffle (shfl, unshfl, shfli, unshfli, zip, unzip)
|
||||
`B_R_INSTR_CG_BEGIN(shfl)
|
||||
`CP_VALUE_RANGE(shuffle_mode, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(unshfl)
|
||||
`CP_VALUE_RANGE(shuffle_mode, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(shfli)
|
||||
`CP_VALUE_RANGE(shuffle_mode, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(unshfli)
|
||||
`CP_VALUE_RANGE(shuffle_mode, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(shflw)
|
||||
`CP_VALUE_RANGE(shuffle_mode, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(unshflw)
|
||||
`CP_VALUE_RANGE(shuffle_mode, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
// Generalized OR-Combine (gorc, gorci)
|
||||
`B_R_INSTR_CG_BEGIN(gorc)
|
||||
`CP_VALUE_RANGE(or_combine_mode, instr.rs2_value, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(gorci)
|
||||
`CP_VALUE_RANGE(or_combine_mode, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(gorcw)
|
||||
`CP_VALUE_RANGE(or_combine_mode, instr.rs2_value, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(gorciw)
|
||||
`CP_VALUE_RANGE(or_combine_mode, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
// Bit-Field Place (bfp)
|
||||
`B_R_INSTR_CG_BEGIN(bfp)
|
||||
// cover all values of length and offset
|
||||
cp_len: coverpoint instr.rs2_value[27:24] iff (XLEN == 32) {
|
||||
`ENABLE_CP_BY_XLEN(32)
|
||||
bins values[] = {[0:XLEN/2-1]};
|
||||
}
|
||||
cp_offset: coverpoint instr.rs2_value[20:16] iff (XLEN == 32) {
|
||||
`ENABLE_CP_BY_XLEN(32)
|
||||
bins values[] = {[0:XLEN-1]};
|
||||
}
|
||||
cp_len_64bit_sel01: coverpoint instr.rs2_value[60:56] iff (XLEN == 64 &&
|
||||
instr.rs2_value[XLEN-1:XLEN-2] == 2'b10) {
|
||||
`ENABLE_CP_BY_XLEN(64)
|
||||
bins values[] = {[0:XLEN/2-1]};
|
||||
}
|
||||
cp_offset_64bit_sel01: coverpoint instr.rs2_value[53:48] iff (XLEN == 64 &&
|
||||
instr.rs2_value[XLEN-1:XLEN-2] == 2'b10) {
|
||||
`ENABLE_CP_BY_XLEN(64)
|
||||
bins values = {[0:XLEN-1]};
|
||||
}
|
||||
cp_len_64bit_not_sel01: coverpoint instr.rs2_value[60:56] iff (XLEN == 64 &&
|
||||
instr.rs2_value[XLEN-1:XLEN-2] != 2'b10) {
|
||||
`ENABLE_CP_BY_XLEN(64)
|
||||
bins values[] = {[0:XLEN/2-1]};
|
||||
}
|
||||
cp_offset_64bit_not_sel01: coverpoint instr.rs2_value[53:48] iff (XLEN == 64 &&
|
||||
instr.rs2_value[XLEN-1:XLEN-2] != 2'b10) {
|
||||
`ENABLE_CP_BY_XLEN(64)
|
||||
bins values[] = {[0:XLEN-1]};
|
||||
}
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(bfpw)
|
||||
// cover all values of length and offset
|
||||
`CP_VALUE_RANGE(length, instr.rs2_value[27:24], 0, XLEN/2-1)
|
||||
`CP_VALUE_RANGE(offset, instr.rs2_value[20:16], 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(bext)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(bextw)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(bdep)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(bdepw)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(clmul)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(clmulh)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(clmulr)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(clmulw)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(clmulhw)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(clmulrw)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32_b)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32_h)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32_w)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32c_b)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32c_h)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32c_w)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32_d)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(crc32c_d)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(bmator)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(bmatxor)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_NO_RS2_CG_BEGIN(bmatflip)
|
||||
`CG_END
|
||||
|
||||
`B_R4_INSTR_CG_BEGIN(cmix)
|
||||
`CG_END
|
||||
|
||||
`B_R4_INSTR_CG_BEGIN(cmov)
|
||||
`CG_END
|
||||
|
||||
`B_R4_INSTR_CG_BEGIN(fsl)
|
||||
`CP_VALUE_RANGE(num_shift, instr.rs2_value, 0, 2*XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R4_INSTR_CG_BEGIN(fsr)
|
||||
`CP_VALUE_RANGE(num_shift, instr.rs2_value, 0, 2*XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(fsri)
|
||||
cp_rs3 : coverpoint instr.rs3;
|
||||
`CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R4_INSTR_CG_BEGIN(fslw)
|
||||
`CP_VALUE_RANGE(num_shift, instr.rs2_value, 0, 2*XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_R4_INSTR_CG_BEGIN(fsrw)
|
||||
`CP_VALUE_RANGE(num_shift, instr.rs2_value, 0, 2*XLEN-1)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(fsriw)
|
||||
cp_rs3 : coverpoint instr.rs3;
|
||||
`CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN/2-1)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(addwu)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(subwu)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(addiwu)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(addu_w)
|
||||
`CG_END
|
||||
|
||||
`B_R_INSTR_CG_BEGIN(subu_w)
|
||||
`CG_END
|
||||
|
||||
`B_I_INSTR_CG_BEGIN(slliu_w)
|
||||
`CP_VALUE_RANGE(num_shift, instr.imm, 0, XLEN-1)
|
||||
`CG_END
|
||||
|
||||
// CSR instructions
|
||||
`CSR_INSTR_CG_BEGIN(csrrw)
|
||||
cp_rs1 : coverpoint instr.rs1;
|
||||
|
@ -1220,6 +1650,103 @@ class riscv_instr_cover_group;
|
|||
fnmsub_s_cg = new();
|
||||
`CG_SELECTOR_END
|
||||
|
||||
`CG_SELECTOR_BEGIN(RV32B)
|
||||
clz_cg = new();
|
||||
ctz_cg = new();
|
||||
pcnt_cg = new();
|
||||
andn_cg = new();
|
||||
orn_cg = new();
|
||||
xnor_cg = new();
|
||||
pack_cg = new();
|
||||
packh_cg = new();
|
||||
min_cg = new();
|
||||
max_cg = new();
|
||||
minu_cg = new();
|
||||
maxu_cg = new();
|
||||
sext_b_cg = new();
|
||||
sext_h_cg = new();
|
||||
sbset_cg = new();
|
||||
sbclr_cg = new();
|
||||
sbinv_cg = new();
|
||||
sbext_cg = new();
|
||||
sbseti_cg = new();
|
||||
sbclri_cg = new();
|
||||
sbinvi_cg = new();
|
||||
sbexti_cg = new();
|
||||
slo_cg = new();
|
||||
sro_cg = new();
|
||||
sloi_cg = new();
|
||||
sroi_cg = new();
|
||||
ror_cg = new();
|
||||
rol_cg = new();
|
||||
rori_cg = new();
|
||||
grev_cg = new();
|
||||
grevi_cg = new();
|
||||
shfli_cg = new();
|
||||
unshfli_cg = new();
|
||||
shfl_cg = new();
|
||||
unshfl_cg = new();
|
||||
gorc_cg = new();
|
||||
gorci_cg = new();
|
||||
bfp_cg = new();
|
||||
bext_cg = new();
|
||||
bdep_cg = new();
|
||||
clmul_cg = new();
|
||||
clmulh_cg = new();
|
||||
clmulr_cg = new();
|
||||
crc32_b_cg = new();
|
||||
crc32_h_cg = new();
|
||||
crc32_w_cg = new();
|
||||
crc32c_b_cg = new();
|
||||
crc32c_h_cg = new();
|
||||
crc32c_w_cg = new();
|
||||
cmix_cg = new();
|
||||
cmov_cg = new();
|
||||
fsl_cg = new();
|
||||
fsr_cg = new();
|
||||
fsri_cg = new();
|
||||
`CG_SELECTOR_END
|
||||
|
||||
`CG_SELECTOR_BEGIN(RV64B)
|
||||
clzw_cg = new();
|
||||
ctzw_cg = new();
|
||||
pcntw_cg = new();
|
||||
packw_cg = new();
|
||||
packuw_cg = new();
|
||||
slow_cg = new();
|
||||
srow_cg = new();
|
||||
sloiw_cg = new();
|
||||
sroiw_cg = new();
|
||||
rorw_cg = new();
|
||||
rolw_cg = new();
|
||||
roriw_cg = new();
|
||||
grevw_cg = new();
|
||||
greviw_cg = new();
|
||||
shflw_cg = new();
|
||||
unshflw_cg = new();
|
||||
gorcw_cg = new();
|
||||
gorciw_cg = new();
|
||||
bfpw_cg = new();
|
||||
bextw_cg = new();
|
||||
bdepw_cg = new();
|
||||
clmulw_cg = new();
|
||||
clmulhw_cg = new();
|
||||
clmulrw_cg = new();
|
||||
crc32_d_cg = new();
|
||||
crc32c_d_cg = new();
|
||||
bmator_cg = new();
|
||||
bmatxor_cg = new();
|
||||
bmatflip_cg = new();
|
||||
fslw_cg = new();
|
||||
fsrw_cg = new();
|
||||
fsriw_cg = new();
|
||||
addwu_cg = new();
|
||||
subwu_cg = new();
|
||||
addiwu_cg = new();
|
||||
addu_w_cg = new();
|
||||
subu_w_cg = new();
|
||||
slliu_w_cg = new();
|
||||
`CG_SELECTOR_END
|
||||
// Ignore the exception which cannot be covered when running with ISS
|
||||
if (iss_mode) begin
|
||||
int i;
|
||||
|
@ -1387,6 +1914,100 @@ class riscv_instr_cover_group;
|
|||
FNMADD_S : `SAMPLE(fnmadd_s_cg, instr)
|
||||
FMSUB_S : `SAMPLE(fmsub_s_cg, instr)
|
||||
FNMSUB_S : `SAMPLE(fnmsub_s_cg, instr)
|
||||
// RV32B
|
||||
CLZ : `SAMPLE(clz_cg, instr)
|
||||
CTZ : `SAMPLE(ctz_cg, instr)
|
||||
PCNT : `SAMPLE(pcnt_cg, instr)
|
||||
ANDN : `SAMPLE(andn_cg, instr)
|
||||
ORN : `SAMPLE(orn_cg, instr)
|
||||
XNOR : `SAMPLE(xnor_cg, instr)
|
||||
PACK : `SAMPLE(pack_cg, instr)
|
||||
PACKH : `SAMPLE(packh_cg, instr)
|
||||
MIN : `SAMPLE(min_cg, instr)
|
||||
MAX : `SAMPLE(max_cg, instr)
|
||||
MINU : `SAMPLE(minu_cg, instr)
|
||||
MAXU : `SAMPLE(maxu_cg, instr)
|
||||
SEXT_B : `SAMPLE(sext_b_cg, instr)
|
||||
SEXT_H : `SAMPLE(sext_h_cg, instr)
|
||||
SBSET : `SAMPLE(sbset_cg, instr)
|
||||
SBCLR : `SAMPLE(sbclr_cg, instr)
|
||||
SBINV : `SAMPLE(sbinv_cg, instr)
|
||||
SBEXT : `SAMPLE(sbext_cg, instr)
|
||||
SBSETI : `SAMPLE(sbseti_cg, instr)
|
||||
SBCLRI : `SAMPLE(sbclri_cg, instr)
|
||||
SBINVI : `SAMPLE(sbinvi_cg, instr)
|
||||
SBEXTI : `SAMPLE(sbexti_cg, instr)
|
||||
SLO : `SAMPLE(slo_cg, instr)
|
||||
SRO : `SAMPLE(sro_cg, instr)
|
||||
SLOI : `SAMPLE(sloi_cg, instr)
|
||||
SROI : `SAMPLE(sroi_cg, instr)
|
||||
ROR : `SAMPLE(ror_cg, instr)
|
||||
ROL : `SAMPLE(rol_cg, instr)
|
||||
RORI : `SAMPLE(rori_cg, instr)
|
||||
GREV : `SAMPLE(grev_cg, instr)
|
||||
GREVI : `SAMPLE(grevi_cg, instr)
|
||||
SHFLI : `SAMPLE(shfli_cg, instr)
|
||||
UNSHFLI : `SAMPLE(unshfli_cg, instr)
|
||||
SHFL : `SAMPLE(shfl_cg, instr)
|
||||
UNSHFL : `SAMPLE(unshfl_cg, instr)
|
||||
GORC : `SAMPLE(gorc_cg, instr)
|
||||
GORCI : `SAMPLE(gorci_cg, instr)
|
||||
BFP : `SAMPLE(bfp_cg, instr)
|
||||
BEXT : `SAMPLE(bext_cg, instr)
|
||||
BDEP : `SAMPLE(bdep_cg, instr)
|
||||
CLMUL : `SAMPLE(clmul_cg, instr)
|
||||
CLMULH : `SAMPLE(clmulh_cg, instr)
|
||||
CLMULR : `SAMPLE(clmulr_cg, instr)
|
||||
CRC32_B : `SAMPLE(crc32_b_cg, instr)
|
||||
CRC32_H : `SAMPLE(crc32_h_cg, instr)
|
||||
CRC32_W : `SAMPLE(crc32_w_cg, instr)
|
||||
CRC32C_B : `SAMPLE(crc32c_b_cg, instr)
|
||||
CRC32C_H : `SAMPLE(crc32c_h_cg, instr)
|
||||
CRC32C_W : `SAMPLE(crc32c_w_cg, instr)
|
||||
CMIX : `SAMPLE(cmix_cg, instr)
|
||||
CMOV : `SAMPLE(cmov_cg, instr)
|
||||
FSL : `SAMPLE(fsl_cg, instr)
|
||||
FSR : `SAMPLE(fsr_cg, instr)
|
||||
FSRI : `SAMPLE(fsri_cg, instr)
|
||||
// RV64B
|
||||
CLZW : `SAMPLE(clzw_cg, instr)
|
||||
CTZW : `SAMPLE(ctzw_cg, instr)
|
||||
PCNTW : `SAMPLE(pcntw_cg, instr)
|
||||
PACKW : `SAMPLE(packw_cg, instr)
|
||||
PACKUW : `SAMPLE(packuw_cg, instr)
|
||||
SLOW : `SAMPLE(slow_cg, instr)
|
||||
SROW : `SAMPLE(srow_cg, instr)
|
||||
SLOIW : `SAMPLE(sloiw_cg, instr)
|
||||
SROIW : `SAMPLE(sroiw_cg, instr)
|
||||
RORW : `SAMPLE(rorw_cg, instr)
|
||||
ROLW : `SAMPLE(rolw_cg, instr)
|
||||
RORIW : `SAMPLE(roriw_cg, instr)
|
||||
GREVW : `SAMPLE(grevw_cg, instr)
|
||||
GREVIW : `SAMPLE(greviw_cg, instr)
|
||||
SHFLW : `SAMPLE(shflw_cg, instr)
|
||||
UNSHFLW : `SAMPLE(unshflw_cg, instr)
|
||||
GORCW : `SAMPLE(gorcw_cg, instr)
|
||||
GORCIW : `SAMPLE(gorciw_cg, instr)
|
||||
BFPW : `SAMPLE(bfpw_cg, instr)
|
||||
BEXTW : `SAMPLE(bextw_cg, instr)
|
||||
BDEPW : `SAMPLE(bdepw_cg, instr)
|
||||
CLMULW : `SAMPLE(clmulw_cg, instr)
|
||||
CLMULHW : `SAMPLE(clmulhw_cg, instr)
|
||||
CLMULRW : `SAMPLE(clmulrw_cg, instr)
|
||||
CRC32_D : `SAMPLE(crc32_d_cg, instr)
|
||||
CRC32C_D : `SAMPLE(crc32c_d_cg, instr)
|
||||
BMATOR : `SAMPLE(bmator_cg, instr)
|
||||
BMATXOR : `SAMPLE(bmatxor_cg, instr)
|
||||
BMATFLIP : `SAMPLE(bmatflip_cg, instr)
|
||||
FSLW : `SAMPLE(fslw_cg, instr)
|
||||
FSRW : `SAMPLE(fsrw_cg, instr)
|
||||
FSRIW : `SAMPLE(fsriw_cg, instr)
|
||||
ADDWU : `SAMPLE(addwu_cg, instr)
|
||||
SUBWU : `SAMPLE(subwu_cg, instr)
|
||||
ADDIWU : `SAMPLE(addiwu_cg, instr)
|
||||
ADDU_W : `SAMPLE(addu_w_cg, instr)
|
||||
SUBU_W : `SAMPLE(subu_w_cg, instr)
|
||||
SLLIU_W : `SAMPLE(slliu_w_cg, instr)
|
||||
`VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv")
|
||||
default: begin
|
||||
if (instr.group == RV32I) begin
|
||||
|
|
|
@ -80,6 +80,11 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
// Used by any DCSR operations inside of the debug rom.
|
||||
// Also used by the PMP generation.
|
||||
rand riscv_reg_t scratch_reg;
|
||||
// Reg used exclusively by the PMP exception handling routine.
|
||||
// Can overlap with the other GPRs used in the random generation,
|
||||
// as PMP exception handler is hardcoded and does not include any
|
||||
// random instructions.
|
||||
rand riscv_reg_t pmp_reg;
|
||||
// Use a random register for stack pointer/thread pointer
|
||||
rand riscv_reg_t sp;
|
||||
rand riscv_reg_t tp;
|
||||
|
@ -395,9 +400,15 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
scratch_reg != tp;
|
||||
}
|
||||
|
||||
constraint reserve_pmp_reg_c {
|
||||
pmp_reg != ZERO;
|
||||
pmp_reg != sp;
|
||||
pmp_reg != tp;
|
||||
}
|
||||
|
||||
constraint gpr_c {
|
||||
foreach (gpr[i]) {
|
||||
!(gpr[i] inside {sp, tp, scratch_reg, ZERO, RA, GP});
|
||||
!(gpr[i] inside {sp, tp, scratch_reg, pmp_reg, ZERO, RA, GP});
|
||||
}
|
||||
unique {gpr};
|
||||
}
|
||||
|
|
|
@ -1054,6 +1054,9 @@ package riscv_instr_pkg;
|
|||
bit r;
|
||||
// RV32: the pmpaddr is the top 32 bits of a 34 bit PMP address
|
||||
// RV64: the pmpaddr is the top 54 bits of a 56 bit PMP address
|
||||
bit [XLEN - 1 : 0] addr;
|
||||
// The offset from the address of <main> - automatically populated by the
|
||||
// PMP generation routine.
|
||||
bit [XLEN - 1 : 0] offset;
|
||||
`else
|
||||
typedef struct{
|
||||
|
@ -1065,6 +1068,9 @@ package riscv_instr_pkg;
|
|||
rand bit r;
|
||||
// RV32: the pmpaddr is the top 32 bits of a 34 bit PMP address
|
||||
// RV64: the pmpaddr is the top 54 bits of a 56 bit PMP address
|
||||
bit [XLEN - 1 : 0] addr;
|
||||
// The offset from the address of <main> - automatically populated by the
|
||||
// PMP generation routine.
|
||||
rand bit [XLEN - 1 : 0] offset;
|
||||
`endif
|
||||
} pmp_cfg_reg_t;
|
||||
|
|
|
@ -252,7 +252,7 @@ class riscv_instr_sequence extends uvm_sequence;
|
|||
// Convert the instruction stream to the string format.
|
||||
// Label is attached to the instruction if available, otherwise attach proper space to make
|
||||
// the code indent consistent.
|
||||
function void generate_instr_stream(bit no_label = 1'b0);
|
||||
virtual function void generate_instr_stream(bit no_label = 1'b0);
|
||||
string prefix, str;
|
||||
int i;
|
||||
instr_string_list = {};
|
||||
|
|
350
vendor/google_riscv-dv/src/riscv_pmp_cfg.sv
vendored
350
vendor/google_riscv-dv/src/riscv_pmp_cfg.sv
vendored
|
@ -22,11 +22,22 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
// default to granularity of 0 (4 bytes grain)
|
||||
int pmp_granularity = 0;
|
||||
|
||||
// number of configuration bytes per pmpcfg CSR
|
||||
int cfg_per_csr;
|
||||
|
||||
// enable bit for pmp randomization
|
||||
bit pmp_randomize = 0;
|
||||
|
||||
// allow pmp randomization to cause address range overlap
|
||||
bit pmp_allow_addr_overlap = 0;
|
||||
rand bit pmp_allow_addr_overlap = 0;
|
||||
|
||||
// By default, after returning from a PMP exception, we return to the exact same instruction that
|
||||
// resulted in a PMP exception to begin with, creating an infinite loop of taking an exception.
|
||||
// To avoid this situation, this configuration knob will enable the relevant PMP exception
|
||||
// handlers to find the pmpcfg CSR that controls the address region resulting in the exception and
|
||||
// change the relevant access bit to 1'b1, allowing forward progress in the code, while also
|
||||
// allowing all access restrictions to be enforced.
|
||||
bit enable_pmp_exception_handler = 1'b1;
|
||||
|
||||
// pmp CSR configurations
|
||||
rand pmp_cfg_reg_t pmp_cfg[];
|
||||
|
@ -43,6 +54,10 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
typedef uvm_enum_wrapper#(pmp_addr_mode_t) addr_mode_wrapper;
|
||||
pmp_addr_mode_t addr_mode;
|
||||
|
||||
// Store the base addresses of pmpaddr0 and pmpcfg0
|
||||
riscv_instr_pkg::privileged_reg_t base_pmp_addr = PMPADDR0;
|
||||
riscv_instr_pkg::privileged_reg_t base_pmpcfg_addr = PMPCFG0;
|
||||
|
||||
`uvm_object_utils_begin(riscv_pmp_cfg)
|
||||
`uvm_field_int(pmp_num_regions, UVM_DEFAULT)
|
||||
`uvm_field_int(pmp_granularity, UVM_DEFAULT)
|
||||
|
@ -92,9 +107,19 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
}
|
||||
}
|
||||
|
||||
// Privileged spec states that in TOR mode, offset[i-1] < offset[i]
|
||||
constraint tor_addr_overlap_c {
|
||||
foreach (pmp_cfg[i]) {
|
||||
if (pmp_cfg[i].a == TOR) {
|
||||
pmp_allow_addr_overlap == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function new(string name = "");
|
||||
string s;
|
||||
super.new(name);
|
||||
cfg_per_csr = XLEN / 8;
|
||||
inst = uvm_cmdline_processor::get_inst();
|
||||
get_bool_arg_value("+pmp_randomize=", pmp_randomize);
|
||||
get_bool_arg_value("+pmp_allow_addr_overlap=", pmp_allow_addr_overlap);
|
||||
|
@ -117,7 +142,7 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
function void post_randomize();
|
||||
`ifdef _VCP //GRK958
|
||||
foreach(pmp_cfg[i]) pmp_cfg[i].zero = 2'b00;
|
||||
`endif
|
||||
`endif
|
||||
setup_pmp();
|
||||
endfunction
|
||||
|
||||
|
@ -146,18 +171,19 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
foreach (pmp_cfg[i]) begin
|
||||
arg_name = $sformatf("+pmp_region_%0d=", i);
|
||||
if (inst.get_arg_value(arg_name, pmp_region)) begin
|
||||
parse_pmp_config(pmp_region, pmp_cfg[i]);
|
||||
pmp_cfg[i] = parse_pmp_config(pmp_region, pmp_cfg[i]);
|
||||
`uvm_info(`gfn, $sformatf("Configured pmp_cfg[%0d] from command line: %p",
|
||||
i, pmp_cfg[i]), UVM_LOW)
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void parse_pmp_config(string pmp_region, ref pmp_cfg_reg_t pmp_cfg_reg);
|
||||
function pmp_cfg_reg_t parse_pmp_config(string pmp_region, pmp_cfg_reg_t ref_pmp_cfg);
|
||||
string fields[$];
|
||||
string field_vals[$];
|
||||
string field_type;
|
||||
string field_val;
|
||||
pmp_cfg_reg_t pmp_cfg_reg = ref_pmp_cfg;
|
||||
uvm_split_string(pmp_region, ",", fields);
|
||||
foreach (fields[i]) begin
|
||||
uvm_split_string(fields[i], ":", field_vals);
|
||||
|
@ -183,13 +209,14 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
"ADDR": begin
|
||||
// Don't have to convert address to "PMP format" here,
|
||||
// since it must be masked off in hardware
|
||||
pmp_cfg_reg.offset = format_addr(field_val.atohex());
|
||||
pmp_cfg_reg.addr = format_addr(field_val.atohex());
|
||||
end
|
||||
default: begin
|
||||
`uvm_fatal(`gfn, $sformatf("%s, Invalid PMP configuration field name!", field_val))
|
||||
end
|
||||
endcase
|
||||
end
|
||||
return pmp_cfg_reg;
|
||||
endfunction
|
||||
|
||||
function bit [XLEN - 1 : 0] format_addr(bit [XLEN - 1 : 0] addr);
|
||||
|
@ -221,12 +248,9 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
// CSR, this function waits until it has reached this maximum to write to the physical CSR to
|
||||
// save some extraneous instructions from being performed.
|
||||
function void gen_pmp_instr(riscv_reg_t scratch_reg[2], ref string instr[$]);
|
||||
int cfg_per_csr = XLEN / 8;
|
||||
bit [XLEN - 1 : 0] pmp_word;
|
||||
bit [XLEN - 1 : 0] cfg_bitmask;
|
||||
bit [7 : 0] cfg_byte;
|
||||
riscv_instr_pkg::privileged_reg_t base_pmp_addr = PMPADDR0;
|
||||
riscv_instr_pkg::privileged_reg_t base_pmpcfg_addr = PMPCFG0;
|
||||
int pmp_id;
|
||||
foreach (pmp_cfg[i]) begin
|
||||
// TODO(udinator) condense this calculations if possible
|
||||
|
@ -251,15 +275,33 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
instr.push_back($sformatf("csrw 0x%0x, x%0d", base_pmp_addr + i, scratch_reg[0]));
|
||||
`uvm_info(`gfn, "Loaded the address of <main> section into pmpaddr0", UVM_LOW)
|
||||
end else begin
|
||||
// Add the offset to the base address to get the other pmpaddr values
|
||||
instr.push_back($sformatf("la x%0d, main", scratch_reg[0]));
|
||||
instr.push_back($sformatf("li x%0d, 0x%0x", scratch_reg[1], pmp_cfg[i].offset));
|
||||
instr.push_back($sformatf("add x%0d, x%0d, x%0d",
|
||||
scratch_reg[0], scratch_reg[0], scratch_reg[1]));
|
||||
instr.push_back($sformatf("srli x%0d, x%0d, 2", scratch_reg[0], scratch_reg[0]));
|
||||
instr.push_back($sformatf("csrw 0x%0x, x%0d", base_pmp_addr + i, scratch_reg[0]));
|
||||
`uvm_info(`gfn, $sformatf("Offset of pmp_addr_%d from pmpaddr0: 0x%0x",
|
||||
i, pmp_cfg[i].offset), UVM_LOW)
|
||||
// If an actual address has been set from the command line, use this address,
|
||||
// otherwise use the default offset+<main> address
|
||||
//
|
||||
// TODO(udinator) - The practice of passing in a max offset from the command line
|
||||
// is somewhat unintuitive, and is just an initial step. Eventually a max address
|
||||
// should be passed in from the command line and this routine do all of the
|
||||
// calculations to split the address range formed by [<main> : pmp_max_addr].
|
||||
// This will likely require a complex assembly routine - the code below is a very simple
|
||||
// first step towards this goal, allowing users to specify a PMP memory address
|
||||
// from the command line instead of having to calculate an offset themselves.
|
||||
if (pmp_cfg[i].addr != 0) begin
|
||||
instr.push_back($sformatf("li x%0d, 0x%0x", scratch_reg[0], pmp_cfg[i].addr));
|
||||
instr.push_back($sformatf("csrw 0x%0x, x%0d", base_pmp_addr + i, scratch_reg[0]));
|
||||
`uvm_info(`gfn,
|
||||
$sformatf("Address 0x%0x loaded into pmpaddr[%d] CSR", base_pmp_addr + i, i),
|
||||
UVM_LOW);
|
||||
end else begin
|
||||
// Add the offset to the base address to get the other pmpaddr values
|
||||
instr.push_back($sformatf("la x%0d, main", scratch_reg[0]));
|
||||
instr.push_back($sformatf("li x%0d, 0x%0x", scratch_reg[1], pmp_cfg[i].offset));
|
||||
instr.push_back($sformatf("add x%0d, x%0d, x%0d",
|
||||
scratch_reg[0], scratch_reg[0], scratch_reg[1]));
|
||||
instr.push_back($sformatf("srli x%0d, x%0d, 2", scratch_reg[0], scratch_reg[0]));
|
||||
instr.push_back($sformatf("csrw 0x%0x, x%0d", base_pmp_addr + i, scratch_reg[0]));
|
||||
`uvm_info(`gfn, $sformatf("Offset of pmp_addr_%d from pmpaddr0: 0x%0x",
|
||||
i, pmp_cfg[i].offset), UVM_LOW)
|
||||
end
|
||||
end
|
||||
// Now, check if we have to write to the appropriate pmpcfg CSR.
|
||||
// Short circuit if we reach the end of the list
|
||||
|
@ -280,4 +322,278 @@ class riscv_pmp_cfg extends uvm_object;
|
|||
end
|
||||
endfunction
|
||||
|
||||
// This function creates a special PMP exception routine that is generated within the
|
||||
// instr_fault, load_fault, and store_fault exception routines to prevent infinite loops.
|
||||
// This routine will first find the correct pmpcfg CSR that corresponds to the address that
|
||||
// caused the exception in the first place, and then will enable the appropriate access bit
|
||||
// (X for instruction faults, W for store faults, and R for load faults).
|
||||
//
|
||||
// Note: If a pmpcfg CSR is locked, it is unable to be written to until a full reset, so in this
|
||||
// case we will immediately jump to the <test_done> label if the faulting address matches to
|
||||
// this region, otherwise we'll keep looping through the remaining CSRs.
|
||||
//
|
||||
// TODO(udinator) : investigate switching branch targets to named labels instead of numbers
|
||||
// to better clarify where the multitude of jumps are actually going to.
|
||||
function void gen_pmp_exception_routine(riscv_reg_t scratch_reg[6],
|
||||
exception_cause_t fault_type,
|
||||
ref string instr[$]);
|
||||
// mscratch : loop counter
|
||||
// scratch_reg[0] : temporary storage
|
||||
// scratch_reg[1] : &pmpaddr[i]
|
||||
// scratch_reg[2] : &pmpcfg[i]
|
||||
// scratch_reg[3] : 8-bit configuration fields
|
||||
// scratch_reg[4] : 2-bit pmpcfg[i].A address matching mode
|
||||
// scratch_reg[5] : holds the previous pmpaddr[i] value (necessary for TOR matching)
|
||||
instr = {instr,
|
||||
//////////////////////////////////////////////////
|
||||
// Initialize loop counter and save to mscratch //
|
||||
//////////////////////////////////////////////////
|
||||
$sformatf("li x%0d, 0", scratch_reg[0]),
|
||||
$sformatf("csrw 0x%0x, x%0d", MSCRATCH, scratch_reg[0]),
|
||||
$sformatf("li x%0d, 0", scratch_reg[5]),
|
||||
////////////////////////////////////////////////////
|
||||
// calculate next pmpaddr and pmpcfg CSRs to read //
|
||||
////////////////////////////////////////////////////
|
||||
$sformatf("0: csrr x%0d, 0x%0x", scratch_reg[0], MSCRATCH),
|
||||
$sformatf("mv x%0d, x%0d", scratch_reg[4], scratch_reg[0])
|
||||
};
|
||||
// Generate a sequence of loads and branches that will compare the loop index to every
|
||||
// value within [0 : pmp_num_regions] to manually check which PMP CSRs to read from
|
||||
for (int i = 1; i < pmp_num_regions + 1; i++) begin
|
||||
int pmpaddr_addr = base_pmp_addr + i;
|
||||
int pmpcfg_addr = base_pmpcfg_addr + (i / cfg_per_csr);
|
||||
instr.push_back($sformatf("li x%0d, %0d", scratch_reg[4], i-1));
|
||||
instr.push_back($sformatf("beq x%0d, x%0d, %0df", scratch_reg[0], scratch_reg[4], i));
|
||||
end
|
||||
|
||||
// Generate the branch targets for the above sequence of loads and branches to actually
|
||||
// read from the pmpaddr and pmpcfg CSRs
|
||||
for (int i = 1; i < pmp_num_regions + 1; i++) begin
|
||||
int pmpaddr_addr = base_pmp_addr + i;
|
||||
int pmpcfg_addr = base_pmpcfg_addr + (i / cfg_per_csr);
|
||||
instr.push_back($sformatf("%0d: csrr x%0d, 0x%0x", i, scratch_reg[1], base_pmp_addr + i - 1));
|
||||
instr.push_back($sformatf("csrr x%0d, 0x%0x", scratch_reg[2], base_pmpcfg_addr + ((i-1)/4)));
|
||||
instr.push_back("j 17f");
|
||||
end
|
||||
|
||||
// Logic to store pmpaddr[i] and pmpcfg[i] and branch to a code section
|
||||
// based on pmpcfg[i].A (address matching mode)
|
||||
instr = {instr,
|
||||
////////////////////////////////////////////
|
||||
// get correct 8-bit configuration fields //
|
||||
////////////////////////////////////////////
|
||||
$sformatf("17: li x%0d, %0d", scratch_reg[3], cfg_per_csr),
|
||||
$sformatf("csrr x%0d, 0x%0x", scratch_reg[0], MSCRATCH),
|
||||
// calculate offset to left-shift pmpcfg[i] (scratch_reg[2]),
|
||||
// use scratch_reg[4] as temporary storage
|
||||
//
|
||||
// First calculate (loop_counter % cfg_per_csr)
|
||||
$sformatf("slli x%0d, x%0d, %0d", scratch_reg[0], scratch_reg[0],
|
||||
XLEN - $clog2(cfg_per_csr)),
|
||||
$sformatf("srli x%0d, x%0d, %0d", scratch_reg[0], scratch_reg[0],
|
||||
XLEN - $clog2(cfg_per_csr)),
|
||||
// Calculate (cfg_per_csr - modded_loop_counter - 1) to determine how many 8bit slots to
|
||||
// the left this needs to be shifted
|
||||
$sformatf("sub x%0d, x%0d, x%0d", scratch_reg[4], scratch_reg[3], scratch_reg[0]),
|
||||
$sformatf("addi x%0d, x%0d, %0d", scratch_reg[4], scratch_reg[4], -1),
|
||||
// Multiply this "slot offset" by 8 to get the actual number of bits it should
|
||||
// be leftshifted.
|
||||
$sformatf("slli x%0d, x%0d, 3", scratch_reg[4], scratch_reg[4]),
|
||||
// Perform the leftshifting operation
|
||||
$sformatf("sll x%0d, x%0d, x%0d", scratch_reg[3], scratch_reg[2], scratch_reg[4]),
|
||||
// Add 8*modded_loop_counter to 8*(cfg_per_csr - modded_loop_counter - 1)
|
||||
// stored in scratch_reg[4] to get "slot offset" for the pending rightshift operation.
|
||||
$sformatf("slli x%0d, x%0d, 3", scratch_reg[0], scratch_reg[0]),
|
||||
$sformatf("add x%0d, x%0d, x%0d", scratch_reg[4], scratch_reg[4], scratch_reg[0]),
|
||||
// Perform the rightshift operation
|
||||
$sformatf("srl x%0d, x%0d, x%0d", scratch_reg[3], scratch_reg[3], scratch_reg[4]),
|
||||
///////////////////////////
|
||||
// get pmpcfg[i].A field //
|
||||
///////////////////////////
|
||||
// pmpcfg[i].A will be bits [4:3] of the 8-bit configuration entry
|
||||
$sformatf("slli x%0d, x%0d, %0d", scratch_reg[4], scratch_reg[3], XLEN - 5),
|
||||
$sformatf("srli x%0d, x%0d, %0d", scratch_reg[4], scratch_reg[4], XLEN - 2),
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// based on address match mode, branch to appropriate "handler" //
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// pmpcfg[i].A == OFF
|
||||
$sformatf("beqz x%0d, 20f", scratch_reg[4]),
|
||||
// pmpcfg[i].A == TOR
|
||||
// scratch_reg[5] will contain pmpaddr[i-1]
|
||||
$sformatf("li x%0d, 1", scratch_reg[0]),
|
||||
$sformatf("beq x%0d, x%0d, 21f", scratch_reg[4], scratch_reg[0]),
|
||||
// pmpcfg[i].A == NA4
|
||||
$sformatf("li x%0d, 2", scratch_reg[0]),
|
||||
$sformatf("beq x%0d, x%0d, 25f", scratch_reg[4], scratch_reg[0]),
|
||||
// pmpcfg[i].A == NAPOT
|
||||
$sformatf("li x%0d, 3", scratch_reg[0]),
|
||||
$sformatf("beq x%0d, x%0d, 27f", scratch_reg[4], scratch_reg[0]),
|
||||
// Error check, if no address modes match, something has gone wrong
|
||||
$sformatf("j test_done"),
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// increment loop counter and branch back to beginning of loop //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
$sformatf("18: csrr x%0d, 0x%0x", scratch_reg[0], MSCRATCH),
|
||||
// load pmpaddr[i] into scratch_reg[5] to store for iteration [i+1]
|
||||
$sformatf("mv x%0d, x%0d", scratch_reg[5], scratch_reg[1]),
|
||||
// increment loop counter by 1
|
||||
$sformatf("addi x%0d, x%0d, 1", scratch_reg[0], scratch_reg[0]),
|
||||
// store loop counter to MSCRATCH
|
||||
$sformatf("csrw 0x%0x, x%0d", MSCRATCH, scratch_reg[0]),
|
||||
// load number of pmp regions - loop limit
|
||||
$sformatf("li x%0d, %0d", scratch_reg[1], pmp_num_regions),
|
||||
// if counter < pmp_num_regions => branch to beginning of loop
|
||||
$sformatf("ble x%0d, x%0d, 19f", scratch_reg[1], scratch_reg[0]),
|
||||
$sformatf("j 0b"),
|
||||
// if counter >= pmp_num_regions, jump to the end of the handler, as in M-mode,
|
||||
// no PMP match means the access succeeds
|
||||
$sformatf("19: j 34f")
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// Sub-sections for all address matching modes //
|
||||
/////////////////////////////////////////////////
|
||||
// scratch_reg[0] : temporary storage
|
||||
// scratch_reg[1] : pmpaddr[i]
|
||||
// scratch_reg[2] : pmpcfg[i]
|
||||
// scratch_reg[3] : 8-bit configuration fields
|
||||
// scratch_reg[4] : temporary storage
|
||||
// scratch_reg[5] : pmpaddr[i-1]
|
||||
|
||||
// Sub-section to deal with address matching mode OFF.
|
||||
// If entry is OFF, simply continue looping through other PMP CSR.
|
||||
instr = {instr, "20: j 18b"};
|
||||
|
||||
// Sub-section to handle address matching mode TOR.
|
||||
instr = {instr,
|
||||
|
||||
$sformatf("21: csrr x%0d, 0x%0x", scratch_reg[0], MSCRATCH),
|
||||
$sformatf("csrr x%0d, 0x%0x", scratch_reg[4], MTVAL),
|
||||
$sformatf("srli x%0d, x%0d, 2", scratch_reg[4], scratch_reg[4]),
|
||||
// If loop_counter==0, compare fault_addr to 0
|
||||
$sformatf("bnez x%0d, 22f", scratch_reg[0]),
|
||||
// If fault_addr < 0 : continue looping
|
||||
$sformatf("bltz x%0d, 18b", scratch_reg[4]),
|
||||
$sformatf("j 23f"),
|
||||
// If fault_addr < pmpaddr[i-1] : continue looping
|
||||
$sformatf("22: bgtu x%0d, x%0d, 18b", scratch_reg[5], scratch_reg[4]),
|
||||
// If fault_addr >= pmpaddr[i] : continue looping
|
||||
$sformatf("23: bleu x%0d, x%0d, 18b", scratch_reg[1], scratch_reg[4]),
|
||||
// If we get here, there is a TOR match, if the entry is locked jump to
|
||||
// <test_done>, otherwise modify access bits and return
|
||||
$sformatf("andi x%0d, x%0d, 128", scratch_reg[4], scratch_reg[3]),
|
||||
$sformatf("beqz x%0d, 24f", scratch_reg[4]),
|
||||
$sformatf("j test_done"),
|
||||
// TODO : update with correct label
|
||||
$sformatf("24: j 29f")
|
||||
};
|
||||
|
||||
// Sub-section to handle address matching mode NA4.
|
||||
// TODO(udinator) : add rv64 support
|
||||
instr = {instr,
|
||||
$sformatf("25: csrr x%0d, 0x%0x", scratch_reg[0], MTVAL),
|
||||
$sformatf("srli x%0d, x%0d, 2", scratch_reg[0], scratch_reg[0]),
|
||||
// Zero out pmpaddr[i][31:30]
|
||||
$sformatf("slli x%0d, x%0d, 2", scratch_reg[4], scratch_reg[1]),
|
||||
$sformatf("srli x%0d, x%0d, 2", scratch_reg[4], scratch_reg[4]),
|
||||
// If fault_addr[31:2] != pmpaddr[i][29:0] => there is a mismatch,
|
||||
// so continue looping
|
||||
$sformatf("bne x%0d, x%0d, 18b", scratch_reg[0], scratch_reg[4]),
|
||||
// If we get here, there is an NA4 address match, jump to <test_done> if the
|
||||
// entry is locked, otherwise modify access bits
|
||||
$sformatf("andi x%0d, x%0d, 128", scratch_reg[4], scratch_reg[3]),
|
||||
$sformatf("beqz x%0d, 26f", scratch_reg[4]),
|
||||
$sformatf("j test_done"),
|
||||
// TODO : update with correct label
|
||||
$sformatf("26: j 29f")
|
||||
};
|
||||
|
||||
// Sub-section to handle address matching mode NAPOT.
|
||||
instr = {instr,
|
||||
$sformatf("27: csrr x%0d, 0x%0x", scratch_reg[0], MTVAL),
|
||||
// get fault_addr[31:2]
|
||||
$sformatf("srli x%0d, x%0d, 2", scratch_reg[0], scratch_reg[0]),
|
||||
// mask the bottom pmp_granularity bits of fault_addr
|
||||
$sformatf("srli x%0d, x%0d, %0d", scratch_reg[0], scratch_reg[0], pmp_granularity),
|
||||
$sformatf("slli x%0d, x%0d, %0d", scratch_reg[0], scratch_reg[0], pmp_granularity),
|
||||
// get pmpaddr[i][29:0]
|
||||
$sformatf("slli x%0d, x%0d, 2", scratch_reg[4], scratch_reg[1]),
|
||||
$sformatf("srli x%0d, x%0d, 2", scratch_reg[4], scratch_reg[4]),
|
||||
// mask the bottom pmp_granularity bits of pmpaddr[i]
|
||||
$sformatf("srli x%0d, x%0d, %0d", scratch_reg[4], scratch_reg[4], pmp_granularity),
|
||||
$sformatf("slli x%0d, x%0d, %0d", scratch_reg[4], scratch_reg[4], pmp_granularity),
|
||||
// If masked_fault_addr != masked_pmpaddr[i] : mismatch, so continue looping
|
||||
$sformatf("bne x%0d, x%0d, 18b", scratch_reg[0], scratch_reg[4]),
|
||||
// If we get here there is an NAPOT address match, jump to <test_done> if
|
||||
// the entry is locked, otherwise modify access bits
|
||||
$sformatf("andi x%0d, x%0d, 128", scratch_reg[4], scratch_reg[3]),
|
||||
$sformatf("beqz x%0d, 29f", scratch_reg[4]),
|
||||
$sformatf("j test_done"),
|
||||
// TODO : update with correct label
|
||||
$sformatf("28: j 29f")
|
||||
};
|
||||
|
||||
// This case statement creates a bitmask that enables the correct access permissions
|
||||
// and ORs it with the 8-bit configuration fields.
|
||||
case (fault_type)
|
||||
INSTRUCTION_ACCESS_FAULT: begin
|
||||
instr.push_back($sformatf("29: ori x%0d, x%0d, 4", scratch_reg[3], scratch_reg[3]));
|
||||
end
|
||||
STORE_AMO_ACCESS_FAULT: begin
|
||||
// The combination of W:1 and R:0 is reserved, so if we are enabling write
|
||||
// permissions, also enable read permissions to adhere to the spec.
|
||||
instr.push_back($sformatf("29: ori x%0d, x%0d, 3", scratch_reg[3], scratch_reg[3]));
|
||||
end
|
||||
LOAD_ACCESS_FAULT: begin
|
||||
instr.push_back($sformatf("29: ori x%0d, x%0d, 1", scratch_reg[3], scratch_reg[3]));
|
||||
end
|
||||
endcase
|
||||
instr = {instr,
|
||||
$sformatf("csrr x%0d, 0x%0x", scratch_reg[0], MSCRATCH),
|
||||
// Calculate (loop_counter % cfg_per_csr) to find the index of the correct
|
||||
// entry in pmpcfg[i].
|
||||
//
|
||||
// Calculate XLEN - $clog2(cfg_per_csr) to give how many low order bits
|
||||
// of loop_counter we need to keep around
|
||||
$sformatf("li x%0d, %0d", scratch_reg[4], XLEN - $clog2(cfg_per_csr)),
|
||||
// Now leftshift and rightshift loop_counter by this amount to clear all the upper
|
||||
// bits
|
||||
$sformatf("sll x%0d, x%0d, x%0d", scratch_reg[0], scratch_reg[0], scratch_reg[4]),
|
||||
$sformatf("srl x%0d, x%0d, x%0d", scratch_reg[0], scratch_reg[0], scratch_reg[4]),
|
||||
// Multiply the index by 8 to get the shift amount.
|
||||
$sformatf("slli x%0d, x%0d, 3", scratch_reg[4], scratch_reg[0]),
|
||||
// Shift the updated configuration byte to the proper alignment
|
||||
$sformatf("sll x%0d, x%0d, x%0d", scratch_reg[3], scratch_reg[3], scratch_reg[4]),
|
||||
// OR pmpcfg[i] with the updated configuration byte
|
||||
$sformatf("or x%0d, x%0d, x%0d", scratch_reg[2], scratch_reg[2], scratch_reg[3]),
|
||||
// Divide the loop counter by cfg_per_csr to determine which pmpcfg CSR to write to.
|
||||
$sformatf("csrr x%0d, 0x%0x", scratch_reg[0], MSCRATCH),
|
||||
$sformatf("srli x%0d, x%0d, %0d", scratch_reg[0], scratch_reg[0], $clog2(cfg_per_csr)),
|
||||
// Write the updated pmpcfg[i] to the CSR bank and exit the handler.
|
||||
//
|
||||
// Don't touch scratch_reg[2], as it contains the updated pmpcfg[i] to be written.
|
||||
// All other scratch_reg[*] can be used.
|
||||
// scratch_reg[0] contains the index of the correct pmpcfg CSR.
|
||||
// We simply check the index and then write to the correct pmpcfg CSR based on its value.
|
||||
$sformatf("beqz x%0d, 30f", scratch_reg[0]),
|
||||
$sformatf("li x%0d, 1", scratch_reg[4]),
|
||||
$sformatf("beq x%0d, x%0d, 31f", scratch_reg[0], scratch_reg[4]),
|
||||
$sformatf("li x%0d, 2", scratch_reg[4]),
|
||||
$sformatf("beq x%0d, x%0d, 32f", scratch_reg[0], scratch_reg[4]),
|
||||
$sformatf("li x%0d, 3", scratch_reg[4]),
|
||||
$sformatf("beq x%0d, x%0d, 33f", scratch_reg[0], scratch_reg[4]),
|
||||
$sformatf("30: csrw 0x%0x, x%0d", PMPCFG0, scratch_reg[2]),
|
||||
$sformatf("j 34f"),
|
||||
$sformatf("31: csrw 0x%0x, x%0d", PMPCFG1, scratch_reg[2]),
|
||||
$sformatf("j 34f"),
|
||||
$sformatf("32: csrw 0x%0x, x%0d", PMPCFG2, scratch_reg[2]),
|
||||
$sformatf("j 34f"),
|
||||
$sformatf("33: csrw 0x%0x, x%0d", PMPCFG3, scratch_reg[2]),
|
||||
// End the pmp handler with a labeled nop instruction, this provides a branch target
|
||||
// for the internal routine after it has "fixed" the pmp configuration CSR.
|
||||
$sformatf("34: nop")
|
||||
};
|
||||
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
|
22
vendor/google_riscv-dv/target/rv64imcb/riscvOVPsim.ic
vendored
Normal file
22
vendor/google_riscv-dv/target/rv64imcb/riscvOVPsim.ic
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# riscOVPsim configuration file converted from YAML
|
||||
--variant RV64I
|
||||
--override riscvOVPsim/cpu/add_Extensions=MCB
|
||||
--override riscvOVPsim/cpu/misa_MXL=2
|
||||
--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0
|
||||
--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0
|
||||
--override riscvOVPsim/cpu/unaligned=T
|
||||
--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0
|
||||
--override riscvOVPsim/cpu/user_version=2.3
|
||||
--override riscvOVPsim/cpu/priv_version=1.11
|
||||
--override riscvOVPsim/cpu/mvendorid=0
|
||||
--override riscvOVPsim/cpu/marchid=0
|
||||
--override riscvOVPsim/cpu/mimpid=0
|
||||
--override riscvOVPsim/cpu/mhartid=0
|
||||
--override riscvOVPsim/cpu/cycle_undefined=F
|
||||
--override riscvOVPsim/cpu/instret_undefined=F
|
||||
--override riscvOVPsim/cpu/time_undefined=T
|
||||
--override riscvOVPsim/cpu/reset_address=0x80000000
|
||||
--override riscvOVPsim/cpu/simulateexceptions=T
|
||||
--override riscvOVPsim/cpu/defaultsemihost=F
|
||||
--override riscvOVPsim/cpu/wfi_is_nop=T
|
||||
--exitonsymbol _exit
|
118
vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
vendored
Normal file
118
vendor/google_riscv-dv/target/rv64imcb/riscv_core_setting.sv
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Processor feature configuration
|
||||
//-----------------------------------------------------------------------------
|
||||
// XLEN
|
||||
parameter int XLEN = 64;
|
||||
|
||||
// Parameter for SATP mode, set to BARE if address translation is not supported
|
||||
parameter satp_mode_t SATP_MODE = BARE;
|
||||
|
||||
// Supported Privileged mode
|
||||
privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE};
|
||||
|
||||
// Unsupported instructions
|
||||
riscv_instr_name_t unsupported_instr[];
|
||||
|
||||
// ISA supported by the processor
|
||||
riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C, RV32B, RV64I, RV64M, RV64C, RV64B};
|
||||
|
||||
// Interrupt mode support
|
||||
mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED};
|
||||
|
||||
// The number of interrupt vectors to be generated, only used if VECTORED interrupt mode is
|
||||
// supported
|
||||
int max_interrupt_vector_num = 16;
|
||||
|
||||
// Physical memory protection support
|
||||
bit support_pmp = 0;
|
||||
|
||||
// Debug mode support
|
||||
bit support_debug_mode = 0;
|
||||
|
||||
// Support delegate trap to user mode
|
||||
bit support_umode_trap = 0;
|
||||
|
||||
// Support sfence.vma instruction
|
||||
bit support_sfence = 0;
|
||||
|
||||
// Support unaligned load/store
|
||||
bit support_unaligned_load_store = 1'b1;
|
||||
|
||||
// Parameter for vector extension
|
||||
parameter int VECTOR_EXTENSION_ENABLE = 0;
|
||||
parameter int VLEN = 512;
|
||||
parameter int ELEN = 64;
|
||||
parameter int SLEN = 64;
|
||||
|
||||
// Number of harts
|
||||
parameter int NUM_HARTS = 1;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Previleged CSR implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Implemented previlieged CSR list
|
||||
`ifdef DSIM
|
||||
privileged_reg_t implemented_csr[] = {
|
||||
`else
|
||||
const privileged_reg_t implemented_csr[] = {
|
||||
`endif
|
||||
// Machine mode mode CSR
|
||||
MVENDORID, // Vendor ID
|
||||
MARCHID, // Architecture ID
|
||||
MIMPID, // Implementation ID
|
||||
MHARTID, // Hardware thread ID
|
||||
MSTATUS, // Machine status
|
||||
MISA, // ISA and extensions
|
||||
MIE, // Machine interrupt-enable register
|
||||
MTVEC, // Machine trap-handler base address
|
||||
MCOUNTEREN, // Machine counter enable
|
||||
MSCRATCH, // Scratch register for machine trap handlers
|
||||
MEPC, // Machine exception program counter
|
||||
MCAUSE, // Machine trap cause
|
||||
MTVAL, // Machine bad address or instruction
|
||||
MIP // Machine interrupt pending
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Supported interrupt/exception setting, used for functional coverage
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
`ifdef DSIM
|
||||
interrupt_cause_t implemented_interrupt[] = {
|
||||
`else
|
||||
const interrupt_cause_t implemented_interrupt[] = {
|
||||
`endif
|
||||
M_SOFTWARE_INTR,
|
||||
M_TIMER_INTR,
|
||||
M_EXTERNAL_INTR
|
||||
};
|
||||
|
||||
`ifdef DSIM
|
||||
exception_cause_t implemented_exception[] = {
|
||||
`else
|
||||
const exception_cause_t implemented_exception[] = {
|
||||
`endif
|
||||
INSTRUCTION_ACCESS_FAULT,
|
||||
ILLEGAL_INSTRUCTION,
|
||||
BREAKPOINT,
|
||||
LOAD_ADDRESS_MISALIGNED,
|
||||
LOAD_ACCESS_FAULT,
|
||||
ECALL_MMODE
|
||||
};
|
33
vendor/google_riscv-dv/target/rv64imcb/testlist.yaml
vendored
Normal file
33
vendor/google_riscv-dv/target/rv64imcb/testlist.yaml
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Copyright Google LLC
|
||||
#
|
||||
# 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.
|
||||
|
||||
# ================================================================================
|
||||
# Regression test list format
|
||||
# --------------------------------------------------------------------------------
|
||||
# test : Assembly test name
|
||||
# description : Description of this test
|
||||
# gen_opts : Instruction generator options
|
||||
# iterations : Number of iterations of this test
|
||||
# no_iss : Enable/disable ISS simulator (Optional)
|
||||
# gen_test : Test name used by the instruction generator
|
||||
# asm_tests : Path to directed, hand-coded assembly test file or directory
|
||||
# rtl_test : RTL simulation test name
|
||||
# cmp_opts : Compile options passed to the instruction generator
|
||||
# sim_opts : Simulation options passed to the instruction generator
|
||||
# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional)
|
||||
# compare_opts : Options for the RTL & ISS trace comparison
|
||||
# gcc_opts : gcc compile options
|
||||
# --------------------------------------------------------------------------------
|
||||
|
||||
- import: <riscv_dv_root>/target/rv32imcb/testlist.yaml
|
|
@ -138,7 +138,7 @@ class riscv_instr_cov_test extends uvm_test;
|
|||
if (riscv_instr::instr_template.exists(instr_name)) begin
|
||||
instr.copy(riscv_instr::instr_template[instr_name]);
|
||||
if (instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C,
|
||||
RV32F}) begin
|
||||
RV32F, RV32B, RV64B}) begin
|
||||
assign_trace_info_to_instr(instr);
|
||||
end
|
||||
instr.pre_sample();
|
||||
|
@ -173,7 +173,11 @@ class riscv_instr_cov_test extends uvm_test;
|
|||
I_FORMAT: begin
|
||||
// TODO, support I_FORMAT floating point later
|
||||
if (instr.group == RV32F) return;
|
||||
`DV_CHECK_FATAL(operands.size() == 3, trace["instr_str"])
|
||||
if (instr.instr_name inside {FSRI, FSRIW}) begin
|
||||
`DV_CHECK_FATAL(operands.size() == 4, trace["instr_str"])
|
||||
end else begin
|
||||
`DV_CHECK_FATAL(operands.size() == 3, trace["instr_str"])
|
||||
end
|
||||
if(instr.category == LOAD) begin
|
||||
// load rd, imm(rs1)
|
||||
instr.rs1 = get_gpr(operands[2]);
|
||||
|
@ -187,6 +191,13 @@ class riscv_instr_cov_test extends uvm_test;
|
|||
end else begin
|
||||
get_val(operands[1], instr.csr);
|
||||
end
|
||||
end else if (instr.instr_name inside {FSRI, FSRIW}) begin
|
||||
// fsri rd, rs1, rs3, imm
|
||||
instr.rs1 = get_gpr(operands[1]);
|
||||
instr.rs1_value = get_gpr_state(operands[1]);
|
||||
instr.rs3 = get_gpr(operands[2]);
|
||||
instr.rs3_value = get_gpr_state(operands[2]);
|
||||
get_val(operands[3], instr.imm);
|
||||
end else begin
|
||||
// addi rd, rs1, imm
|
||||
instr.rs1 = get_gpr(operands[1]);
|
||||
|
@ -215,8 +226,12 @@ class riscv_instr_cov_test extends uvm_test;
|
|||
end
|
||||
end
|
||||
R_FORMAT: begin
|
||||
if (!instr.instr_name inside {FCLASS_S, FCLASS_D}) `DV_CHECK_FATAL(operands.size() == 3)
|
||||
else `DV_CHECK_FATAL(operands.size() == 2)
|
||||
if ((instr.has_rs2 || instr.category == CSR) &&
|
||||
!(instr.instr_name inside {FCLASS_S, FCLASS_D})) begin
|
||||
`DV_CHECK_FATAL(operands.size() == 3)
|
||||
end else begin
|
||||
`DV_CHECK_FATAL(operands.size() == 2)
|
||||
end
|
||||
if(instr.category == CSR) begin
|
||||
// csrrw rd, csr, rs1
|
||||
if (preg_enum::from_name(operands[1].toupper(), preg)) begin
|
||||
|
@ -240,18 +255,23 @@ class riscv_instr_cov_test extends uvm_test;
|
|||
// add rd, rs1, rs2
|
||||
instr.rs1 = get_gpr(operands[1]);
|
||||
instr.rs1_value = get_gpr_state(operands[1]);
|
||||
instr.rs2 = get_gpr(operands[2]);
|
||||
instr.rs2_value = get_gpr_state(operands[2]);
|
||||
if (instr.has_rs2) begin
|
||||
instr.rs2 = get_gpr(operands[2]);
|
||||
instr.rs2_value = get_gpr_state(operands[2]);
|
||||
end
|
||||
end
|
||||
end
|
||||
R4_FORMAT: begin
|
||||
`DV_CHECK_FATAL(operands.size() == 4)
|
||||
instr.fs1 = get_fpr(operands[1]);
|
||||
instr.fs1_value = get_gpr_state(operands[1]);
|
||||
instr.fs2 = get_fpr(operands[2]);
|
||||
instr.fs2_value = get_gpr_state(operands[2]);
|
||||
instr.fs3 = get_fpr(operands[3]);
|
||||
instr.fs3_value = get_gpr_state(operands[3]);
|
||||
update_instr_reg_by_abi_name(operands[1],
|
||||
instr.rs1, instr.rs1_value,
|
||||
instr.fs1, instr.fs1_value);
|
||||
update_instr_reg_by_abi_name(operands[2],
|
||||
instr.rs2, instr.rs2_value,
|
||||
instr.fs2, instr.fs2_value);
|
||||
update_instr_reg_by_abi_name(operands[3],
|
||||
instr.rs3, instr.rs3_value,
|
||||
instr.fs3, instr.fs3_value);
|
||||
end
|
||||
CI_FORMAT, CIW_FORMAT: begin
|
||||
if (instr.instr_name == C_ADDI16SP) begin
|
||||
|
|
|
@ -29,7 +29,7 @@ class riscv_rand_instr_test extends riscv_instr_base_test;
|
|||
endfunction
|
||||
|
||||
virtual function void apply_directed_instr();
|
||||
// Mix below directed instructino streams with the random instructions
|
||||
// Mix below directed instruction streams with the random instructions
|
||||
asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 4);
|
||||
asm_gen.add_directed_instr_stream("riscv_loop_instr", 3);
|
||||
asm_gen.add_directed_instr_stream("riscv_jal_instr", 4);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue