Add interrupt agent (#116)

This commit is contained in:
taoliug 2019-07-01 18:25:37 -07:00 committed by GitHub
parent c86f71e724
commit 6d09fb1060
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 211 additions and 7 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View file

@ -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

View file

@ -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

View file

@ -6,6 +6,9 @@
import argparse
import re
import sys
sys.path.insert(0, "../../vendor/google_riscv-dv/scripts")
from riscv_trace_csv import *

View file

@ -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

View file

@ -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)