mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-23 13:37:20 -04:00
Add interrupt agent (#116)
This commit is contained in:
parent
c86f71e724
commit
6d09fb1060
11 changed files with 211 additions and 7 deletions
23
dv/uvm/common/irq_agent/irq_agent_pkg.sv
Normal file
23
dv/uvm/common/irq_agent/irq_agent_pkg.sv
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
`include "irq_if.sv"
|
||||
|
||||
package irq_agent_pkg;
|
||||
|
||||
import uvm_pkg::*;
|
||||
|
||||
parameter DATA_WIDTH = 32;
|
||||
parameter ADDR_WIDTH = 32;
|
||||
|
||||
`include "uvm_macros.svh"
|
||||
`include "irq_seq_item.sv"
|
||||
|
||||
typedef uvm_sequencer#(irq_seq_item) irq_master_sequencer;
|
||||
|
||||
`include "irq_monitor.sv"
|
||||
`include "irq_master_driver.sv"
|
||||
`include "irq_master_agent.sv"
|
||||
|
||||
endpackage
|
12
dv/uvm/common/irq_agent/irq_if.sv
Normal file
12
dv/uvm/common/irq_agent/irq_if.sv
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// 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;
|
||||
endinterface
|
29
dv/uvm/common/irq_agent/irq_master_agent.sv
Normal file
29
dv/uvm/common/irq_agent/irq_master_agent.sv
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
class irq_master_agent extends uvm_agent;
|
||||
|
||||
irq_master_driver driver;
|
||||
irq_master_sequencer sequencer;
|
||||
irq_monitor monitor;
|
||||
|
||||
`uvm_component_utils(irq_master_agent)
|
||||
`uvm_component_new
|
||||
|
||||
virtual function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
monitor = irq_monitor::type_id::create("monitor", this);
|
||||
if (get_is_active() == UVM_ACTIVE) begin
|
||||
driver = irq_master_driver::type_id::create("driver", this);
|
||||
sequencer = irq_master_sequencer::type_id::create("sequencer", this);
|
||||
end
|
||||
endfunction : build_phase
|
||||
|
||||
function void connect_phase(uvm_phase phase);
|
||||
if (get_is_active() == UVM_ACTIVE) begin
|
||||
driver.seq_item_port.connect(sequencer.seq_item_export);
|
||||
end
|
||||
endfunction : connect_phase
|
||||
|
||||
endclass : irq_master_agent
|
66
dv/uvm/common/irq_agent/irq_master_driver.sv
Normal file
66
dv/uvm/common/irq_agent/irq_master_driver.sv
Normal file
|
@ -0,0 +1,66 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
class irq_master_driver extends uvm_driver #(irq_seq_item);
|
||||
|
||||
// The virtual interface used to drive and view HDL signals.
|
||||
protected virtual irq_if vif;
|
||||
|
||||
`uvm_component_utils(irq_master_driver)
|
||||
`uvm_component_new
|
||||
|
||||
function void build_phase(uvm_phase phase);
|
||||
super.build_phase(phase);
|
||||
if (!uvm_config_db#(virtual irq_if)::get(this, "", "vif", vif)) begin
|
||||
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
|
||||
end
|
||||
endfunction: build_phase
|
||||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
fork
|
||||
get_and_drive();
|
||||
reset_signals();
|
||||
join
|
||||
endtask : run_phase
|
||||
|
||||
virtual protected task get_and_drive();
|
||||
@(negedge vif.reset);
|
||||
forever begin
|
||||
seq_item_port.try_next_item(req);
|
||||
if (req != null) begin
|
||||
$cast(rsp, req.clone());
|
||||
rsp.set_id_info(req);
|
||||
drive_seq_item(rsp);
|
||||
seq_item_port.item_done(rsp);
|
||||
end else begin
|
||||
@(posedge vif.clock);
|
||||
end
|
||||
end
|
||||
endtask : get_and_drive
|
||||
|
||||
virtual protected task reset_signals();
|
||||
forever begin
|
||||
@(posedge vif.reset);
|
||||
vif.irq_i <= 'h0;
|
||||
vif.irq_id_i <= 'hz;
|
||||
end
|
||||
endtask : reset_signals
|
||||
|
||||
virtual protected task drive_seq_item (irq_seq_item trans);
|
||||
if (trans.delay > 0) begin
|
||||
repeat(trans.delay) @(posedge vif.clock);
|
||||
end
|
||||
vif.irq_i <= 1'b1;
|
||||
vif.irq_id_i <= trans.irq_id;
|
||||
@(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;
|
||||
endtask : drive_seq_item
|
||||
|
||||
endclass : irq_master_driver
|
||||
|
41
dv/uvm/common/irq_agent/irq_monitor.sv
Normal file
41
dv/uvm/common/irq_agent/irq_monitor.sv
Normal file
|
@ -0,0 +1,41 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
class irq_monitor extends uvm_monitor;
|
||||
|
||||
protected virtual irq_if vif;
|
||||
|
||||
uvm_analysis_port#(irq_seq_item) irq_port;
|
||||
|
||||
`uvm_component_utils(irq_monitor)
|
||||
|
||||
function new(string name, uvm_component parent=null);
|
||||
super.new(name, parent);
|
||||
irq_port = new("irq_port", this);
|
||||
endfunction : new
|
||||
|
||||
function void build_phase(uvm_phase phase);
|
||||
if (!uvm_config_db#(virtual irq_if)::get(this, "", "vif", vif)) begin
|
||||
`uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
|
||||
end
|
||||
endfunction: build_phase
|
||||
|
||||
virtual task run_phase(uvm_phase phase);
|
||||
collect_irq();
|
||||
endtask : run_phase
|
||||
|
||||
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);
|
||||
@(posedge vif.clock);
|
||||
end
|
||||
endtask : collect_irq
|
||||
|
||||
endclass : irq_monitor
|
19
dv/uvm/common/irq_agent/irq_seq_item.sv
Normal file
19
dv/uvm/common/irq_agent/irq_seq_item.sv
Normal file
|
@ -0,0 +1,19 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
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;
|
||||
|
||||
`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_object_utils_end
|
||||
|
||||
`uvm_object_new
|
||||
|
||||
endclass : irq_seq_item
|
1
dv/uvm/env/core_ibex_dut_probe_if.sv
vendored
1
dv/uvm/env/core_ibex_dut_probe_if.sv
vendored
|
@ -7,4 +7,5 @@ interface core_ibex_dut_probe_if(input logic clk);
|
|||
logic illegal_instr;
|
||||
logic ecall;
|
||||
logic fetch_enable;
|
||||
logic debug_req;
|
||||
endinterface
|
||||
|
|
|
@ -30,12 +30,14 @@ ${PRJ_DIR}/ibex/rtl/ibex_core.sv
|
|||
+incdir+${PRJ_DIR}/ibex/dv/uvm/env
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/tests
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/common/ibex_mem_intf_agent
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/common/irq_agent
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/common/mem_model
|
||||
+incdir+${PRJ_DIR}/ibex/dv/uvm/common/utils
|
||||
${PRJ_DIR}/ibex/dv/uvm/common/utils/clk_if.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/common/utils/dv_utils_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/common/mem_model/mem_model_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/common/ibex_mem_intf_agent/ibex_mem_intf_agent_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/common/irq_agent/irq_agent_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/env/core_ibex_env_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/tests/core_ibex_test_pkg.sv
|
||||
${PRJ_DIR}/ibex/dv/uvm/tb/core_ibex_tb_top.sv
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, "../../vendor/google_riscv-dv/scripts")
|
||||
|
||||
from riscv_trace_csv import *
|
||||
|
||||
|
|
|
@ -20,17 +20,16 @@ module core_ibex_tb_top;
|
|||
.core_id_i('0),
|
||||
.cluster_id_i('0),
|
||||
.boot_addr_i(`BOOT_ADDR), // align with spike boot address
|
||||
.irq_i('0),
|
||||
.irq_id_i('0),
|
||||
.debug_req_i('0),
|
||||
.fetch_enable_i(fetch_enable)
|
||||
);
|
||||
|
||||
ibex_mem_intf data_mem_vif();
|
||||
ibex_mem_intf instr_mem_vif();
|
||||
ibex_mem_intf data_mem_vif();
|
||||
ibex_mem_intf instr_mem_vif();
|
||||
irq_if irq_vif();
|
||||
|
||||
initial begin
|
||||
//data load/store vif connection
|
||||
// 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;
|
||||
|
@ -42,7 +41,7 @@ module core_ibex_tb_top;
|
|||
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
|
||||
// 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;
|
||||
|
@ -53,18 +52,27 @@ module core_ibex_tb_top;
|
|||
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;
|
||||
// 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.id_stage_i.ecall_insn_dec;
|
||||
assign fetch_enable = dut_if.fetch_enable;
|
||||
assign dut_if.debug_req = dut.debug_req_i;
|
||||
|
||||
initial begin
|
||||
uvm_config_db#(virtual clk_if)::set(null, "*", "clk_if", ibex_clk_if);
|
||||
uvm_config_db#(virtual core_ibex_dut_probe_if)::set(null, "*", "dut_if", dut_if);
|
||||
uvm_config_db#(virtual ibex_mem_intf)::set(null, "*data_if_slave*", "vif", data_mem_vif);
|
||||
uvm_config_db#(virtual ibex_mem_intf)::set(null, "*instr_if_slave*", "vif", instr_mem_vif);
|
||||
uvm_config_db#(virtual irq_if)::set(null, "*", "vif", irq_vif);
|
||||
run_test();
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ class core_ibex_base_test extends uvm_test;
|
|||
virtual core_ibex_dut_probe_if dut_vif;
|
||||
mem_model_pkg::mem_model mem;
|
||||
core_ibex_vseq vseq;
|
||||
int unsigned timeout_in_cycles = 1000000;
|
||||
int unsigned timeout_in_cycles = 2000000;
|
||||
|
||||
`uvm_component_utils(core_ibex_base_test)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue