Update google_riscv-dv to google/riscv-dv@6344e95 (#673)

Update code from upstream repository https://github.com/google/riscv-
dv to revision 6344e951fef22b383551a85365ebb7d6aa74eb34

* fix incorrect initialization routine (Udi Jonnalagadda)
* Add coverage for single precision floating (Part 1) (google/riscv-
  dv#488) (weicaiyang)
* Add load/store shared memory test (google/riscv-dv#508) (taoliug)
* Fix hart id assignment for load/store instruction stream
  (google/riscv-dv#507) (taoliug)

Signed-off-by: Udi <udij@google.com>
This commit is contained in:
udinator 2020-03-09 15:53:39 -07:00 committed by GitHub
parent 753e76549d
commit 19173290e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 266 additions and 21 deletions

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
rev: 4583049cc2b3469ba9dea56b5e2d75809a89d8f3
rev: 6344e951fef22b383551a85365ebb7d6aa74eb34
}
}

View file

@ -386,10 +386,6 @@ class riscv_asm_program_gen extends uvm_object;
// Init stack pointer to point to the end of the user stack
str = {indent, $sformatf("la x%0d, %0suser_stack_end", cfg.sp, hart_prefix(hart))};
instr_stream.push_back(str);
if (support_pmp) begin
str = {indent, "j main"};
instr_stream.push_back(str);
end
if (cfg.enable_floating_point) begin
init_floating_point_gpr();
end
@ -398,6 +394,10 @@ class riscv_asm_program_gen extends uvm_object;
end
core_is_initialized();
gen_dummy_csr_write(); // TODO add a way to disable xStatus read
if (support_pmp) begin
str = {indent, "j main"};
instr_stream.push_back(str);
end
endfunction
// Setup MISA based on supported extensions

View file

@ -90,7 +90,7 @@
`INSTR_BODY(instr_n, instr_format, instr_category, instr_group, imm_tp)
// Vector arithmetic instruction
`define DEFINE_VA_INSTR(instr_n, instr_format, instr_category, instr_group, vav = {}, imm_tp = IMM) \
`define DEFINE_VA_INSTR(instr_n, instr_format, instr_category, instr_group, vav = {}, imm_tp = IMM)\
class riscv_``instr_n``_instr extends riscv_vector_instr; \
`VA_INSTR_BODY(instr_n, instr_format, instr_category, instr_group, vav, imm_tp)

View file

@ -44,13 +44,16 @@ endclass
class riscv_mem_access_stream extends riscv_directed_instr_stream;
int max_data_page_id;
bit load_store_shared_memory;
mem_region_t data_page[$];
`uvm_object_utils(riscv_mem_access_stream)
`uvm_object_new
function void pre_randomize();
if(kernel_mode) begin
if (load_store_shared_memory) begin
data_page = cfg.amo_region;
end else if(kernel_mode) begin
data_page = cfg.s_mem_region;
end else begin
data_page = cfg.mem_region;
@ -64,11 +67,14 @@ class riscv_mem_access_stream extends riscv_directed_instr_stream;
la_instr = riscv_pseudo_instr::type_id::create("la_instr");
la_instr.pseudo_instr_name = LA;
la_instr.rd = gpr;
if(kernel_mode) begin
la_instr.imm_str = $sformatf("%0s%s+%0d",
if (load_store_shared_memory) begin
la_instr.imm_str = $sformatf("%0s+%0d", cfg.amo_region[id].name, base);
end else if(kernel_mode) begin
la_instr.imm_str = $sformatf("%0s%0s+%0d",
hart_prefix(hart), cfg.s_mem_region[id].name, base);
end else begin
la_instr.imm_str = $sformatf("%0s%s+%0d",
la_instr.imm_str = $sformatf("%0s%0s+%0d",
hart_prefix(hart), cfg.mem_region[id].name, base);
end
instr_list.push_front(la_instr);
@ -187,8 +193,7 @@ class riscv_jump_instr extends riscv_directed_instr_stream;
end
jump.has_label = 1'b1;
jump.label = "1";
jump.comment = $sformatf("%s jump %0s -> %0s",
hart_prefix(hart), label, target_program_label);
jump.comment = $sformatf("jump %0s -> %0s", label, target_program_label);
branch.imm_str = "1f";
branch.comment = "branch to jump instr";
branch.branch_assigned = 1'b1;

View file

@ -23,8 +23,13 @@ class riscv_instr_cov_item extends riscv_instr;
rand bit [XLEN-1:0] rs1_value;
rand bit [XLEN-1:0] rs2_value;
rand bit [XLEN-1:0] rd_value;
rand riscv_fpr_t fs1;
rand riscv_fpr_t fs2;
rand riscv_fpr_t fs3;
rand riscv_fpr_t fd;
rand bit [XLEN-1:0] fs1_value;
rand bit [XLEN-1:0] fs2_value;
rand bit [XLEN-1:0] fs3_value;
rand bit [XLEN-1:0] fd_value;
bit [31:0] binary;
bit [XLEN-1:0] pc;
@ -37,8 +42,12 @@ 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 fs1_sign;
operand_sign_e fs2_sign;
operand_sign_e fs3_sign;
operand_sign_e imm_sign;
operand_sign_e rd_sign;
operand_sign_e fd_sign;
hazard_e gpr_hazard;
hazard_e lsu_hazard;
special_val_e rs1_special_val;
@ -59,6 +68,10 @@ class riscv_instr_cov_item extends riscv_instr;
rs1_sign = get_operand_sign(rs1_value);
rs2_sign = get_operand_sign(rs2_value);
rd_sign = get_operand_sign(rd_value);
fs1_sign = get_operand_sign(fs1_value);
fs2_sign = get_operand_sign(fs2_value);
fs3_sign = get_operand_sign(fs2_value);
fd_sign = get_operand_sign(fd_value);
imm_sign = get_imm_sign(imm);
rs1_special_val = get_operand_special_val(rs1_value);
rd_special_val = get_operand_special_val(rd_value);

View file

@ -216,6 +216,47 @@
`INSTR_CG_BEGIN(INSTR_NAME) \
cp_imm_sign : coverpoint instr.imm_sign;
// TODO, will handle special value later
// single-precision floating point special values coverpoint
`define FP_SPECIAL_VALUES_CP(VAR, NAME) \
cp_fp_special_values_on_``NAME`` : coverpoint VAR { \
bins infinity[] = {32'h7f80_0000, 32'hff80_0000}; \
bins largest[] = {32'h7f7f_ffff, 32'hff7f_ffff}; \
bins zeros[] = {32'h0000_0000, 32'h1000_0000}; \
bins NaN[] = {32'h7fc0_0000, 32'h7f80_0000}; \
}
`define FP_R_INSTR_CG_BEGIN(INSTR_NAME) \
`INSTR_CG_BEGIN(INSTR_NAME) \
cp_fs1 : coverpoint instr.fs1; \
cp_fs2 : coverpoint instr.fs2; \
cp_fd : coverpoint instr.fd; \
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_fs2_sign : coverpoint instr.fs2_sign; \
cp_fd_sign : coverpoint instr.fd_sign; \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`define FP_R4_INSTR_CG_BEGIN(INSTR_NAME) \
`INSTR_CG_BEGIN(INSTR_NAME) \
cp_fs1 : coverpoint instr.fs1; \
cp_fs2 : coverpoint instr.fs2; \
cp_fs3 : coverpoint instr.fs3; \
cp_fd : coverpoint instr.fd; \
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_fs2_sign : coverpoint instr.fs2_sign; \
cp_fs3_sign : coverpoint instr.fs3_sign; \
cp_fd_sign : coverpoint instr.fd_sign; \
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fs3_sign, cp_fd_sign; \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`define FSQRT_INSTR_CG_BEGIN(INSTR_NAME) \
`INSTR_CG_BEGIN(INSTR_NAME) \
cp_fs1 : coverpoint instr.fs1; \
cp_fd : coverpoint instr.fd; \
cp_fs1_sign : coverpoint instr.fs1_sign; \
cp_fd_sign : coverpoint instr.fd_sign; \
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;) \
`define CG_END endgroup
`define CG_SELECTOR_BEGIN(CG_ISA) \
@ -446,6 +487,73 @@ class riscv_instr_cover_group;
cp_ras : cross cp_rs1_link, cp_rd_link;
`CG_END
// floating instructions
`INSTR_CG_BEGIN(flw)
cp_rs1 : coverpoint instr.rs1 {
`DV(ignore_bins zero = {ZERO};)
}
cp_fd : coverpoint instr.fd;
cp_imm_sign : coverpoint instr.imm_sign;
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard;)
`DV(cp_lsu_hazard : coverpoint instr.lsu_hazard {
bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
})
`CG_END
`INSTR_CG_BEGIN(fsw)
cp_rs1 : coverpoint instr.rs1 {
`DV(ignore_bins zero = {ZERO};)
}
cp_fs2 : coverpoint instr.fs2;
cp_imm_sign : coverpoint instr.imm_sign;
`DV(cp_gpr_hazard : coverpoint instr.gpr_hazard {
bins valid_hazard[] = {NO_HAZARD, RAW_HAZARD};
})
`DV(cp_lsu_hazard : coverpoint instr.lsu_hazard {
bins valid_hazard[] = {NO_HAZARD, WAR_HAZARD, WAW_HAZARD};
})
`CG_END
`FP_R_INSTR_CG_BEGIN(fadd_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fsub_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign, cp_fd_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fmul_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fdiv_s)
cp_div_result: coverpoint instr.div_result;
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FSQRT_INSTR_CG_BEGIN(fsqrt_s)
`CG_END
`FP_R_INSTR_CG_BEGIN(fmin_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R_INSTR_CG_BEGIN(fmax_s)
cp_sign_cross: cross cp_fs1_sign, cp_fs2_sign;
`CG_END
`FP_R4_INSTR_CG_BEGIN(fmadd_s)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fnmadd_s)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fmsub_s)
`CG_END
`FP_R4_INSTR_CG_BEGIN(fnmsub_s)
`CG_END
// CSR instructions
`CSR_INSTR_CG_BEGIN(csrrw)
cp_rs1 : coverpoint instr.rs1;
@ -901,6 +1009,13 @@ class riscv_instr_cover_group;
cp_mpp : coverpoint val[12:11];
endgroup
covergroup fcsr_cg with function sample(bit [XLEN-1:0] val);
cp_fflags : coverpoint val[4:0];
cp_frm : coverpoint val[7:5] {
ignore_bins invalid = {3'b101, 3'b110};
}
endgroup
`VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_add.sv")
function new(riscv_instr_gen_config cfg);
@ -1089,6 +1204,22 @@ class riscv_instr_cover_group;
c_addw_cg = new();
`CG_SELECTOR_END
`CG_SELECTOR_BEGIN(RV32F)
flw_cg = new();
fsw_cg = new();
fadd_s_cg = new();
fsub_s_cg = new();
fmul_s_cg = new();
fdiv_s_cg = new();
fsqrt_s_cg = new();
fmin_s_cg = new();
fmax_s_cg = new();
fmadd_s_cg = new();
fnmadd_s_cg = new();
fmsub_s_cg = new();
fnmsub_s_cg = new();
`CG_SELECTOR_END
// Ignore the exception which cannot be covered when running with ISS
if (iss_mode) begin
int i;
@ -1111,6 +1242,7 @@ class riscv_instr_cover_group;
mcause_exception_cg = new();
mcause_interrupt_cg = new();
mstatus_m_cg = new();
fcsr_cg = new();
end
if (!cfg.disable_compressed_instr) begin
mepc_alignment_cg = new();
@ -1242,6 +1374,19 @@ class riscv_instr_cover_group;
C_SUBW : `SAMPLE(c_subw_cg, instr)
C_ADDW : `SAMPLE(c_addw_cg, instr)
C_ADDIW : `SAMPLE(c_addiw_cg, instr)
FLW : `SAMPLE(flw_cg, instr)
FSW : `SAMPLE(fsw_cg, instr)
FADD_S : `SAMPLE(fadd_s_cg, instr)
FSUB_S : `SAMPLE(fsub_s_cg, instr)
FMUL_S : `SAMPLE(fmul_s_cg, instr)
FDIV_S : `SAMPLE(fdiv_s_cg, instr)
FSQRT_S : `SAMPLE(fsqrt_s_cg, instr)
FMIN_S : `SAMPLE(fmin_s_cg, instr)
FMAX_S : `SAMPLE(fmax_s_cg, instr)
FMADD_S : `SAMPLE(fmadd_s_cg, instr)
FNMADD_S : `SAMPLE(fnmadd_s_cg, instr)
FMSUB_S : `SAMPLE(fmsub_s_cg, instr)
FNMSUB_S : `SAMPLE(fnmsub_s_cg, instr)
`VECTOR_INCLUDE("riscv_instr_cover_group_inc_cg_sample.sv")
default: begin
if (instr.group == RV32I) begin
@ -1280,6 +1425,9 @@ class riscv_instr_cover_group;
MSTATUS: begin
`SAMPLE(mstatus_m_cg, instr.rd_value);
end
FCSR: begin
`SAMPLE(fcsr_cg, instr.rd_value);
end
endcase
end
if (instr_cnt > 1) begin

View file

@ -511,8 +511,8 @@ package riscv_instr_pkg;
} riscv_reg_t;
typedef enum bit [4:0] {
F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31
FT0, FT1, FT2, FT3, FT4, FT5, FT6, FT7, FS0, FS1, FA0, FA1, FA2, FA3, FA4, FA5,
FA6, FA7, FS2, FS3, FS4, FS5, FS6, FS7, FS8, FS9, FS10, FS11, FT8, FT9, FT10, FT11
} riscv_fpr_t;
typedef enum bit [4:0] {

View file

@ -42,7 +42,7 @@ class riscv_load_store_base_instr_stream extends riscv_mem_access_stream;
constraint sp_rnd_order_c {
solve use_sp_as_rs1 before rs1_reg;
}
constraint sp_c {
use_sp_as_rs1 dist {1 := 1, 0 := 2};
if (use_sp_as_rs1) {
@ -245,6 +245,20 @@ class riscv_load_store_stress_instr_stream extends riscv_load_store_base_instr_s
endclass
// Back to back load/store instructions
class riscv_load_store_shared_mem_stream extends riscv_load_store_stress_instr_stream;
`uvm_object_utils(riscv_load_store_shared_mem_stream)
`uvm_object_new
function void pre_randomize();
load_store_shared_memory = 1;
super.pre_randomize();
endfunction
endclass
// Random load/store sequence
// A random mix of load/store instructions and other instructions
class riscv_load_store_rand_instr_stream extends riscv_load_store_base_instr_stream;
@ -374,6 +388,7 @@ class riscv_multi_page_load_store_instr_stream extends riscv_mem_access_stream;
load_store_instr_stream[i].min_instr_cnt = 5;
load_store_instr_stream[i].max_instr_cnt = 10;
load_store_instr_stream[i].cfg = cfg;
load_store_instr_stream[i].hart = hart;
load_store_instr_stream[i].sp_c.constraint_mode(0);
// Make sure each load/store sequence doesn't override the rs1 of other sequences.
foreach(rs1_reg[j]) begin

View file

@ -54,6 +54,18 @@
rtl_test: core_base_test
- test: riscv_load_store_shared_mem_test
description: >
Multi-harts load/store from shared memory regions
iterations: 2
gen_test: riscv_rand_instr_test
gen_opts: >
+instr_cnt=5000
+num_of_sub_program=5
+directed_instr_0=riscv_load_store_shared_mem_stream,10
rtl_test: core_base_test
- test: riscv_amo_test
description: >
RISC-V atomic instruction extension test

View file

@ -3,6 +3,7 @@ class riscv_instr_cov_test extends uvm_test;
typedef uvm_enum_wrapper#(riscv_instr_name_t) instr_enum;
typedef uvm_enum_wrapper#(riscv_reg_t) gpr_enum;
typedef uvm_enum_wrapper#(riscv_fpr_t) fpr_enum;
typedef uvm_enum_wrapper#(privileged_reg_t) preg_enum;
riscv_instr_gen_config cfg;
@ -136,7 +137,8 @@ class riscv_instr_cov_test extends uvm_test;
if (instr_enum::from_name(process_instr_name(trace["instr"]), instr_name)) begin
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}) begin
if (instr.group inside {RV32I, RV32M, RV32C, RV64I, RV64M, RV64C,
RV32F}) begin
assign_trace_info_to_instr(instr);
end
instr.pre_sample();
@ -169,6 +171,8 @@ class riscv_instr_cov_test extends uvm_test;
get_val(operands[1], instr.imm);
end
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.category == LOAD) begin
// load rd, imm(rs1)
@ -194,8 +198,10 @@ class riscv_instr_cov_test extends uvm_test;
`DV_CHECK_FATAL(operands.size() == 3)
if(instr.category == STORE) begin
// sw rs2,imm(rs1)
instr.rs2 = get_gpr(operands[0]);
instr.rs2_value = get_gpr_state(operands[0]);
update_instr_reg_by_abi_name(operands[0], // FSW rs2 is fp
instr.rs2, instr.rs2_value,
instr.fs2, instr.fs2_value);
instr.rs1 = get_gpr(operands[2]);
instr.rs1_value = get_gpr_state(operands[2]);
get_val(operands[1], instr.imm);
@ -209,7 +215,8 @@ class riscv_instr_cov_test extends uvm_test;
end
end
R_FORMAT: begin
`DV_CHECK_FATAL(operands.size() == 3)
if (!instr.instr_name inside {FCLASS_S, FCLASS_D}) `DV_CHECK_FATAL(operands.size() == 3)
else `DV_CHECK_FATAL(operands.size() == 2)
if(instr.category == CSR) begin
// csrrw rd, csr, rs1
if (preg_enum::from_name(operands[1].toupper(), preg)) begin
@ -219,6 +226,16 @@ class riscv_instr_cov_test extends uvm_test;
end
instr.rs1 = get_gpr(operands[2]);
instr.rs1_value = get_gpr_state(operands[2]);
end
else if (instr.group inside {RV32F, RV64F, RV32D, RV64D}) begin
// fs1
instr.fs1 = get_fpr(operands[1]);
instr.fs1_value = get_gpr_state(operands[1]);
// fs2
if (!instr.instr_name inside {FCLASS_S, FCLASS_D}) begin
instr.fs2 = get_fpr(operands[2]);
instr.fs2_value = get_gpr_state(operands[2]);
end
end else begin
// add rd, rs1, rs2
instr.rs1 = get_gpr(operands[1]);
@ -227,6 +244,15 @@ class riscv_instr_cov_test extends uvm_test;
instr.rs2_value = get_gpr_state(operands[2]);
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]);
end
CI_FORMAT, CIW_FORMAT: begin
if (instr.instr_name == C_ADDI16SP) begin
get_val(operands[1], instr.imm);
@ -303,8 +329,7 @@ class riscv_instr_cov_test extends uvm_test;
`uvm_fatal(`gfn, $sformatf("Illegal gpr update format: %0s", gpr_update[i]))
end
get_val(pair[1], gpr_state[pair[0]], .hex(1));
instr.rd = get_gpr(pair[0]);
instr.rd_value = get_gpr_state(pair[0]);
update_instr_reg_by_abi_name(pair[0], instr.rd, instr.rd_value, instr.fd, instr.fd_value);
end
endfunction : assign_trace_info_to_instr
@ -315,6 +340,13 @@ class riscv_instr_cov_test extends uvm_test;
end
endfunction : get_gpr
function riscv_fpr_t get_fpr(input string str);
str = str.toupper();
if (!fpr_enum::from_name(str, get_fpr)) begin
`uvm_fatal(`gfn, $sformatf("Cannot convert %0s to FPR", str))
end
endfunction : get_fpr
function bit [XLEN-1:0] get_gpr_state(string name);
if (name inside {"zero", "x0"}) begin
return 0;
@ -347,6 +379,26 @@ class riscv_instr_cov_test extends uvm_test;
`uvm_info(`gfn, $sformatf("imm:%0s -> 0x%0x/%0d", str, val, $signed(val)), UVM_FULL)
endfunction : get_val
function bit is_fp_reg(input string str);
riscv_fpr_t tmp;
str = str.toupper();
return fpr_enum::from_name(str, tmp);
endfunction : is_fp_reg
function void update_instr_reg_by_abi_name(string abi_name,
ref riscv_reg_t rs,
ref bit [XLEN-1:0] rs_value,
ref riscv_fpr_t fs,
ref bit [XLEN-1:0] fs_value);
if (is_fp_reg(abi_name)) begin
fs = get_fpr(abi_name);
fs_value = get_gpr_state(abi_name);
end else begin
rs = get_gpr(abi_name);
rs_value = get_gpr_state(abi_name);
end
endfunction : update_instr_reg_by_abi_name
function string process_instr_name(string instr_name);
instr_name = instr_name.toupper();
foreach (instr_name[i]) begin