diff --git a/dv/uvm/Makefile b/dv/uvm/Makefile index 214a537f..af661321 100644 --- a/dv/uvm/Makefile +++ b/dv/uvm/Makefile @@ -75,6 +75,7 @@ CSR_OPTS=--csr_yaml=${CSR_FILE} \ --lsf_cmd="${LSF_CMD}" \ --core_setting_dir=${DV_DIR}/riscv_dv_extension \ --user_extension_dir=${DV_DIR}/riscv_dv_extension \ + --simulator=${SIMULATOR} \ ${COMMON_OPTS} \ ${CSR_OPTS} \ --sim_opts="+uvm_set_type_override=riscv_asm_program_gen,ibex_asm_program_gen \ diff --git a/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv b/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv index e57803dd..1908dfdb 100644 --- a/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv +++ b/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_driver.sv @@ -61,16 +61,19 @@ class ibex_mem_intf_slave_driver extends uvm_driver #(ibex_mem_intf_seq_item); virtual protected task send_grant(); int gnt_delay; forever begin + vif.grant = 1'b1; while(vif.request !== 1'b1) begin @(negedge vif.clock); end - std::randomize(gnt_delay) with { + if (!std::randomize(gnt_delay) with { gnt_delay dist { min_grant_delay :/ 1, [min_grant_delay+1 : max_grant_delay-1] :/ 1, max_grant_delay :/ 1 }; - }; + }) begin + `uvm_fatal(`gfn, $sformatf("Cannot randomize grant")) + end repeat(gnt_delay) @(negedge vif.clock); if(~vif.reset) begin vif.grant = 1'b1; diff --git a/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_seq_lib.sv b/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_seq_lib.sv index 9ece3884..7188c8a2 100644 --- a/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_seq_lib.sv +++ b/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_slave_seq_lib.sv @@ -25,7 +25,7 @@ class ibex_mem_intf_slave_seq extends uvm_sequence #(ibex_mem_intf_seq_item); bit [ADDR_WIDTH-1:0] aligned_addr; p_sequencer.addr_ph_port.get(item); req = ibex_mem_intf_seq_item::type_id::create("req"); - req.randomize() with { + if (!req.randomize() with { addr == item.addr; read_write == item.read_write; data == item.data; @@ -36,7 +36,9 @@ class ibex_mem_intf_slave_seq extends uvm_sequence #(ibex_mem_intf_seq_item); [max_rvalid_delay/2 : max_rvalid_delay-1] :/ 1, max_rvalid_delay :/ 1 }; - }; + }) begin + `uvm_fatal(`gfn, "Cannot randomize slave request") + end aligned_addr = {req.addr[DATA_WIDTH-1:2], 2'b0}; if(req.read_write == READ) begin : READ_block req.data = m_mem.read(aligned_addr); diff --git a/dv/uvm/common/mem_model/mem_model.sv b/dv/uvm/common/mem_model/mem_model.sv index 4609a7f2..a31529db 100644 --- a/dv/uvm/common/mem_model/mem_model.sv +++ b/dv/uvm/common/mem_model/mem_model.sv @@ -23,7 +23,7 @@ class mem_model#(Addr_width = 32, Data_width = 32) extends uvm_object; $sformatf("Read Mem : Addr[0x%0h], Data[0x%0h]", addr, data), UVM_HIGH) end else begin - std::randomize(data); + void'(std::randomize(data)); `uvm_error(get_full_name(), $sformatf("read to uninitialzed addr 0x%0h", addr)) end return data; diff --git a/dv/uvm/sim.py b/dv/uvm/sim.py index 50e7dbaf..0d92bd22 100644 --- a/dv/uvm/sim.py +++ b/dv/uvm/sim.py @@ -89,13 +89,22 @@ def get_simulator_cmd(simulator, simulator_yaml, en_cov, en_wave): logging.info("Found matching simulator: %s" % entry['tool']) compile_cmd = entry['compile']['cmd'] for i in range(len(compile_cmd)): - compile_cmd[i] = process_cmd("", compile_cmd[i], - entry['compile']['cov_opts'], en_cov) - compile_cmd[i] = process_cmd("", compile_cmd[i], - entry['compile']['wave_opts'], en_wave) + if 'cov_opts' in entry['compile']: + compile_cmd[i] = process_cmd("", compile_cmd[i], + entry['compile']['cov_opts'], en_cov) + if 'wave_opts' in entry['compile']: + compile_cmd[i] = process_cmd("", compile_cmd[i], + entry['compile']['wave_opts'], en_wave) sim_cmd = entry['sim']['cmd'] - sim_cmd = process_cmd("", sim_cmd, entry['sim']['cov_opts'], en_cov) - sim_cmd = process_cmd("", sim_cmd, entry['sim']['wave_opts'], en_wave) + if 'cov_opts' in entry['sim']: + sim_cmd = process_cmd("", sim_cmd, entry['sim']['cov_opts'], en_cov) + if 'wave_opts' in entry['sim']: + sim_cmd = process_cmd("", sim_cmd, entry['sim']['wave_opts'], en_wave) + if 'env_var' in entry: + for env_var in entry['env_var'].split(','): + for i in range(len(compile_cmd)): + compile_cmd[i] = re.sub("<"+env_var+">", get_env_var(env_var), compile_cmd[i]) + sim_cmd = re.sub("<"+env_var+">", get_env_var(env_var), sim_cmd) return compile_cmd, sim_cmd logging.info("Cannot find RTL simulator %0s" % simulator) sys.exit(1) diff --git a/dv/uvm/tb/core_ibex_tb_top.sv b/dv/uvm/tb/core_ibex_tb_top.sv index 9a3c8745..d1e78f8d 100644 --- a/dv/uvm/tb/core_ibex_tb_top.sv +++ b/dv/uvm/tb/core_ibex_tb_top.sv @@ -5,14 +5,17 @@ module core_ibex_tb_top; import uvm_pkg::*; + import core_ibex_test_pkg::*; logic clk; logic rst_n; logic fetch_enable; - logic debug_req; - clk_if ibex_clk_if(.clk(clk)); - irq_if irq_vif(); + clk_if ibex_clk_if(.clk(clk)); + irq_if irq_vif(); + ibex_mem_intf data_mem_vif(); + ibex_mem_intf instr_mem_vif(); + // DUT probe interface core_ibex_dut_probe_if dut_if(.clk(clk)); @@ -25,44 +28,41 @@ module core_ibex_tb_top; .test_en_i(1'b1), .hart_id_i(32'b0), .boot_addr_i(`BOOT_ADDR), // align with spike boot address - .debug_req_i(debug_req), - .irq_software_i(irq_if.irq_software), - .irq_timer_i(irq_if.irq_timer), - .irq_external_i(irq_if.irq_external), - .irq_fast_i(irq_if.irq_fast), - .irq_nm_i(irq_if.irq_nm), + .irq_software_i(irq_vif.irq_software), + .irq_timer_i(irq_vif.irq_timer), + .irq_external_i(irq_vif.irq_external), + .irq_fast_i(irq_vif.irq_fast), + .irq_nm_i(irq_vif.irq_nm), .fetch_enable_i(dut_if.fetch_enable), - .debug_req_i(dut_if.debug_req) + .debug_req_i(dut_if.debug_req), + .data_gnt_i(data_mem_vif.grant), + .data_rvalid_i(data_mem_vif.rvalid), + .data_rdata_i(data_mem_vif.rdata), + .data_err_i(0), + .instr_gnt_i(instr_mem_vif.grant), + .instr_rvalid_i(instr_mem_vif.rvalid), + .instr_rdata_i(instr_mem_vif.rdata), + .instr_err_i(0) ); - ibex_mem_intf data_mem_vif(); - ibex_mem_intf instr_mem_vif(); + // Data load/store vif connection + assign data_mem_vif.clock = clk; + assign data_mem_vif.reset = ~rst_n; + assign data_mem_vif.request = dut.data_req_o; + assign data_mem_vif.we = dut.data_we_o; + assign data_mem_vif.be = dut.data_be_o; + assign data_mem_vif.addr = dut.data_addr_o; + assign data_mem_vif.wdata = dut.data_wdata_o; + // Instruction fetch vif connnection + assign instr_mem_vif.clock = clk; + assign instr_mem_vif.reset = ~rst_n; + assign instr_mem_vif.request = dut.instr_req_o; + assign instr_mem_vif.we = 0; + assign instr_mem_vif.be = 0; + assign instr_mem_vif.wdata = 0; + assign instr_mem_vif.addr = dut.instr_addr_o; initial begin - // Data load/store vif connection - force data_mem_vif.clock = clk; - force data_mem_vif.reset = ~rst_n; - force data_mem_vif.request = dut.data_req_o; - force dut.data_gnt_i = data_mem_vif.grant; - force dut.data_rvalid_i = data_mem_vif.rvalid; - force data_mem_vif.we = dut.data_we_o; - force data_mem_vif.be = dut.data_be_o; - force data_mem_vif.addr = dut.data_addr_o; - force data_mem_vif.wdata = dut.data_wdata_o; - force dut.data_rdata_i = data_mem_vif.rdata; - force dut.data_err_i = 0; // TODO(taliu) Support interface error - // Instruction fetch vif connnection - force instr_mem_vif.clock = clk; - force instr_mem_vif.reset = ~rst_n; - force instr_mem_vif.request = dut.instr_req_o; - force dut.instr_gnt_i = instr_mem_vif.grant; - force instr_mem_vif.we = 0; - force instr_mem_vif.be = 0; - force instr_mem_vif.wdata = 0; - force dut.instr_rvalid_i = instr_mem_vif.rvalid; - force instr_mem_vif.addr = dut.instr_addr_o; - force dut.instr_rdata_i = instr_mem_vif.rdata; - force dut.instr_err_i = 0; // TODO(taliu) Support interface error // IRQ interface force irq_vif.clock = clk; force irq_vif.reset = ~rst_n; diff --git a/dv/uvm/tests/core_ibex_base_test.sv b/dv/uvm/tests/core_ibex_base_test.sv index bef84643..12dab868 100644 --- a/dv/uvm/tests/core_ibex_base_test.sv +++ b/dv/uvm/tests/core_ibex_base_test.sv @@ -169,7 +169,7 @@ class core_ibex_base_test extends uvm_test; // Gets the next CORE_STATUS signature write and compares it against the provided core_status // type, throws uvm_error on mismatch - virtual task check_next_core_status(core_status_t core_status, string error_msg=""); + virtual task check_next_core_status(core_status_t core_status, string error_msg = ""); wait_for_mem_txn(cfg.signature_addr, CORE_STATUS); signature_data = signature_data_q.pop_front(); if (signature_data != core_status) begin diff --git a/dv/uvm/tests/core_ibex_test_lib.sv b/dv/uvm/tests/core_ibex_test_lib.sv index a149c4e7..a66f5e84 100644 --- a/dv/uvm/tests/core_ibex_test_lib.sv +++ b/dv/uvm/tests/core_ibex_test_lib.sv @@ -298,7 +298,8 @@ class core_ibex_dret_test extends core_ibex_directed_test; check_next_core_status(HANDLING_EXCEPTION, "Core did not jump to vectored exception handler"); // The core will receive an illegal instruction handshake after jumping from the vectored trap // handler to the illegal instruction exception handler - check_next_core_status(ILLEGAL_INSTR_EXCEPTION, "Core did not treat dret like illegal instruction"); + check_next_core_status(ILLEGAL_INSTR_EXCEPTION, + "Core did not treat dret like illegal instruction"); end endtask @@ -317,7 +318,8 @@ class core_ibex_debug_ebreak_test extends core_ibex_directed_test; forever begin wait (dut_vif.ebreak === 1'b1); check_next_core_status(HANDLING_EXCEPTION, "Core did not jump to exception handler"); - check_next_core_status(EBREAK_EXCEPTION, "Core did not jump from exception handler to ebreak handler"); + check_next_core_status(EBREAK_EXCEPTION, + "Core did not jump from exception handler to ebreak handler"); wait (dut_vif.mret === 1'b1); // Want to wait until after the ebreak handler has finished to send debug stimulus, to avoid // nested trap scenarios @@ -335,9 +337,11 @@ class core_ibex_debug_ebreak_test extends core_ibex_directed_test; wait (dut_vif.ebreak === 1'b1); // compare the second writes of dcsr and dpc against the captured values wait_for_csr_write(CSR_DCSR); - `DV_CHECK_EQ_FATAL(dcsr, signature_data, "ebreak inside the debug rom has changed the value of DCSR") + `DV_CHECK_EQ_FATAL(dcsr, signature_data, + "ebreak inside the debug rom has changed the value of DCSR") wait_for_csr_write(CSR_DPC); - `DV_CHECK_EQ_FATAL(dpc, signature_data, "ebreak inside the debug rom has changed the value of DPC") + `DV_CHECK_EQ_FATAL(dpc, signature_data, + "ebreak inside the debug rom has changed the value of DPC") wait (dut_vif.dret === 1'b1); end endtask @@ -353,7 +357,8 @@ class core_ibex_debug_ebreakm_test extends core_ibex_directed_test; virtual task check_stimulus(); // send a single debug request after core initialization to configure dcsr vseq.start_debug_single_seq(); - check_next_core_status(IN_DEBUG_MODE, "Core did not enter debug mode after debug_req stimulus"); + check_next_core_status(IN_DEBUG_MODE, + "Core did not enter debug mode after debug_req stimulus"); // Read dcsr and verify the appropriate ebreak(m/s/u) bit has been set based on the prv field, // as well as the cause field wait_for_csr_write(CSR_DCSR); @@ -362,7 +367,8 @@ class core_ibex_debug_ebreakm_test extends core_ibex_directed_test; wait (dut_vif.dret === 1'b1); forever begin wait (dut_vif.ebreak === 1'b1); - check_next_core_status(IN_DEBUG_MODE, "Core did not enter debug mode after execution of ebreak"); + check_next_core_status(IN_DEBUG_MODE, + "Core did not enter debug mode after execution of ebreak"); // Read dcsr and verify the appropriate ebreak(m/s/u) bit has been set based on the prv field wait_for_csr_write(CSR_DCSR); check_dcsr_ebreak(); diff --git a/dv/uvm/yaml/rtl_simulation.yaml b/dv/uvm/yaml/rtl_simulation.yaml index ea7037f2..de497d86 100644 --- a/dv/uvm/yaml/rtl_simulation.yaml +++ b/dv/uvm/yaml/rtl_simulation.yaml @@ -45,3 +45,22 @@ -cm_name test_ wave_opts: > -ucli -do /vcs.tcl + +- tool: dsim + env_var: DSIM,DSIM_LIB_PATH + compile: + cmd: + - "mkdir -p /dsim" + - " -sv -work /dsim + -genimage image + +incdir+$UVM_HOME/src + $UVM_HOME/src/uvm_pkg.sv + +define+DSIM + +acc+rwb + -f ibex_dv.f + -l /dsim/compile.log" + sim: + cmd: > + -sv_seed -pli_lib /libuvm_dpi.so +acc+rwb -image image -work /dsim + wave_opts: > + -waves waves.vcd