From 2616d5e649ca5b387eb5c0858fe044bd507da41d Mon Sep 17 00:00:00 2001 From: Jalali <110232072+AyoubJalali@users.noreply.github.com> Date: Fri, 5 Jul 2024 09:54:34 +0000 Subject: [PATCH] add UVM interrupt agent (#2309) --- verif/env/uvme/cov/uvme_cva6_cov_model.sv | 14 +- verif/env/uvme/cov/uvme_interrupt_covg.sv | 126 ++++++++++++ verif/env/uvme/uvma_interrupt/README.md | 16 ++ .../cov/uvma_interrupt_cov_model.sv | 111 +++++++++++ .../seq/uvma_interrupt_base_seq.sv | 55 ++++++ .../uvma_interrupt/seq/uvma_interrupt_seq.sv | 60 ++++++ .../seq/uvma_interrupt_seq_item.sv | 66 +++++++ .../uvma_interrupt/uvma_interrupt_agent.sv | 182 ++++++++++++++++++ .../uvme/uvma_interrupt/uvma_interrupt_cfg.sv | 115 +++++++++++ .../uvma_interrupt/uvma_interrupt_cntxt.sv | 68 +++++++ .../uvma_interrupt_constants.sv | 14 ++ .../uvme/uvma_interrupt/uvma_interrupt_drv.sv | 165 ++++++++++++++++ .../uvme/uvma_interrupt/uvma_interrupt_if.sv | 28 +++ .../uvma_interrupt/uvma_interrupt_macros.sv | 25 +++ .../uvme/uvma_interrupt/uvma_interrupt_mon.sv | 114 +++++++++++ .../uvma_interrupt/uvma_interrupt_pkg.flist | 17 ++ .../uvme/uvma_interrupt/uvma_interrupt_pkg.sv | 61 ++++++ .../uvme/uvma_interrupt/uvma_interrupt_sqr.sv | 77 ++++++++ .../uvma_interrupt/uvma_interrupt_tdefs.sv | 25 +++ verif/env/uvme/uvme_cva6_cfg.sv | 38 ++-- verif/env/uvme/uvme_cva6_cntxt.sv | 3 + verif/env/uvme/uvme_cva6_env.sv | 22 ++- verif/env/uvme/uvme_cva6_pkg.flist | 1 + verif/env/uvme/uvme_cva6_pkg.sv | 3 + verif/env/uvme/uvme_cva6_vsqr.sv | 7 +- verif/regress/dv-interrupt-test.sh | 42 ++++ verif/sim/Makefile | 2 +- verif/sim/cva6_base_testlist.yaml | 31 +++ verif/tb/uvmt/cva6_tb_wrapper.sv | 21 +- verif/tb/uvmt/uvmt_cva6.flist | 1 + verif/tb/uvmt/uvmt_cva6_dut_wrap.sv | 2 + verif/tb/uvmt/uvmt_cva6_tb.sv | 8 + verif/tests/custom/interrupt/jump_to_zero.S | 65 +++++++ verif/tests/testlist_interrupt.yaml | 32 +++ 34 files changed, 1583 insertions(+), 34 deletions(-) create mode 100644 verif/env/uvme/cov/uvme_interrupt_covg.sv create mode 100644 verif/env/uvme/uvma_interrupt/README.md create mode 100644 verif/env/uvme/uvma_interrupt/cov/uvma_interrupt_cov_model.sv create mode 100644 verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_base_seq.sv create mode 100644 verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq.sv create mode 100644 verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq_item.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_agent.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_cfg.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_cntxt.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_constants.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_drv.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_if.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_macros.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_mon.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.flist create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_sqr.sv create mode 100644 verif/env/uvme/uvma_interrupt/uvma_interrupt_tdefs.sv create mode 100644 verif/regress/dv-interrupt-test.sh create mode 100644 verif/tests/custom/interrupt/jump_to_zero.S create mode 100644 verif/tests/testlist_interrupt.yaml diff --git a/verif/env/uvme/cov/uvme_cva6_cov_model.sv b/verif/env/uvme/cov/uvme_cva6_cov_model.sv index e360163b79..63edcd4c5d 100644 --- a/verif/env/uvme/cov/uvme_cva6_cov_model.sv +++ b/verif/env/uvme/cov/uvme_cva6_cov_model.sv @@ -37,6 +37,7 @@ class uvme_cva6_cov_model_c extends uvm_component; uvme_exception_cov_model_c exception_covg; uvme_axi_covg_c axi_covg; uvme_axi_ext_covg_c axi_ext_covg; + uvme_interrupt_covg_c interrupt_covg; // uvm_analysis_export#(uvma_clknrst_mon_trn_c) reset_export; @@ -101,12 +102,13 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase); `uvm_fatal("CNTXT", "Context handle is null") end - if (cfg.cov_cvxif_model_enabled) begin + if (cfg.cvxif_cfg.cov_model_enabled) begin cvxif_covg = uvme_cvxif_covg_c::type_id::create("cvxif_covg", this); uvm_config_db#(uvme_cva6_cfg_c)::set(this, "cvxif_covg", "cfg", cfg); + uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "cvxif_covg", "cntxt", cntxt); end - if (cfg.cov_isa_model_enabled) begin + if (cfg.isacov_cfg.cov_model_enabled) begin isa_covg = uvme_isa_cov_model_c::type_id::create("isa_covg", this); illegal_covg = uvme_illegal_instr_cov_model_c::type_id::create("illegal_covg", this); exception_covg = uvme_exception_cov_model_c::type_id::create("exception_covg", this); @@ -114,8 +116,6 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase); uvm_config_db#(uvme_cva6_cfg_c)::set(this, "illegal_covg", "cfg", cfg); uvm_config_db#(uvme_cva6_cfg_c)::set(this, "exception_covg", "cfg", cfg); end - - uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "cvxif_covg", "cntxt", cntxt); config_covg = uvme_cva6_config_covg_c::type_id::create("config_covg", this); uvm_config_db#(uvme_cva6_cfg_c)::set(this, "config_covg", "cfg", cfg); @@ -130,6 +130,12 @@ function void uvme_cva6_cov_model_c::build_phase(uvm_phase phase); uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "axi_ext_covg", "cntxt", cntxt); end + if(cfg.interrupt_cfg.cov_model_enabled) begin + interrupt_covg = uvme_interrupt_covg_c::type_id::create("interrupt_covg", this); + uvm_config_db#(uvme_cva6_cfg_c)::set(this, "interrupt_covg", "cfg", cfg); + uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "interrupt_covg", "cntxt", cntxt); + end + endfunction : build_phase function void uvme_cva6_cov_model_c::connect_phase(uvm_phase phase); diff --git a/verif/env/uvme/cov/uvme_interrupt_covg.sv b/verif/env/uvme/cov/uvme_interrupt_covg.sv new file mode 100644 index 0000000000..df9a8261f3 --- /dev/null +++ b/verif/env/uvme/cov/uvme_interrupt_covg.sv @@ -0,0 +1,126 @@ +// +// Copyright 2024 OpenHW Group +// Copyright 2024 Thales +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 + +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + +covergroup cg_interrupt( + string name +) with function sample ( + uvma_isacov_instr_c instr +); + option.per_instance = 1; + option.name = name; + + cp_interrupt: coverpoint instr.rvfi.name_csrs["mcause"].wdata { + bins NO_INTERRUPT = {0} iff (!instr.trap); + + bins MACHINE_MODE_EXTERNAL_INTERRUPT = {32'h8000000b} iff (instr.trap); + bins MACHINE_MODE_SOFTWARE_INTERRUPT = {32'h80000003} iff (instr.trap); + bins MACHINE_MODE_TIMER_INTERRUPT = {32'h80000007} iff (instr.trap); + + } + + cp_mstatus_mie: coverpoint instr.rvfi.name_csrs["mstatus"].wdata[3] { + bins GLOBAL_INTERRUPT_ENABLE = {1'h1}; + } + + cp_msie: coverpoint instr.rvfi.name_csrs["mie"].wdata[3] { + bins MSIE = {1'h1}; + } + + cp_mtie: coverpoint instr.rvfi.name_csrs["mie"].wdata[7] { + bins MTIE = {1'h1}; + } + + cp_meie: coverpoint instr.rvfi.name_csrs["mie"].wdata[11] { + bins MEIE = {1'h1}; + } + + cp_msip: coverpoint instr.rvfi.name_csrs["mip"].wdata[3] { + bins MSIP = {1'h1}; + } + + cp_mtip: coverpoint instr.rvfi.name_csrs["mip"].wdata[7] { + bins MTIP = {1'h1}; + } + + cp_meip: coverpoint instr.rvfi.name_csrs["mip"].wdata[11] { + bins MEIP = {1'h1}; + } + +endgroup : cg_interrupt + +class uvme_interrupt_covg_c extends uvm_component; + + /* + * Class members + */ + // Objects + uvme_cva6_cfg_c cfg ; + uvme_cva6_cntxt_c cntxt ; + + // TLM + uvm_tlm_analysis_fifo#(uvma_isacov_mon_trn_c) mon_trn_fifo; + + uvma_isacov_mon_trn_c mon_trn; + + `uvm_component_utils(uvme_interrupt_covg_c) + + //Interrupt Covergroup + cg_interrupt interrupt_cg; + + extern function new(string name = "interrupt_covg", uvm_component parent = null); + extern function void build_phase(uvm_phase phase); + extern task run_phase(uvm_phase phase); + +endclass : uvme_interrupt_covg_c + +function uvme_interrupt_covg_c::new(string name = "interrupt_covg", uvm_component parent = null); + + super.new(name, parent); + +endfunction : new + +function void uvme_interrupt_covg_c::build_phase(uvm_phase phase); + + super.build_phase(phase); + + void'(uvm_config_db#(uvme_cva6_cfg_c)::get(this, "", "cfg", cfg)); + if (!cfg) begin + `uvm_fatal("CFG", "Configuration handle is null") + end + + interrupt_cg = new("interrupt_cg"); + + mon_trn_fifo = new("mon_trn_fifo" , this); + +endfunction : build_phase + +task uvme_interrupt_covg_c::run_phase(uvm_phase phase); + + super.run_phase(phase); + + `uvm_info(get_type_name(), "The Interrupt env coverage model is running", UVM_LOW); + + forever begin + mon_trn_fifo.get(mon_trn); + interrupt_cg.sample(mon_trn.instr); + end + +endtask : run_phase + diff --git a/verif/env/uvme/uvma_interrupt/README.md b/verif/env/uvme/uvma_interrupt/README.md new file mode 100644 index 0000000000..2994761f7d --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/README.md @@ -0,0 +1,16 @@ +Description of the interrupt agent. + +- The interrupt agent supports mainly 3 modes: + 1 - The agent sends one interrupt request, then we deassert it. + 2 - The agent sends several interrupt requests at the same time, with the same size, then we deassert the interrupt requests. + 3 - The agent sends randomized interrupt requests. + +- The interrupt agent has 2 type of delays in `uvma_interrupt_seq_item.sv`: + 1 - `irq_delay` is related to the delay between two interrupt request. + 2 - `irq_time` is related to the time the interrupt request could take. + +- The interrupt agent sends requests asynchronously. + +- To enable interrupt requests you should add the option `"+enable_interrupt"`. + +- There is no mechanism to clear the interrupt requests (on going). diff --git a/verif/env/uvme/uvma_interrupt/cov/uvma_interrupt_cov_model.sv b/verif/env/uvme/uvma_interrupt/cov/uvma_interrupt_cov_model.sv new file mode 100644 index 0000000000..b4c152223b --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/cov/uvma_interrupt_cov_model.sv @@ -0,0 +1,111 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_COV_MODEL_SV__ +`define __UVMA_INTERRUPT_COV_MODEL_SV__ + +covergroup cg_interrupt( + string name + ) with function + sample(uvma_interrupt_seq_item_c req_item); + + option.per_instance = 1; + option.name = name; + + cp_interrupt_req : coverpoint req_item.interrupt_valid; + +endgroup: cg_interrupt + +/** + * Component encapsulating Interrupt functional coverage model. + */ +class uvma_interrupt_cov_model_c extends uvm_component; + + // Objects + uvma_interrupt_cfg_c cfg; + uvma_interrupt_cntxt_c cntxt; + + uvma_interrupt_seq_item_c req_item; + + // TLM + uvm_tlm_analysis_fifo#(uvma_interrupt_seq_item_c) seq_item_fifo; + + + `uvm_component_utils_begin(uvma_interrupt_cov_model_c) + `uvm_field_object(cfg , UVM_DEFAULT) + `uvm_field_object(cntxt, UVM_DEFAULT) + `uvm_component_utils_end + + cg_interrupt interrupt_cg; + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_cov_model", uvm_component parent=null); + + /** + * 1. Ensures cfg & cntxt handles are not null. + * 2. Builds fifos. + */ + extern virtual function void build_phase(uvm_phase phase); + + /** + * Forks all sampling loops + */ + extern virtual task run_phase(uvm_phase phase); + +endclass : uvma_interrupt_cov_model_c + + +function uvma_interrupt_cov_model_c::new(string name="uvma_interrupt_cov_model", uvm_component parent=null); + + super.new(name, parent); + +endfunction : new + + +function void uvma_interrupt_cov_model_c::build_phase(uvm_phase phase); + + super.build_phase(phase); + + void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg)); + if (cfg == null) begin + `uvm_fatal("CFG", "Configuration handle is null") + end + + void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt)); + if (cntxt == null) begin + `uvm_fatal("CNTXT", "Context handle is null") + end + + interrupt_cg = new("interrupt_cg"); + + seq_item_fifo = new("seq_item_fifo", this); + +endfunction : build_phase + + +task uvma_interrupt_cov_model_c::run_phase(uvm_phase phase); + + super.run_phase(phase); + + if (cfg.enabled && cfg.cov_model_enabled) begin + + // Sequence items + forever begin + seq_item_fifo.get(req_item); + interrupt_cg.sample(req_item); + end + end + +endtask : run_phase + + +`endif // __UVMA_INTERRUPT_COV_MODEL_SV__ diff --git a/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_base_seq.sv b/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_base_seq.sv new file mode 100644 index 0000000000..9ee875afdd --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_base_seq.sv @@ -0,0 +1,55 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_BASE_SEQ_SV__ +`define __UVMA_INTERRUPT_BASE_SEQ_SV__ + + +/** + * Abstract object from which all other Interrupt agent sequences must extend. + * Subclasses must be run on Interrupt sequencer (uvma_interrupt_sqr_c) instance. + */ +class uvma_interrupt_base_seq_c extends uvm_sequence#(uvma_interrupt_seq_item_c); + + `uvm_object_utils(uvma_interrupt_base_seq_c) + `uvm_declare_p_sequencer(uvma_interrupt_sqr_c) + + // Objects + uvma_interrupt_cfg_c cfg; + uvma_interrupt_cntxt_c cntxt; + + uvma_interrupt_seq_item_c req_item; + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_base_seq"); + + /** + * Assigns cfg and cntxt handles from p_sequencer. + */ + extern virtual task pre_start(); + +endclass : uvma_interrupt_base_seq_c + +function uvma_interrupt_base_seq_c::new(string name="uvma_interrupt_base_seq"); + + super.new(name); + +endfunction : new + +task uvma_interrupt_base_seq_c::pre_start(); + + cfg = p_sequencer.cfg; + cntxt = p_sequencer.cntxt; + +endtask : pre_start + +`endif // __UVMA_INTERRUPT_BASE_SEQ_SV__ diff --git a/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq.sv b/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq.sv new file mode 100644 index 0000000000..93099dacc6 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq.sv @@ -0,0 +1,60 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_SEQ_SV__ +`define __UVMA_INTERRUPT_SEQ_SV__ + + +/** + * Abstract object from which all other Interrupt agent sequences must extend. + * Subclasses must be run on Interrupt sequencer (uvma_interrupt_sqr_c) instance. + */ +class uvma_interrupt_seq_c extends uvma_interrupt_base_seq_c; + + `uvm_object_utils(uvma_interrupt_seq_c) + `uvm_declare_p_sequencer(uvma_interrupt_sqr_c) + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_seq"); + + extern virtual task body(); + +endclass : uvma_interrupt_seq_c + +function uvma_interrupt_seq_c::new(string name="uvma_interrupt_seq"); + + super.new(name); + +endfunction : new + +task uvma_interrupt_seq_c::body(); + + forever begin + req_item = uvma_interrupt_seq_item_c::type_id::create("req_item"); + + start_item(req_item); + assert(req_item.randomize() with { + if(!cfg.enable_interrupt){ + req_item.interrupt_valid == 'h0; + } + else { + req_item.irq_cntrl != UVMA_INTERRUPT_RANDOMIZE; + } + }) + cfg.calc_random_req_latency(); + + finish_item(req_item); + end + +endtask : body + +`endif // __UVMA_INTERRUPT_SEQ_SV__ diff --git a/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq_item.sv b/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq_item.sv new file mode 100644 index 0000000000..50b94bd945 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/seq/uvma_interrupt_seq_item.sv @@ -0,0 +1,66 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_SEQ_ITEM_SV__ +`define __UVMA_INTERRUPT_SEQ_ITEM_SV__ + + +/** + * Object created by Interrupt agent sequences extending uvma_interrupt_seq_base_c. + */ +class uvma_interrupt_seq_item_c extends uvml_trn_seq_item_c; + + rand uvma_interrupt_cntrl_enum irq_cntrl; + rand int unsigned irq_delay; // Delay before applying individual interrupt + rand int unsigned irq_time; // How many cycles take an interrupt + + rand bit[NUM_IRQ-1:0] interrupt_valid; //the valid interrupts for the core under test + + `uvm_object_utils_begin(uvma_interrupt_seq_item_c) + `uvm_field_enum(uvma_interrupt_cntrl_enum, irq_cntrl, UVM_DEFAULT) + `uvm_field_int(irq_delay, UVM_DEFAULT) + `uvm_field_int(irq_time, UVM_DEFAULT) + `uvm_field_int(interrupt_valid, UVM_DEFAULT) + `uvm_object_utils_end + + + constraint default_irq_delay_c { + irq_delay inside {[150:250]}; + } + + constraint default_irq_time_c { + irq_time inside {[5:10]}; + } + + constraint irq_mode_c { + + if (irq_cntrl == UVMA_INTERRUPT_ONE_BY_ONE) { + $countones(interrupt_valid) == 1; + } + if (irq_cntrl == UVMA_INTERRUPT_MORE_THAN_ONE) { + $countones(interrupt_valid) > 1; + } + } + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_seq_item"); + +endclass : uvma_interrupt_seq_item_c + +function uvma_interrupt_seq_item_c::new(string name="uvma_interrupt_seq_item"); + + super.new(name); + +endfunction : new + + +`endif // __UVMA_INTERRUPT_SEQ_ITEM_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_agent.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_agent.sv new file mode 100644 index 0000000000..db891c0dde --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_agent.sv @@ -0,0 +1,182 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_AGENT_SV__ +`define __UVMA_INTERRUPT_AGENT_SV__ + +class uvma_interrupt_agent_c extends uvm_agent; + + // Objects + uvma_interrupt_cfg_c cfg; + uvma_interrupt_cntxt_c cntxt; + + // Components + uvma_interrupt_mon_c monitor; + uvma_interrupt_drv_c driver; + uvma_interrupt_sqr_c sequencer; + uvma_interrupt_cov_model_c cov_model; + + `uvm_component_utils_begin(uvma_interrupt_agent_c) + `uvm_field_object(cfg , UVM_DEFAULT) + `uvm_field_object(cntxt, UVM_DEFAULT) + `uvm_component_utils_end + + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_agent", uvm_component parent=null); + + /** + * 1. Ensures cfg & cntxt handles are not null + * 2. Builds all components + */ + extern virtual function void build_phase(uvm_phase phase); + + /** + * 1. Links agent's analysis ports to sub-components' + * 2. Connects coverage models and loggers + */ + extern virtual function void connect_phase(uvm_phase phase); + + /** + * Uses uvm_config_db to retrieve cfg and hand out to sub-components. + */ + extern function void get_and_set_cfg(); + + /** + * Uses uvm_config_db to retrieve cntxt and hand out to sub-components. + */ + extern function void get_and_set_cntxt(); + + /** + * Uses uvm_config_db to retrieve the Virtual Interface (vif) associated with this + * agent. + */ + extern function void retrieve_vif(); + + /** + * Creates sub-components. + */ + extern function void create_components(); + + /** + * Connects sequencer and driver's TLM port(s). + */ + extern function void connect_sequencer_and_driver(); + + /** + * Connects coverage model to monitor and driver's analysis ports. + */ + extern function void connect_cov_model(); + +endclass : uvma_interrupt_agent_c + + +function uvma_interrupt_agent_c::new(string name="uvma_interrupt_agent", uvm_component parent=null); + + super.new(name, parent); + +endfunction : new + + +function void uvma_interrupt_agent_c::build_phase(uvm_phase phase); + + super.build_phase(phase); + + get_and_set_cfg (); + get_and_set_cntxt(); + retrieve_vif (); + create_components(); + +endfunction : build_phase + + +function void uvma_interrupt_agent_c::connect_phase(uvm_phase phase); + + super.connect_phase(phase); + + connect_sequencer_and_driver(); + connect_cov_model(); + +endfunction: connect_phase + + +function void uvma_interrupt_agent_c::get_and_set_cfg(); + + void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg)); + if (cfg == null) begin + `uvm_fatal("CFG", "Configuration handle is null") + end + else begin + `uvm_info("CFG", $sformatf("Found configuration handle:\n%s", cfg.sprint()), UVM_DEBUG) + uvm_config_db#(uvma_interrupt_cfg_c)::set(this, "*", "cfg", cfg); + end + +endfunction : get_and_set_cfg + + +function void uvma_interrupt_agent_c::get_and_set_cntxt(); + + void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt)); + if (cntxt == null) begin + `uvm_info("CNTXT", "Context handle is null; creating.", UVM_DEBUG) + cntxt = uvma_interrupt_cntxt_c::type_id::create("cntxt"); + end + uvm_config_db#(uvma_interrupt_cntxt_c)::set(this, "*", "cntxt", cntxt); + +endfunction : get_and_set_cntxt + + +function void uvma_interrupt_agent_c::retrieve_vif(); + + if (!uvm_config_db#(virtual uvma_interrupt_if)::get(this, "", "interrupt_vif", cntxt.interrupt_vif)) begin + `uvm_fatal("VIF", $sformatf("Could not find vif handle of type %s in uvm_config_db", $typename(cntxt.interrupt_vif))) + end + else begin + `uvm_info("VIF", $sformatf("Found vif handle of type %s in uvm_config_db", $typename(cntxt.interrupt_vif)), UVM_DEBUG) + end + +endfunction : retrieve_vif + + +function void uvma_interrupt_agent_c::create_components(); + + monitor = uvma_interrupt_mon_c ::type_id::create("monitor" , this); + if (cfg.is_active == UVM_ACTIVE) begin + sequencer = uvma_interrupt_sqr_c ::type_id::create("sequencer" , this); + driver = uvma_interrupt_drv_c ::type_id::create("driver" , this); + end + if (cfg.cov_model_enabled) begin + cov_model = uvma_interrupt_cov_model_c ::type_id::create("cov_model" , this); + end + +endfunction : create_components + + +function void uvma_interrupt_agent_c::connect_sequencer_and_driver(); + + if (cfg.is_active == UVM_ACTIVE) begin + driver.seq_item_port.connect(sequencer.seq_item_export); + end + +endfunction : connect_sequencer_and_driver + + +function void uvma_interrupt_agent_c::connect_cov_model(); + + if (cfg.cov_model_enabled) begin + monitor.ap.connect(cov_model.seq_item_fifo.analysis_export); + end + +endfunction : connect_cov_model + + +`endif // __UVMA_INTERRUPT_AGENT_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_cfg.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_cfg.sv new file mode 100644 index 0000000000..7b6f73e652 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_cfg.sv @@ -0,0 +1,115 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_CFG_SV__ +`define __UVMA_INTERRUPT_CFG_SV__ + + +class uvma_interrupt_cfg_c extends uvm_object; + + // Common options + rand bit enabled; + rand uvm_active_passive_enum is_active; + + rand bit cov_model_enabled; + rand bit trn_log_enabled; + + rand bit enable_interrupt; + bit interrupt_plusarg_valid; + + // Interrupt request latency modes + rand uvma_interrupt_drv_req_enum drv_req_mode; + rand int unsigned drv_req_fixed_latency; + rand int unsigned drv_req_random_latency_min; + rand int unsigned drv_req_random_latency_max; + + `uvm_object_utils_begin(uvma_interrupt_cfg_c) + `uvm_field_int ( enabled , UVM_DEFAULT) + `uvm_field_enum(uvm_active_passive_enum, is_active , UVM_DEFAULT) + `uvm_field_int ( cov_model_enabled , UVM_DEFAULT) + `uvm_field_int ( trn_log_enabled , UVM_DEFAULT) + `uvm_field_int ( enable_interrupt , UVM_DEFAULT) + `uvm_field_int ( interrupt_plusarg_valid , UVM_DEFAULT) + `uvm_field_enum(uvma_interrupt_drv_req_enum, drv_req_mode , UVM_DEFAULT) + `uvm_field_int ( drv_req_fixed_latency , UVM_DEFAULT) + `uvm_field_int ( drv_req_random_latency_min , UVM_DEFAULT) + `uvm_field_int ( drv_req_random_latency_max , UVM_DEFAULT) + `uvm_object_utils_end + + + constraint defaults_cons { + soft enabled == 1; + soft is_active == UVM_PASSIVE; + soft cov_model_enabled == 1; + soft trn_log_enabled == 1; + + } + + constraint default_enable_irq_cons { + soft enable_interrupt == 0; + } + + constraint default_drive_req_mode_cons { + soft drv_req_mode == UVMA_INTERRUPT_DRV_REQ_MODE_FIXED_LATENCY; + } + + constraint default_fixed_req_latency_cons { + soft drv_req_fixed_latency inside {[250:300]}; + } + + constraint valid_random_req_latency_cons { + drv_req_random_latency_min < drv_req_random_latency_max; + } + + constraint default_random_latency_cons { + soft drv_req_random_latency_min inside {[50:100]}; + soft drv_req_random_latency_max inside {[150:200]}; + } + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_cfg"); + + /** + * Calculate a new random gnt latency + */ + extern function int unsigned calc_random_req_latency(); + +endclass : uvma_interrupt_cfg_c + +function uvma_interrupt_cfg_c::new(string name="uvma_interrupt_cfg"); + + super.new(name); + + // Read plusargs for defaults + if ($test$plusargs("enable_interrupt")) begin + interrupt_plusarg_valid = 1; + end + +endfunction : new + +function int unsigned uvma_interrupt_cfg_c::calc_random_req_latency(); + + int unsigned req_latency; + + case (drv_req_mode) + UVMA_INTERRUPT_DRV_REQ_MODE_CONSTANT : req_latency = 0; + UVMA_INTERRUPT_DRV_REQ_MODE_FIXED_LATENCY : req_latency = drv_req_fixed_latency; + UVMA_INTERRUPT_DRV_REQ_MODE_RANDOM_LATENCY: begin + req_latency = $urandom_range(drv_req_random_latency_min, drv_req_random_latency_max); + end + endcase + + return req_latency; + +endfunction : calc_random_req_latency + +`endif // __UVMA_INTERRUPT_CFG_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_cntxt.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_cntxt.sv new file mode 100644 index 0000000000..84a2611199 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_cntxt.sv @@ -0,0 +1,68 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_CNTXT_SV__ +`define __UVMA_INTERRUPT_CNTXT_SV__ + + +/** + * Object encapsulating all state variables for all Interrupt agent + * (uvma_interrupt_agent_c) components. + */ +class uvma_interrupt_cntxt_c extends uvm_object; + + // Handle to agent interface + virtual uvma_interrupt_if interrupt_vif; + + // Events + uvm_event sample_cfg_e; + uvm_event sample_cntxt_e; + + `uvm_object_utils_begin(uvma_interrupt_cntxt_c) + `uvm_field_event(sample_cfg_e , UVM_DEFAULT) + `uvm_field_event(sample_cntxt_e, UVM_DEFAULT) + `uvm_object_utils_end + + /** + * Builds events. + */ + extern function new(string name="uvma_interrupt_cntxt"); + + /** + * TODO Describe uvma_interrupt_cntxt_c::reset() + */ + extern function void reset(); + +endclass : uvma_interrupt_cntxt_c + + +`pragma protect begin + + +function uvma_interrupt_cntxt_c::new(string name="uvma_interrupt_cntxt"); + + super.new(name); + + sample_cfg_e = new("sample_cfg_e" ); + sample_cntxt_e = new("sample_cntxt_e"); + +endfunction : new + +function void uvma_interrupt_cntxt_c::reset(); + + // TODO Implement uvma_interrupt_cntxt_c::reset() + +endfunction : reset + + +`pragma protect end + + +`endif // __UVMA_INTERRUPT_CNTXT_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_constants.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_constants.sv new file mode 100644 index 0000000000..9b93f91d13 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_constants.sv @@ -0,0 +1,14 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + +`ifndef __UVMA_INTERRUPT_CONSTANTS_SV__ +`define __UVMA_INTERRUPT_CONSTANTS_SV__ + + +`endif // __UVMA_INTERRUPT_CONSTANTS_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_drv.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_drv.sv new file mode 100644 index 0000000000..45c949aeaa --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_drv.sv @@ -0,0 +1,165 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + +`ifndef __UVMA_INTERRUPT_DRV_SV__ +`define __UVMA_INTERRUPT_DRV_SV__ + +/** + * Component driving interrupt virtual interface (uvma_interrupt_if). + */ +class uvma_interrupt_drv_c extends uvm_driver#(uvma_interrupt_seq_item_c); + + // Objects + uvma_interrupt_cfg_c cfg; + uvma_interrupt_cntxt_c cntxt; + + uvma_interrupt_seq_item_c req_item; + + `uvm_component_utils_begin(uvma_interrupt_drv_c) + `uvm_field_object(cfg , UVM_DEFAULT) + `uvm_field_object(cntxt, UVM_DEFAULT) + `uvm_component_utils_end + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_drv", uvm_component parent=null); + + /** + * 1. Ensures cfg & cntxt handles are not null. + * 2. Builds ap. + */ + extern virtual function void build_phase(uvm_phase phase); + + /** + * Obtains the reqs from the sequence item port and calls drv_irq() + */ + extern virtual task run_phase(uvm_phase phase); + + /** + * Drives the virtual interface's (cntxt.interrupt_vif) signals using req's contents. + */ + extern task drv_irq(uvma_interrupt_seq_item_c req); + + /** + * Assert only one interrupt each time + */ + extern task assert_irq_one_by_one(uvma_interrupt_seq_item_c req); + + /** + * Assert one or more interrupt each time + */ + extern task assert_irq_more(uvma_interrupt_seq_item_c req); + + /** + * Randomize interrupt signal + */ + extern task assert_irq_randomize(uvma_interrupt_seq_item_c req); + +endclass : uvma_interrupt_drv_c + +function uvma_interrupt_drv_c::new(string name="uvma_interrupt_drv", uvm_component parent=null); + + super.new(name, parent); + +endfunction : new + + +function void uvma_interrupt_drv_c::build_phase(uvm_phase phase); + + super.build_phase(phase); + + void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg)); + if (cfg == null) begin + `uvm_fatal("CFG", "Configuration handle is null") + end + uvm_config_db#(uvma_interrupt_cfg_c)::set(this, "*", "cfg", cfg); + + void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt)); + if (cntxt == null) begin + `uvm_fatal("CNTXT", "Context handle is null") + end + uvm_config_db#(uvma_interrupt_cntxt_c)::set(this, "*", "cntxt", cntxt); + + req_item = uvma_interrupt_seq_item_c::type_id::create("req_item"); + +endfunction : build_phase + +task uvma_interrupt_drv_c::run_phase(uvm_phase phase); + + super.run_phase(phase); + + //Initial the interface before the CPU start + cntxt.interrupt_vif.irq <= 'h0; + + if(!cfg.enable_interrupt) begin + `uvm_warning(get_type_name(), "Driving Interrupt reqeust is disabled"); + return; + end + + forever begin + + seq_item_port.get_next_item(req_item); + drv_irq(req_item); + seq_item_port.item_done(); + + end + +endtask : run_phase + +task uvma_interrupt_drv_c::drv_irq(uvma_interrupt_seq_item_c req); + `uvm_info(get_type_name(), $sformatf("Driving:\n%s", req.sprint()), UVM_HIGH); + + case (req.irq_cntrl) + UVMA_INTERRUPT_ONE_BY_ONE: begin + assert_irq_one_by_one(req); + end + UVMA_INTERRUPT_MORE_THAN_ONE: begin + assert_irq_more(req); + end + UVMA_INTERRUPT_RANDOMIZE: begin + assert_irq_randomize(req); + end + endcase + +endtask : drv_irq + +task uvma_interrupt_drv_c::assert_irq_one_by_one(uvma_interrupt_seq_item_c req); + + #req.irq_delay; + cntxt.interrupt_vif.irq <= req.interrupt_valid; + `uvm_info(get_type_name(), $sformatf("Assert interrupt channel(s) %0b", req.interrupt_valid), UVM_HIGH) + #req.irq_time; + cntxt.interrupt_vif.irq <= 'h0; + +endtask : assert_irq_one_by_one + +task uvma_interrupt_drv_c::assert_irq_more(uvma_interrupt_seq_item_c req); + + #req.irq_delay; + cntxt.interrupt_vif.irq <= req.interrupt_valid; + #req.irq_time; + cntxt.interrupt_vif.irq <= 'h0; + +endtask : assert_irq_more + +task uvma_interrupt_drv_c::assert_irq_randomize(uvma_interrupt_seq_item_c req); + + repeat(5) begin + #req.irq_delay; + cntxt.interrupt_vif.irq <= req.interrupt_valid; + #req.irq_time; + end + + cntxt.interrupt_vif.irq <= 'h0; + cfg.calc_random_req_latency(); + +endtask : assert_irq_randomize + +`endif // __UVMA_INTERRUPT_DRV_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_if.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_if.sv new file mode 100644 index 0000000000..57ac09a534 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_if.sv @@ -0,0 +1,28 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_IF_SV__ +`define __UVMA_INTERRUPT_IF_SV__ + + +/** + * Encapsulates all signals and clocking of Interrupt interface. Used by + * monitor and driver. + */ +interface uvma_interrupt_if + ( + ); + + logic [uvma_interrupt_pkg::NUM_IRQ-1:0] irq; + +endinterface : uvma_interrupt_if + + +`endif // __UVMA_INTERRUPT_IF_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_macros.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_macros.sv new file mode 100644 index 0000000000..fb2d8902ff --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_macros.sv @@ -0,0 +1,25 @@ +// Copyright 2020 OpenHW Group +// Copyright 2020 Datum Technology Corporation +// Copyright 2020 Silicon Labs, Inc. +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://solderpad.org/licenses/ +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +`ifndef __UVMA_INTERRUPT_MACROS_SV__ +`define __UVMA_INTERRUPT_MACROS_SV__ + + + + + +`endif // __UVMA_INTERRUPT_MACROS_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_mon.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_mon.sv new file mode 100644 index 0000000000..4334314352 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_mon.sv @@ -0,0 +1,114 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + +`ifndef __UVMA_INTERRUPT_MON_SV__ +`define __UVMA_INTERRUPT_MON_SV__ + +class uvma_interrupt_mon_c extends uvm_monitor; + + // Objects + uvma_interrupt_cfg_c cfg; + uvma_interrupt_cntxt_c cntxt; + + `uvm_component_utils_begin(uvma_interrupt_mon_c) + `uvm_field_object(cfg , UVM_DEFAULT) + `uvm_field_object(cntxt, UVM_DEFAULT) + `uvm_component_utils_end + + // TLM + uvm_analysis_port #(uvma_interrupt_seq_item_c) ap; + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_mon", uvm_component parent=null); + + /** + * 1. Ensures cfg & cntxt handles are not null. + * 2. Builds ap. + */ + extern virtual function void build_phase(uvm_phase phase); + + /** + * Oversees monitoring via monitor_clk() and monitor_reset() tasks in parallel + * forks. + */ + extern virtual task run_phase(uvm_phase phase); + + /** + * Monitor interrupt + */ + extern virtual task mon_irq(); + +endclass : uvma_interrupt_mon_c + + /** + * Default constructor. + */ + function uvma_interrupt_mon_c::new(string name = "uvma_interrupt_mon", uvm_component parent); + super.new(name, parent); + + endfunction + + /** + * 1. Ensures cfg & cntxt handles are not null. + * 2. Builds ap. + */ + function void uvma_interrupt_mon_c::build_phase(uvm_phase phase); + + super.build_phase(phase); + + void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt)); + if (cntxt == null) begin + `uvm_fatal("build_phase", "monitor cntxt class failed") + end + + void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg)); + if (cfg == null) begin + `uvm_fatal("CFG", "Configuration handle is null") + end + + ap = new("ap", this); + + endfunction + + /** + * TODO Describe uvma_interrupt_mon_c::run_phase() + */ + task uvma_interrupt_mon_c::run_phase(uvm_phase phase); + super.run_phase(phase); + + fork + begin + mon_irq(); + end + join_none + + endtask: run_phase + + /** + * TODO Describe uvma_interrupt_mon_c::mon_post_reset() + */ + task uvma_interrupt_mon_c::mon_irq(); + + uvma_interrupt_seq_item_c irq_item; + + while(1) begin + @(cntxt.interrupt_vif.irq); + + irq_item = uvma_interrupt_seq_item_c::type_id::create("irq_item"); + irq_item.interrupt_valid = cntxt.interrupt_vif.irq; + `uvm_info(get_type_name(), $sformatf("monitor interrupt : %0d", irq_item.interrupt_valid), UVM_LOW) + ap.write(irq_item); + + end + + endtask: mon_irq + +`endif diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.flist b/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.flist new file mode 100644 index 0000000000..f5a11c792d --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.flist @@ -0,0 +1,17 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +// Directories ++incdir+${DV_UVMA_INTERRUPT_PATH} ++incdir+${DV_UVMA_INTERRUPT_PATH}/cov ++incdir+${DV_UVMA_INTERRUPT_PATH}/seq + +// Files +${DV_UVMA_INTERRUPT_PATH}/uvma_interrupt_pkg.sv diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv new file mode 100644 index 0000000000..fd520eaf24 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_pkg.sv @@ -0,0 +1,61 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_PKG_SV__ +`define __UVMA_INTERRUPT_PKG_SV__ + + +// Pre-processor macros +`include "uvm_macros.svh" +`include "uvml_hrtbt_macros.sv" +`include "uvma_interrupt_macros.sv" + +/** + * Encapsulates all the types needed for an UVM agent capable of driving and/or + * monitoring Clock & Reset. + */ + +package uvma_interrupt_pkg; + + import uvm_pkg ::*; + import uvml_hrtbt_pkg::*; + import uvml_trn_pkg ::*; + import uvml_logs_pkg ::*; + + parameter NUM_IRQ = 3; + + // Constants / Structs / Enums + `include "uvma_interrupt_constants.sv" + `include "uvma_interrupt_tdefs.sv" + + // Objects + `include "uvma_interrupt_cfg.sv" + `include "uvma_interrupt_cntxt.sv" + + // High-level transactions + `include "uvma_interrupt_seq_item.sv" + + // Agent components + `include "uvma_interrupt_cov_model.sv" + `include "uvma_interrupt_mon.sv" + `include "uvma_interrupt_drv.sv" + `include "uvma_interrupt_sqr.sv" + `include "uvma_interrupt_agent.sv" + + // Sequences + `include "uvma_interrupt_base_seq.sv" + `include "uvma_interrupt_seq.sv" + +endpackage : uvma_interrupt_pkg + + // Interface(s) / Module(s) / Checker(s) + `include "uvma_interrupt_if.sv" + +`endif // __UVMA_INTERRUPT_PKG_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_sqr.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_sqr.sv new file mode 100644 index 0000000000..37b0a41cbe --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_sqr.sv @@ -0,0 +1,77 @@ +// +// Copyright 2020 OpenHW Group +// Copyright 2020 Datum Technology Corporation +// Copyright 2020 Silicon Labs, Inc. +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + + +`ifndef __UVMA_INTERRUPT_SQR_SV__ +`define __UVMA_INTERRUPT_SQR_SV__ + + +/** + * Component running interrupt sequences extending uvma_interrupt_seq_base_c. + * Provides sequence items for uvma_interrupt_drv_c. + */ +class uvma_interrupt_sqr_c extends uvm_sequencer#(uvma_interrupt_seq_item_c); + + // Objects + uvma_interrupt_cfg_c cfg; + uvma_interrupt_cntxt_c cntxt; + + // Analysis port to receive + uvm_tlm_analysis_fifo #(uvma_interrupt_seq_item_c) mm_req_fifo; + + `uvm_component_utils_begin(uvma_interrupt_sqr_c) + `uvm_field_object(cfg , UVM_DEFAULT) + `uvm_field_object(cntxt, UVM_DEFAULT) + `uvm_component_utils_end + + + /** + * Default constructor. + */ + extern function new(string name="uvma_interrupt_sqr", uvm_component parent=null); + + /** + * Ensures cfg & cntxt handles are not null + */ + extern virtual function void build_phase(uvm_phase phase); + +endclass : uvma_interrupt_sqr_c + + +function uvma_interrupt_sqr_c::new(string name="uvma_interrupt_sqr", uvm_component parent=null); + + super.new(name, parent); + +endfunction : new + + +function void uvma_interrupt_sqr_c::build_phase(uvm_phase phase); + + super.build_phase(phase); + + void'(uvm_config_db#(uvma_interrupt_cfg_c)::get(this, "", "cfg", cfg)); + if (cfg == null) begin + `uvm_fatal("CFG", "Configuration handle is null") + end + + void'(uvm_config_db#(uvma_interrupt_cntxt_c)::get(this, "", "cntxt", cntxt)); + if (cntxt == null) begin + `uvm_fatal("CNTXT", "Context handle is null") + end + + mm_req_fifo = new("mm_req_fifo", this); + +endfunction : build_phase + + +`endif // __UVMA_INTERRUPT_SQR_SV__ diff --git a/verif/env/uvme/uvma_interrupt/uvma_interrupt_tdefs.sv b/verif/env/uvme/uvma_interrupt/uvma_interrupt_tdefs.sv new file mode 100644 index 0000000000..c054f98b16 --- /dev/null +++ b/verif/env/uvme/uvma_interrupt/uvma_interrupt_tdefs.sv @@ -0,0 +1,25 @@ +// Copyright 2024 Thales DIS SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + +`ifndef __UVMA_INTERRUPT_TDEFS_SV__ +`define __UVMA_INTERRUPT_TDEFS_SV__ + +typedef enum { + UVMA_INTERRUPT_ONE_BY_ONE, + UVMA_INTERRUPT_MORE_THAN_ONE, + UVMA_INTERRUPT_RANDOMIZE +} uvma_interrupt_cntrl_enum; + +typedef enum { + UVMA_INTERRUPT_DRV_REQ_MODE_CONSTANT, + UVMA_INTERRUPT_DRV_REQ_MODE_FIXED_LATENCY, + UVMA_INTERRUPT_DRV_REQ_MODE_RANDOM_LATENCY +} uvma_interrupt_drv_req_enum; + +`endif // __UVMA_INTERRUPT_TDEFS_SV__ diff --git a/verif/env/uvme/uvme_cva6_cfg.sv b/verif/env/uvme/uvme_cva6_cfg.sv index 51b9315982..79a0ed00f0 100644 --- a/verif/env/uvme/uvme_cva6_cfg.sv +++ b/verif/env/uvme/uvme_cva6_cfg.sv @@ -34,8 +34,6 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; rand bit scoreboard_enabled; rand bit tandem_enabled; rand bit cov_model_enabled; - rand bit cov_cvxif_model_enabled; - rand bit cov_isa_model_enabled; rand bit trn_log_enabled; rand int unsigned sys_clk_period; @@ -45,6 +43,7 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; rand uvma_axi_cfg_c axi_cfg; rand uvma_rvfi_cfg_c#(ILEN,XLEN) rvfi_cfg; rand uvma_isacov_cfg_c isacov_cfg; + rand uvma_interrupt_cfg_c interrupt_cfg; // Zicond extension rand bit ext_zicond_supported; @@ -84,6 +83,8 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; `uvm_field_object(isacov_cfg, UVM_DEFAULT) + `uvm_field_object(interrupt_cfg, UVM_DEFAULT) + `uvm_object_utils_end @@ -185,11 +186,20 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; (!dm_exception_addr_plusarg_valid) -> (dm_exception_addr == 'h0000_0000); } + constraint default_interrupt_cons { + if (interrupt_cfg.interrupt_plusarg_valid) { + interrupt_cfg.enable_interrupt == 'h1; + } + else + interrupt_cfg.enable_interrupt == 'h0; + } + constraint agent_cfg_cons { if (enabled) { - clknrst_cfg.enabled == 1; - isacov_cfg.enabled == 1; - rvfi_cfg.enabled == 1; + clknrst_cfg.enabled == 1; + isacov_cfg.enabled == 1; + rvfi_cfg.enabled == 1; + interrupt_cfg.enabled == 1; } isacov_cfg.seq_instr_group_x2_enabled == 1; @@ -203,9 +213,10 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; axi_cfg.rand_channel_delay_enabled == 0; if (is_active == UVM_ACTIVE) { - clknrst_cfg.is_active == UVM_ACTIVE; - isacov_cfg.is_active == UVM_PASSIVE; - rvfi_cfg.is_active == UVM_PASSIVE; + clknrst_cfg.is_active == UVM_ACTIVE; + isacov_cfg.is_active == UVM_PASSIVE; + rvfi_cfg.is_active == UVM_PASSIVE; + interrupt_cfg.is_active == UVM_ACTIVE; } if (trn_log_enabled) { @@ -216,12 +227,10 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; } if (cov_model_enabled) { - cvxif_cfg.cov_model_enabled == 1; - isacov_cfg.cov_model_enabled == 1; - axi_cfg.cov_model_enabled == 1; - //env coverage models - cov_cvxif_model_enabled == 1; - cov_isa_model_enabled == 1; + cvxif_cfg.cov_model_enabled == 1; + isacov_cfg.cov_model_enabled == 1; + axi_cfg.cov_model_enabled == 1; + interrupt_cfg.cov_model_enabled == 1; } } @@ -253,6 +262,7 @@ function uvme_cva6_cfg_c::new(string name="uvme_cva6_cfg"); axi_cfg = uvma_axi_cfg_c::type_id::create("axi_cfg"); rvfi_cfg = uvma_rvfi_cfg_c#(ILEN,XLEN)::type_id::create("rvfi_cfg"); isacov_cfg = uvma_isacov_cfg_c::type_id::create("isacov_cfg"); + interrupt_cfg = uvma_interrupt_cfg_c::type_id::create("interrupt_cfg"); isacov_cfg.core_cfg = this; rvfi_cfg.core_cfg = this; diff --git a/verif/env/uvme/uvme_cva6_cntxt.sv b/verif/env/uvme/uvme_cva6_cntxt.sv index d06bdf57de..0ad5a5bfcb 100644 --- a/verif/env/uvme/uvme_cva6_cntxt.sv +++ b/verif/env/uvme/uvme_cva6_cntxt.sv @@ -35,6 +35,7 @@ class uvme_cva6_cntxt_c extends uvm_object; uvma_axi_cntxt_c axi_cntxt; uvma_cva6_core_cntrl_cntxt_c core_cntrl_cntxt; uvma_rvfi_cntxt_c rvfi_cntxt; + uvma_interrupt_cntxt_c interrupt_cntxt; // Memory modelling rand uvml_mem_cva6 mem; @@ -49,6 +50,7 @@ class uvme_cva6_cntxt_c extends uvm_object; `uvm_field_object(axi_cntxt, UVM_DEFAULT) `uvm_field_object(core_cntrl_cntxt, UVM_DEFAULT) `uvm_field_object(rvfi_cntxt, UVM_DEFAULT) + `uvm_field_object(interrupt_cntxt, UVM_DEFAULT) `uvm_field_event(sample_cfg_e , UVM_DEFAULT) `uvm_field_event(sample_cntxt_e, UVM_DEFAULT) `uvm_field_object(mem, UVM_DEFAULT) @@ -75,6 +77,7 @@ function uvme_cva6_cntxt_c::new(string name="uvme_cva6_cntxt"); axi_cntxt = uvma_axi_cntxt_c::type_id::create("axi_cntxt"); mem = uvml_mem_cva6::type_id::create("mem"); rvfi_cntxt = uvma_rvfi_cntxt_c#()::type_id::create("rvfi_cntxt"); + interrupt_cntxt = uvma_interrupt_cntxt_c::type_id::create("interrupt_cntxt"); sample_cfg_e = new("sample_cfg_e" ); sample_cntxt_e = new("sample_cntxt_e"); diff --git a/verif/env/uvme/uvme_cva6_env.sv b/verif/env/uvme/uvme_cva6_env.sv index 4f535b7ce5..8a25ef2de3 100644 --- a/verif/env/uvme/uvme_cva6_env.sv +++ b/verif/env/uvme/uvme_cva6_env.sv @@ -47,6 +47,7 @@ class uvme_cva6_env_c extends uvm_env; uvma_cva6_core_cntrl_agent_c core_cntrl_agent; uvma_rvfi_agent_c#(ILEN,XLEN) rvfi_agent; uvma_isacov_agent_c#(ILEN,XLEN) isacov_agent; + uvma_interrupt_agent_c interrupt_agent; // Handle to agent switch interface virtual uvmt_axi_switch_intf axi_switch_vif; @@ -258,6 +259,8 @@ function void uvme_cva6_env_c::assign_cfg(); uvm_config_db#(uvma_core_cntrl_cfg_c)::set(this, "*rvfi_scoreboard", "cfg", cfg); uvm_config_db#(uvma_core_cntrl_cfg_c)::set(this, "reference_model", "cfg", cfg); + uvm_config_db#(uvma_interrupt_cfg_c)::set(this, "*interrupt_agent", "cfg", cfg.interrupt_cfg); + endfunction: assign_cfg @@ -267,6 +270,7 @@ function void uvme_cva6_env_c::assign_cntxt(); uvm_config_db#(uvma_clknrst_cntxt_c)::set(this, "clknrst_agent", "cntxt", cntxt.clknrst_cntxt); uvm_config_db#(uvma_axi_cntxt_c)::set(this, "axi_agent", "cntxt", cntxt.axi_cntxt); uvm_config_db#(uvma_rvfi_cntxt_c)::set(this, "rvfi_agent", "cntxt", cntxt.rvfi_cntxt); + uvm_config_db#(uvma_interrupt_cntxt_c)::set(this, "interrupt_agent", "cntxt", cntxt.interrupt_cntxt); endfunction: assign_cntxt @@ -279,6 +283,7 @@ function void uvme_cva6_env_c::create_agents(); core_cntrl_agent = uvma_cva6_core_cntrl_agent_c::type_id::create("core_cntrl_agent", this); rvfi_agent = uvma_rvfi_agent_c#(ILEN,XLEN)::type_id::create("rvfi_agent", this); isacov_agent = uvma_isacov_agent_c#(ILEN,XLEN)::type_id::create("isacov_agent", this); + interrupt_agent = uvma_interrupt_agent_c::type_id::create("interrupt_agent", this); endfunction: create_agents @@ -358,6 +363,7 @@ function void uvme_cva6_env_c::assemble_vsequencer(); vsequencer.clknrst_sequencer = clknrst_agent.sequencer; vsequencer.cvxif_vsequencer = cvxif_agent.vsequencer; vsequencer.axi_vsequencer = axi_agent.vsequencer; + vsequencer.interrupt_sequencer = interrupt_agent.sequencer; endfunction: assemble_vsequencer @@ -379,15 +385,23 @@ task uvme_cva6_env_c::run_phase(uvm_phase phase); axi_vseq.start(axi_agent.vsequencer); end end + + begin + if(cfg.interrupt_cfg.is_active == UVM_ACTIVE) begin + uvma_interrupt_seq_c interrupt_seq; + interrupt_seq = uvma_interrupt_seq_c::type_id::create("interrupt_seq"); + interrupt_seq.start(interrupt_agent.sequencer); + end + end join_none endtask function void uvme_cva6_env_c::connect_coverage_model(); - if (cfg.cov_cvxif_model_enabled) begin + if (cfg.cvxif_cfg.cov_model_enabled) begin cvxif_agent.monitor.req_ap.connect(cov_model.cvxif_covg.req_item_fifo.analysis_export); end - if (cfg.cov_isa_model_enabled) begin + if (cfg.isacov_cfg.cov_model_enabled) begin isacov_agent.monitor.ap.connect(cov_model.isa_covg.mon_trn_fifo.analysis_export); isacov_agent.monitor.ap.connect(cov_model.illegal_covg.mon_trn_fifo.analysis_export); isacov_agent.monitor.ap.connect(cov_model.exception_covg.mon_trn_fifo.analysis_export); @@ -408,6 +422,10 @@ function void uvme_cva6_env_c::connect_coverage_model(); axi_agent.monitor.m_axi_superset_write_req_packets_collected.connect(cov_model.axi_ext_covg.uvme_axi_cov_aw_req_fifo.analysis_export); end + if(cfg.interrupt_cfg.cov_model_enabled) begin + isacov_agent.monitor.ap.connect(cov_model.interrupt_covg.mon_trn_fifo.analysis_export); + end + endfunction: connect_coverage_model `endif // __UVME_CVA6_ENV_SV__ diff --git a/verif/env/uvme/uvme_cva6_pkg.flist b/verif/env/uvme/uvme_cva6_pkg.flist index 3f38acb01f..4d8cf4274a 100644 --- a/verif/env/uvme/uvme_cva6_pkg.flist +++ b/verif/env/uvme/uvme_cva6_pkg.flist @@ -22,6 +22,7 @@ +incdir+${CVA6_UVME_PATH}/cov +incdir+${CVA6_UVME_PATH}/vseq +incdir+${CVA6_UVME_PATH}/cvxif_vseq ++incdir+${CVA6_UVME_PATH}/uvma_interrupt // Files ${CVA6_UVME_PATH}/uvme_cva6_pkg.sv diff --git a/verif/env/uvme/uvme_cva6_pkg.sv b/verif/env/uvme/uvme_cva6_pkg.sv index 12331fdc21..3093b6c94b 100644 --- a/verif/env/uvme/uvme_cva6_pkg.sv +++ b/verif/env/uvme/uvme_cva6_pkg.sv @@ -54,7 +54,9 @@ package uvme_cva6_pkg; import uvmc_rvfi_scoreboard_pkg::*; import uvmc_rvfi_reference_model_pkg::*; import uvma_isacov_pkg::*; + import uvma_interrupt_pkg::*; import config_pkg::*; + import "DPI-C" function void read_elf(input string filename); import "DPI-C" function byte get_section(output longint address, output longint len); import "DPI-C" context function void read_section_sv(input longint address, inout byte buffer[]); @@ -102,6 +104,7 @@ package uvme_cva6_pkg; `include "uvme_isa_covg.sv" `include "uvme_illegal_instr_covg.sv" `include "uvme_exception_covg.sv" + `include "uvme_interrupt_covg.sv" `include "uvme_cva6_config_covg.sv" `include "uvme_axi_covg.sv" `include "uvme_axi_ext_covg.sv" diff --git a/verif/env/uvme/uvme_cva6_vsqr.sv b/verif/env/uvme/uvme_cva6_vsqr.sv index 221d4765f8..aaef996f12 100644 --- a/verif/env/uvme/uvme_cva6_vsqr.sv +++ b/verif/env/uvme/uvme_cva6_vsqr.sv @@ -35,9 +35,10 @@ class uvme_cva6_vsqr_c extends uvm_sequencer#( uvme_cva6_cntxt_c cntxt; // Sequencer handles - uvma_clknrst_sqr_c clknrst_sequencer; - uvma_cvxif_vsqr_c cvxif_vsequencer; - uvma_axi_vsqr_c axi_vsequencer; + uvma_clknrst_sqr_c clknrst_sequencer; + uvma_cvxif_vsqr_c cvxif_vsequencer; + uvma_axi_vsqr_c axi_vsequencer; + uvma_interrupt_sqr_c interrupt_sequencer; `uvm_component_utils_begin(uvme_cva6_vsqr_c) diff --git a/verif/regress/dv-interrupt-test.sh b/verif/regress/dv-interrupt-test.sh new file mode 100644 index 0000000000..84839acce8 --- /dev/null +++ b/verif/regress/dv-interrupt-test.sh @@ -0,0 +1,42 @@ +# Copyright 2023 Thales DIS +# +# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +# You may obtain a copy of the License at https://solderpad.org/licenses/ +# +# Original Author: Ayoub JALALI - Thales + +if [ -n "$RISCV_ZCB" ]; then + echo "Using RISCV_ZCB to support Zcb extension" + RISCV=$RISCV_ZCB +fi + +if ! [ -n "$RISCV" ]; then + echo "Error: RISCV variable undefined" + return +fi + +# install the required tools +source ./verif/regress/install-verilator.sh +source ./verif/regress/install-spike.sh + +source ./verif/sim/setup-env.sh + +export cov=1 #enable the Code Coverage + +if ! [ -n "$DV_TARGET" ]; then + DV_TARGET=cv32a65x +fi + +if ! [ -n "$DV_SIMULATORS" ]; then + DV_SIMULATORS=vcs-uvm,spike +fi + +cd verif/sim/ +cp ../env/corev-dv/custom/riscv_custom_instr_enum.sv ./dv/src/isa/custom/ + +python3 cva6.py --testlist=cva6_base_testlist.yaml --test riscv_interrupt_test --iss_yaml cva6.yaml --target $DV_TARGET -cs ../env/corev-dv/target/rv32imcb/ --mabi ilp32 --isa rv32imc --isa_extension="zba,zbb,zbc,zbs,zcb" --simulator_yaml ../env/corev-dv/simulator.yaml --iss=$DV_SIMULATORS --priv=m --issrun_opts="+enable_interrupt" -i 5 -bz 1 --iss_timeout 300 +python3 cva6.py --testlist=../tests/testlist_interrupt.yaml --test jump_to_zero --iss_yaml cva6.yaml --target $DV_TARGET -cs ../env/corev-dv/target/rv32imcb/ --mabi ilp32 --isa rv32imc --isa_extension="zba,zbb,zbc,zbs,zcb" --simulator_yaml ../env/corev-dv/simulator.yaml --iss=$DV_SIMULATORS --priv=m --issrun_opts="+enable_interrupt" + +cd - diff --git a/verif/sim/Makefile b/verif/sim/Makefile index a82b55b0e9..8b3affca4f 100644 --- a/verif/sim/Makefile +++ b/verif/sim/Makefile @@ -164,7 +164,7 @@ export DV_UVMA_ISACOV_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_isacov export DV_UVMA_CLKNRST_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_clknrst export DV_UVMA_CVXIF_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_cvxif export DV_UVMA_AXI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_axi5 -export DV_UVMA_INTERRUPT_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_interrupt +export DV_UVMA_INTERRUPT_PATH = $(DV_UVME_PATH)/uvma_interrupt export DV_UVMA_DEBUG_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_debug export DV_UVMA_OBI_PATH = $(CORE_V_VERIF)/lib/uvm_agents/uvma_obi export DV_UVMC_RVFI_SCOREBOARD_PATH = $(CORE_V_VERIF)/lib/uvm_components/uvmc_rvfi_scoreboard/ diff --git a/verif/sim/cva6_base_testlist.yaml b/verif/sim/cva6_base_testlist.yaml index 0bf2be4fa0..1dbcfd2bdd 100644 --- a/verif/sim/cva6_base_testlist.yaml +++ b/verif/sim/cva6_base_testlist.yaml @@ -730,3 +730,34 @@ iterations: 2 gen_test: cva6_instr_hazard_test_c rtl_test: core_base_test + +- test: riscv_interrupt_test + description: > + Arithmetic instruction test, no load/store/branch instructions no compressed + gcc_opts: > + -static + -mcmodel=medany + -fvisibility=hidden + -nostdlib + -nostartfiles + gen_opts: > + +instr_cnt=500 + +num_of_sub_program=0 + +no_fence=1 + +no_data_page=1 + +enable_interrupt=1 + +enable_timer_irq=1 + +no_branch_jump=1 + +no_wfi=0 + +boot_mode=m + +no_csr_instr=1 + +tvec_alignment=8 + +disable_compressed_instr=1 + +enable_zba_extension=1 + +enable_zbb_extension=1 + +enable_zbc_extension=1 + +enable_zbs_extension=1 + +enable_zcb_extension=1 + iterations: 2 + gen_test: cva6_instr_base_test_c + rtl_test: core_base_test diff --git a/verif/tb/uvmt/cva6_tb_wrapper.sv b/verif/tb/uvmt/cva6_tb_wrapper.sv index 878798a8c5..a592d45c90 100644 --- a/verif/tb/uvmt/cva6_tb_wrapper.sv +++ b/verif/tb/uvmt/cva6_tb_wrapper.sv @@ -58,6 +58,7 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #( output rvfi_csr_t rvfi_csr_o, input cvxif_pkg::cvxif_resp_t cvxif_resp, output cvxif_pkg::cvxif_req_t cvxif_req, + input logic [2:0] irq_i, uvma_axi_intf axi_slave, uvmt_axi_switch_intf axi_switch_vif, uvmt_default_inputs_intf default_inputs_vif @@ -81,19 +82,19 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #( .rvfi_probes_csr_t ( rvfi_probes_csr_t ), .rvfi_probes_t ( rvfi_probes_t ) ) i_cva6 ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .boot_addr_i ( boot_addr_i ),//Driving the boot_addr value from the core control agent + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .boot_addr_i ( boot_addr_i ),//Driving the boot_addr value from the core control agent .hart_id_i ( default_inputs_vif.hart_id ), - .irq_i ( default_inputs_vif.irq ), - .ipi_i ( default_inputs_vif.ipi ), - .time_irq_i ( default_inputs_vif.time_irq ), + .irq_i ( {1'b0, irq_i[0]} ), + .ipi_i ( irq_i[1] ), + .time_irq_i ( irq_i[2] ), .debug_req_i ( default_inputs_vif.debug_req ), .rvfi_probes_o ( rvfi_probes ), - .cvxif_req_o ( cvxif_req ), - .cvxif_resp_i ( cvxif_resp ), - .noc_req_o ( axi_ariane_req ), - .noc_resp_i ( axi_ariane_resp ) + .cvxif_req_o ( cvxif_req ), + .cvxif_resp_i ( cvxif_resp ), + .noc_req_o ( axi_ariane_req ), + .noc_resp_i ( axi_ariane_resp ) ); //---------------------------------------------------------------------------- diff --git a/verif/tb/uvmt/uvmt_cva6.flist b/verif/tb/uvmt/uvmt_cva6.flist index 10d7e48a3f..c42ca778eb 100644 --- a/verif/tb/uvmt/uvmt_cva6.flist +++ b/verif/tb/uvmt/uvmt_cva6.flist @@ -30,6 +30,7 @@ -f ${DV_UVMA_ISACOV_PATH}/uvma_isacov_pkg.flist -f ${DV_UVMC_RVFI_REFERENCE_MODEL_PATH}/uvmc_rvfi_reference_model_pkg.flist -f ${DV_UVMC_RVFI_SCOREBOARD_PATH}/uvmc_rvfi_scoreboard_pkg.flist +-f ${CVA6_UVME_PATH}/uvma_interrupt/uvma_interrupt_pkg.flist // Environments -f ${CVA6_UVME_PATH}/uvme_cva6_pkg.flist diff --git a/verif/tb/uvmt/uvmt_cva6_dut_wrap.sv b/verif/tb/uvmt/uvmt_cva6_dut_wrap.sv index 038b69370b..9e8bb9d2e4 100644 --- a/verif/tb/uvmt/uvmt_cva6_dut_wrap.sv +++ b/verif/tb/uvmt/uvmt_cva6_dut_wrap.sv @@ -34,6 +34,7 @@ module uvmt_cva6_dut_wrap # ( uvmt_axi_switch_intf axi_switch_vif, uvmt_default_inputs_intf default_inputs_vif, uvme_cva6_core_cntrl_if core_cntrl_if, + uvma_interrupt_if interrupt_vif, output logic[31:0] tb_exit_o, output rvfi_instr_t [CVA6Cfg.NrCommitPorts-1:0] rvfi_o, output rvfi_csr_t rvfi_csr_o @@ -60,6 +61,7 @@ module uvmt_cva6_dut_wrap # ( .boot_addr_i ( boot_addr ), .cvxif_resp ( cvxif_if.cvxif_resp_o ), .cvxif_req ( cvxif_if.cvxif_req_i ), + .irq_i ( interrupt_vif.irq ), .axi_slave ( axi_if ), .axi_switch_vif ( axi_switch_vif ), .default_inputs_vif ( default_inputs_vif ), diff --git a/verif/tb/uvmt/uvmt_cva6_tb.sv b/verif/tb/uvmt/uvmt_cva6_tb.sv index 24daffe98b..11c0e54f9e 100644 --- a/verif/tb/uvmt/uvmt_cva6_tb.sv +++ b/verif/tb/uvmt/uvmt_cva6_tb.sv @@ -67,6 +67,11 @@ module uvmt_cva6_tb; .clk(clknrst_if.clk), .rst_n(clknrst_if.reset_n) ); + + uvma_interrupt_if + interrupt_vif( + ); + uvmt_axi_switch_intf axi_switch_vif(); uvme_cva6_core_cntrl_if core_cntrl_if(); uvma_rvfi_instr_if #( @@ -122,6 +127,7 @@ module uvmt_cva6_tb; .axi_switch_vif (axi_switch_vif), .default_inputs_vif (default_inputs_vif), .core_cntrl_if(core_cntrl_if), + .interrupt_vif(interrupt_vif), .tb_exit_o(tb_exit_if.tb_exit_o), .rvfi_o(rvfi_if.rvfi_o), .rvfi_csr_o(rvfi_if.rvfi_csr_o) @@ -370,6 +376,8 @@ module uvmt_cva6_tb; uvm_config_db#(virtual uvmt_axi_switch_intf )::set(.cntxt(null), .inst_name("*.env"), .field_name("axi_switch_vif"), .value(axi_switch_vif)); uvm_config_db#(virtual uvmt_rvfi_if#( .CVA6Cfg(CVA6Cfg), .rvfi_instr_t(rvfi_instr_t), .rvfi_csr_t (rvfi_csr_t)))::set(.cntxt(null), .inst_name("*"), .field_name("rvfi_vif"), .value(rvfi_if)); uvm_config_db#(virtual uvme_cva6_core_cntrl_if)::set(.cntxt(null), .inst_name("*"), .field_name("core_cntrl_vif"), .value(core_cntrl_if)); + uvm_config_db#(virtual uvma_interrupt_if)::set(.cntxt(null), .inst_name("*"), .field_name("interrupt_vif"), .value(interrupt_vif)); + uvm_config_db#(virtual uvmt_tb_exit_if)::set(.cntxt(null), .inst_name("*"), .field_name("tb_exit_vif"), .value(tb_exit_if)); // DUT and ENV parameters diff --git a/verif/tests/custom/interrupt/jump_to_zero.S b/verif/tests/custom/interrupt/jump_to_zero.S new file mode 100644 index 0000000000..b5233e96ba --- /dev/null +++ b/verif/tests/custom/interrupt/jump_to_zero.S @@ -0,0 +1,65 @@ +# Copyright 2024 Thales DIS SAS +# +# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +# You may obtain a copy of the License at https://solderpad.org/licenses/ +# +# Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + +#***************************************************************************** +# jump_to_zero.S +#----------------------------------------------------------------------------- +# + + .globl main +main: +# core of the test + la t1, exception_handler + csrw mtvec, t1 ## Load the address of the exception handler into MTVEC + csrw 0x341, zero ## Writing Zero to MEPC CSR + csrw 0x342, zero ## Writing Zero to MCAUSE CSR + #End Handle exceptions + +# enable interrupt in mie and mstatus + li a1, 0x888 + csrw mie, a1 + csrr a2, mie + li a1, 0x8 + csrw mstatus, a1 + csrr a2, mstatus + +jump00: + jal a1, jump00 + +jump01: + c.j jump01 + +jump02: + c.jal jump02 + + #End of test + j test_done + +test_done: + li ra, 0 + slli ra, ra, 1 + addi ra, ra, 1 + sw ra, tohost, t5 + self_loop: j self_loop + +.align 8 +exception_handler: + # increment return address to skip instruction generating the exception + # valid only if faulting instruction is not compressed (4-byte long) + csrr s11, mepc + lbu s5, 0(s11) + li s9, 0x3 + and s5, s5, s9 + bne s5, s9, exception_handler_incr_mepc2 + addi s11, s11, 2 + exception_handler_incr_mepc2: + addi s11, s11, 2 + csrw mepc, s11 + csrr t6, mepc + mret diff --git a/verif/tests/testlist_interrupt.yaml b/verif/tests/testlist_interrupt.yaml new file mode 100644 index 0000000000..a3cd8ab8b3 --- /dev/null +++ b/verif/tests/testlist_interrupt.yaml @@ -0,0 +1,32 @@ +# Copyright 2024 Thales DIS design services SAS +# +# Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +# You may obtain a copy of the License at https:#solderpad.org/licenses/ +# +# Original Author: Ayoub JALALI (ayoub.jalali@external.thalesgroup.com) + +# ================================================================================ +# Regression test list format +# -------------------------------------------------------------------------------- +# test : Assembly test name +# description : Description of this test +# gen_opts : Instruction generator options +# iterations : Number of iterations of this test +# no_iss : Enable/disable ISS simulator (Optional) +# gen_test : Test name used by the instruction generator +# asm_tests : Path to directed, hand-coded assembly test file or directory +# rtl_test : RTL simulation test name +# cmp_opts : Compile options passed to the instruction generator +# sim_opts : Simulation options passed to the instruction generator +# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional) +# compare_opts : Options for the RTL & ISS trace comparison +# gcc_opts : gcc compile options +# -------------------------------------------------------------------------------- + +- test: jump_to_zero + iterations: 1 + path_var: TESTS_PATH + gcc_opts: "-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles ../tests/custom/common/syscalls.c ../tests/custom/common/crt.S -I../tests/custom/env -I../tests/custom/common -T ../tests/custom/common/test.ld -lgcc" + asm_tests: /custom/interrupt/jump_to_zero.S