diff --git a/dv/uvm/common/irq_agent/irq_if.sv b/dv/uvm/common/irq_agent/irq_if.sv index 0c486883..138f50fc 100644 --- a/dv/uvm/common/irq_agent/irq_if.sv +++ b/dv/uvm/common/irq_agent/irq_if.sv @@ -3,10 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 interface irq_if; - logic clock; - logic reset; - logic irq_i; - logic [4:0] irq_id_i; - logic [4:0] irq_id_o; - logic irq_ack_o; + logic clock; + logic reset; + logic irq_software; + logic irq_timer; + logic irq_external; + logic [14:0] irq_fast; + logic irq_nm; // non-maskeable interrupt endinterface diff --git a/dv/uvm/common/irq_agent/irq_master_driver.sv b/dv/uvm/common/irq_agent/irq_master_driver.sv index 4339a0dc..5e11d515 100644 --- a/dv/uvm/common/irq_agent/irq_master_driver.sv +++ b/dv/uvm/common/irq_agent/irq_master_driver.sv @@ -42,8 +42,7 @@ class irq_master_driver extends uvm_driver #(irq_seq_item); virtual protected task reset_signals(); forever begin @(posedge vif.reset); - vif.irq_i <= 'h0; - vif.irq_id_i <= 'hz; + drive_reset_value(); end endtask : reset_signals @@ -51,16 +50,22 @@ class irq_master_driver extends uvm_driver #(irq_seq_item); if (trans.delay > 0) begin repeat(trans.delay) @(posedge vif.clock); end - vif.irq_i <= 1'b1; - vif.irq_id_i <= trans.irq_id; + vif.irq_software <= trans.irq_software; + vif.irq_timer <= trans.irq_timer; + vif.irq_external <= trans.irq_external; + vif.irq_fast <= trans.irq_fast; + vif.irq_nm <= trans.irq_nm; @(posedge vif.clock); - while (vif.irq_ack_o !== 1'b1) begin - @(posedge vif.clock); - end - trans.irq_id_o = vif.irq_id_o; - vif.irq_i <= 'h0; - vif.irq_id_i <= 'hz; + drive_reset_value(); endtask : drive_seq_item + task drive_reset_value(); + vif.irq_software <= '0; + vif.irq_timer <= '0; + vif.irq_external <= '0; + vif.irq_fast <= '0; + vif.irq_nm <= '0; + endtask : drive_reset_value + endclass : irq_master_driver diff --git a/dv/uvm/common/irq_agent/irq_monitor.sv b/dv/uvm/common/irq_agent/irq_monitor.sv index b08e760b..f3332f37 100644 --- a/dv/uvm/common/irq_agent/irq_monitor.sv +++ b/dv/uvm/common/irq_agent/irq_monitor.sv @@ -28,12 +28,16 @@ class irq_monitor extends uvm_monitor; virtual protected task collect_irq(); irq_seq_item irq; forever begin - irq = irq_seq_item::type_id::create("irq"); - while (vif.irq_i === 1'b0) @(posedge vif.clock); - irq.irq_id = vif.irq_id_i; - while (vif.irq_ack_o === 1'b0) @(posedge vif.clock); - irq.irq_id_o = vif.irq_id_o; - irq_port.write(irq); + if (|{vif.irq_software, vif.irq_timer, vif.irq_external, + vif.irq_fast, vif.irq_nm}) begin + irq = irq_seq_item::type_id::create("irq"); + irq.irq_software = vif.irq_software; + irq.irq_timer = vif.irq_timer; + irq.irq_external = vif.irq_external; + irq.irq_fast = vif.irq_fast; + irq.irq_nm = vif.irq_nm; + irq_port.write(irq); + end @(posedge vif.clock); end endtask : collect_irq diff --git a/dv/uvm/common/irq_agent/irq_seq_item.sv b/dv/uvm/common/irq_agent/irq_seq_item.sv index 403c5a87..0e744bf6 100644 --- a/dv/uvm/common/irq_agent/irq_seq_item.sv +++ b/dv/uvm/common/irq_agent/irq_seq_item.sv @@ -4,14 +4,20 @@ class irq_seq_item extends uvm_sequence_item; - rand bit [4:0] irq_id; - rand bit [3:0] delay; - rand bit [4:0] irq_id_o; + rand bit irq_software; + rand bit irq_timer; + rand bit irq_external; + rand bit [14:0] irq_fast; + rand bit irq_nm; + rand int unsigned delay; `uvm_object_utils_begin(irq_seq_item) - `uvm_field_int(irq_id, UVM_DEFAULT) - `uvm_field_int(irq_id_o, UVM_DEFAULT) - `uvm_field_int(delay, UVM_DEFAULT) + `uvm_field_int(irq_software, UVM_DEFAULT) + `uvm_field_int(irq_timer, UVM_DEFAULT) + `uvm_field_int(irq_external, UVM_DEFAULT) + `uvm_field_int(irq_fast, UVM_DEFAULT) + `uvm_field_int(irq_nm, UVM_DEFAULT) + `uvm_field_int(delay, UVM_DEFAULT) `uvm_object_utils_end `uvm_object_new diff --git a/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv b/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv index 9109771d..a3c9da7d 100644 --- a/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv +++ b/dv/uvm/riscv_dv_extension/ibex_asm_program_gen.sv @@ -12,7 +12,7 @@ class ibex_asm_program_gen extends riscv_asm_program_gen; `uvm_object_new virtual function void gen_program_header(); - // Override the cfg value, below field is not supported by ibex + // Override the cfg value, below fields are not supported by ibex cfg.mstatus_mprv = 0; cfg.mstatus_mxr = 0; cfg.mstatus_sum = 0; @@ -28,28 +28,26 @@ class ibex_asm_program_gen extends riscv_asm_program_gen; instr_stream.push_back(".endm"); instr_stream.push_back(".section .text.init"); instr_stream.push_back(".globl _start"); - // 0x0 - 0xFF is reserved for trap/interrupt handling instr_stream.push_back(".option norvc"); - instr_stream.push_back("j mtvec_handler"); - // 0x40 debug mode entry - instr_stream.push_back(".align 6"); + // 0x0 - 0x4F is reserved for trap/interrupt handling + repeat (20) begin + instr_stream.push_back("j mtvec_handler"); + end + // 0x50 debug mode entry instr_stream.push_back("j debug_rom"); - // 0x44 debug mode exception handler + // 0x54 debug mode exception handler instr_stream.push_back("j debug_exception"); - instr_stream.push_back(".option rvc"); // Align the start section to 0x80 instr_stream.push_back(".align 7"); instr_stream.push_back("_start: j _reset_entry"); // ibex reserves 0x84-0x8C for trap handling, redirect everything mtvec_handler // 0x84 illegal instruction - instr_stream.push_back(".align 2"); instr_stream.push_back("j mtvec_handler"); // 0x88 ECALL instruction handler - instr_stream.push_back(".align 2"); instr_stream.push_back("j mtvec_handler"); // 0x8C LSU error - instr_stream.push_back(".align 2"); instr_stream.push_back("j mtvec_handler"); + instr_stream.push_back(".option rvc"); // Starting point of the reset entry instr_stream.push_back("_reset_entry:"); endfunction diff --git a/dv/uvm/tb/core_ibex_tb_top.sv b/dv/uvm/tb/core_ibex_tb_top.sv index 2f777fb6..1eaab876 100644 --- a/dv/uvm/tb/core_ibex_tb_top.sv +++ b/dv/uvm/tb/core_ibex_tb_top.sv @@ -12,10 +12,14 @@ module core_ibex_tb_top; logic debug_req; clk_if ibex_clk_if(.clk(clk)); + irq_if irq_vif(); + + // DUT probe interface + core_ibex_dut_probe_if dut_if(.clk(clk)); // TODO(taliu) Resolve the tied-off ports - ibex_core_tracing #(.DmHaltAddr(`BOOT_ADDR + 'h40), - .DmExceptionAddr(`BOOT_ADDR + 'h44) + ibex_core_tracing #(.DmHaltAddr(`BOOT_ADDR + 'h50), + .DmExceptionAddr(`BOOT_ADDR + 'h54) ) dut ( .clk_i(clk), .rst_ni(rst_n), @@ -24,12 +28,17 @@ module core_ibex_tb_top; .cluster_id_i('0), .boot_addr_i(`BOOT_ADDR), // align with spike boot address .debug_req_i(debug_req), - .fetch_enable_i(fetch_enable) + .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), + .fetch_enable_i(dut_if.fetch_enable), + .debug_req_i(dut_if.debug_req) ); ibex_mem_intf data_mem_vif(); ibex_mem_intf instr_mem_vif(); - irq_if irq_vif(); initial begin // Data load/store vif connection @@ -58,17 +67,10 @@ module core_ibex_tb_top; // IRQ interface force irq_vif.clock = clk; force irq_vif.reset = ~rst_n; - force dut.irq_i = irq_vif.irq_i; - force dut.irq_id_i = irq_vif.irq_id_i; - force irq_vif.irq_ack_o = dut.irq_ack_o; - force irq_vif.irq_id_o = dut.irq_id_o; end - // DUT probe interface - core_ibex_dut_probe_if dut_if(.clk(clk)); assign dut_if.ecall = dut.u_ibex_core.id_stage_i.ecall_insn_dec; - assign fetch_enable = dut_if.fetch_enable; - assign debug_req = dut_if.debug_req; + initial begin uvm_config_db#(virtual clk_if)::set(null, "*", "clk_if", ibex_clk_if); diff --git a/dv/uvm/tests/core_ibex_seq_lib.sv b/dv/uvm/tests/core_ibex_seq_lib.sv index 91bce2b2..2035a430 100644 --- a/dv/uvm/tests/core_ibex_seq_lib.sv +++ b/dv/uvm/tests/core_ibex_seq_lib.sv @@ -55,6 +55,7 @@ class core_base_seq #(type REQ = uvm_sequence_item) extends uvm_sequence#(REQ); virtual task stop(); stop_seq = 1'b1; + `uvm_info(get_full_name(), "Stopping sequence", UVM_LOW) wait (seq_finished == 1'b1); endtask @@ -72,6 +73,7 @@ class irq_seq extends core_base_seq#(irq_seq_item); start_item(irq); `DV_CHECK_RANDOMIZE_FATAL(irq) finish_item(irq); + get_response(irq); endtask endclass