diff --git a/verif/env/uvme/uvme_cva6_cfg.sv b/verif/env/uvme/uvme_cva6_cfg.sv index 1f597e49c..bdb579a7f 100644 --- a/verif/env/uvme/uvme_cva6_cfg.sv +++ b/verif/env/uvme/uvme_cva6_cfg.sv @@ -43,6 +43,8 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; // Agent cfg handles rand uvma_clknrst_cfg_c clknrst_cfg; rand uvma_axi_cfg_c axi_cfg; + rand uvma_obi_memory_cfg_c obi_memory_instr_cfg; + //rand uvma_obi_memory_cfg_c obi_memory_data_cfg; rand uvma_rvfi_cfg_c#(ILEN,XLEN) rvfi_cfg; rand uvma_isacov_cfg_c isacov_cfg; rand uvma_interrupt_cfg_c interrupt_cfg; @@ -66,6 +68,9 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; // Software interrupt supported rand bit sw_int_supported; + //OBI stall gnt and rvalid + rand bit zero_stall_sim; + `uvm_object_utils_begin(uvme_cva6_cfg_c) `uvm_field_int ( enabled , UVM_DEFAULT ) `uvm_field_enum(uvm_active_passive_enum, is_active , UVM_DEFAULT ) @@ -87,6 +92,10 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; `uvm_field_object(axi_cfg, UVM_DEFAULT) + `uvm_field_object(obi_memory_instr_cfg, UVM_DEFAULT) + + // TODO:`uvm_field_object(obi_memory_data_cfg, UVM_DEFAULT) + `uvm_field_object(rvfi_cfg, UVM_DEFAULT) `uvm_field_object(isacov_cfg, UVM_DEFAULT) @@ -169,6 +178,36 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; } } + constraint obi_zero_stall_sim_dist_cons { + //zero_stall_sim dist { 0 :/ 2, 1 :/ 1}; // TODO: Randomize + zero_stall_sim == 0; + } + + constraint zero_stall_sim_cons { + if (zero_stall_sim) { + obi_memory_instr_cfg.drv_slv_gnt_mode == UVMA_OBI_MEMORY_DRV_SLV_GNT_MODE_CONSTANT; + obi_memory_instr_cfg.drv_slv_rvalid_mode == UVMA_OBI_MEMORY_DRV_SLV_RVALID_MODE_CONSTANT; + //obi_memory_data_cfg.drv_slv_gnt_mode == UVMA_OBI_MEMORY_DRV_SLV_GNT_MODE_CONSTANT; + //obi_memory_data_cfg.drv_slv_rvalid_mode == UVMA_OBI_MEMORY_DRV_SLV_RVALID_MODE_CONSTANT; + } + } + + // TODO FIX + //constraint max_data_zero_instr_stall_sim_cons { + //if (max_data_zero_instr_stall) { + //obi_memory_instr_cfg.drv_slv_gnt_mode == UVMA_OBI_MEMORY_DRV_SLV_GNT_MODE_CONSTANT; + //obi_memory_instr_cfg.drv_slv_rvalid_mode == UVMA_OBI_MEMORY_DRV_SLV_RVALID_MODE_CONSTANT; + + //obi_memory_data_cfg.drv_slv_gnt_mode == UVMA_OBI_MEMORY_DRV_SLV_GNT_MODE_RANDOM_LATENCY; + //obi_memory_data_cfg.drv_slv_gnt_random_latency_min == 0; + //obi_memory_data_cfg.drv_slv_gnt_random_latency_max == 8; + + //obi_memory_data_cfg.drv_slv_rvalid_mode == UVMA_OBI_MEMORY_DRV_SLV_RVALID_MODE_RANDOM_LATENCY; + //obi_memory_data_cfg.drv_slv_rvalid_random_latency_min == 0; + //obi_memory_data_cfg.drv_slv_rvalid_random_latency_max == 8; + //} + //} + constraint agent_cfg_cons { if (enabled) { clknrst_cfg.enabled == 1; @@ -188,21 +227,51 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; axi_cfg.zero_delay_mode == 1; axi_cfg.disable_trs_randomization == 1; + obi_memory_instr_cfg.drv_mode == UVMA_OBI_MEMORY_MODE_SLV; + obi_memory_instr_cfg.version == UVMA_OBI_MEMORY_VERSION_1P2; + + obi_memory_instr_cfg.auser_width == RTLCVA6Cfg.ObiFetchbusCfg.OptionalCfg.AUserWidth; + obi_memory_instr_cfg.wuser_width == RTLCVA6Cfg.ObiFetchbusCfg.OptionalCfg.WUserWidth; + obi_memory_instr_cfg.ruser_width == RTLCVA6Cfg.ObiFetchbusCfg.OptionalCfg.RUserWidth; + obi_memory_instr_cfg.addr_width == RTLCVA6Cfg.ObiFetchbusCfg.AddrWidth ; + obi_memory_instr_cfg.data_width == RTLCVA6Cfg.ObiFetchbusCfg.DataWidth ; + obi_memory_instr_cfg.id_width == RTLCVA6Cfg.ObiFetchbusCfg.IdWidth ; + obi_memory_instr_cfg.achk_width == RTLCVA6Cfg.ObiFetchbusCfg.OptionalCfg.AChkWidth ; + obi_memory_instr_cfg.rchk_width == RTLCVA6Cfg.ObiFetchbusCfg.OptionalCfg.RChkWidth ; + + soft obi_memory_instr_cfg.drv_slv_gnt_random_latency_max <= 2; + soft obi_memory_instr_cfg.drv_slv_gnt_fixed_latency <= 2; + soft obi_memory_instr_cfg.drv_slv_rvalid_random_latency_max <= 3; + soft obi_memory_instr_cfg.drv_slv_rvalid_fixed_latency <= 3; + + // TODO: obi_memory_data_cfg ... + if (is_active == UVM_ACTIVE) { 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 (RTLCVA6Cfg.PipelineOnly) { + obi_memory_instr_cfg.is_active == UVM_ACTIVE; + //TODO :obi_memory_data_cfg.is_active == UVM_ACTIVE; + } else { + obi_memory_instr_cfg.is_active == UVM_PASSIVE; + //TODO :obi_memory_data_cfg.is_active == UVM_PASSIVE; + } } if (trn_log_enabled) { clknrst_cfg.trn_log_enabled == 0; axi_cfg.trn_log_enabled == 1; + obi_memory_instr_cfg.trn_log_enabled == 1; + //obi_memory_data_cfg.trn_log_enabled == 1; rvfi_cfg.trn_log_enabled == 1; isacov_cfg.trn_log_enabled == 1; } else { clknrst_cfg.trn_log_enabled == 0; axi_cfg.trn_log_enabled == 0; + obi_memory_instr_cfg.trn_log_enabled == 0; + //obi_memory_data_cfg.trn_log_enabled == 0; rvfi_cfg.trn_log_enabled == 0; isacov_cfg.trn_log_enabled == 0; } @@ -210,10 +279,14 @@ class uvme_cva6_cfg_c extends uvma_core_cntrl_cfg_c; if (cov_model_enabled) { isacov_cfg.cov_model_enabled == 1; axi_cfg.cov_model_enabled == 1; + obi_memory_instr_cfg.cov_model_enabled == 1; + //obi_memory_data_cfg.cov_model_enabled == 1; //TODO interrupt_cfg.cov_model_enabled == 1; } else { isacov_cfg.cov_model_enabled == 0; axi_cfg.cov_model_enabled == 0; + obi_memory_instr_cfg.cov_model_enabled == 0; + //obi_memory_data_cfg.cov_model_enabled == 1; //TODO interrupt_cfg.cov_model_enabled == 0; } @@ -250,6 +323,8 @@ function uvme_cva6_cfg_c::new(string name="uvme_cva6_cfg"); clknrst_cfg = uvma_clknrst_cfg_c::type_id::create("clknrst_cfg"); axi_cfg = uvma_axi_cfg_c::type_id::create("axi_cfg"); + obi_memory_instr_cfg = uvma_obi_memory_cfg_c::type_id::create("obi_memory_instr_cfg"); + // TODO:obi_memory_data_cfg = uvma_obi_memory_cfg_c::type_id::create("obi_memory_data_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"); diff --git a/verif/env/uvme/uvme_cva6_cntxt.sv b/verif/env/uvme/uvme_cva6_cntxt.sv index 111278090..2e48a79f2 100644 --- a/verif/env/uvme/uvme_cva6_cntxt.sv +++ b/verif/env/uvme/uvme_cva6_cntxt.sv @@ -30,15 +30,18 @@ class uvme_cva6_cntxt_c extends uvm_object; typedef uvml_mem_c#(cva6_config_pkg::CVA6ConfigAxiAddrWidth) uvml_mem_cva6; // Agent context handles - uvma_clknrst_cntxt_c clknrst_cntxt; - uvma_axi_cntxt_c axi_cntxt; + uvma_clknrst_cntxt_c clknrst_cntxt; + uvma_axi_cntxt_c axi_cntxt; + uvma_obi_memory_cntxt_c obi_memory_instr_cntxt; + //TODO :uvma_obi_memory_cntxt_c obi_memory_data_cntxt; uvma_cva6_core_cntrl_cntxt_c core_cntrl_cntxt; uvma_rvfi_cntxt_c rvfi_cntxt; uvma_interrupt_cntxt_c interrupt_cntxt; uvma_cvxif_cntxt_c cvxif_cntxt; // Memory modelling - rand uvml_mem_cva6 mem; + rand uvml_mem_cva6 mem; + rand uvml_mem_c mem_obi; // Handle to debug_req interface virtual uvma_debug_if debug_vif; @@ -51,6 +54,8 @@ class uvme_cva6_cntxt_c extends uvm_object; `uvm_object_utils_begin(uvme_cva6_cntxt_c) `uvm_field_object(clknrst_cntxt, UVM_DEFAULT) `uvm_field_object(axi_cntxt, UVM_DEFAULT) + `uvm_field_object(obi_memory_instr_cntxt, UVM_DEFAULT) + //TODO :`uvm_field_object(obi_memory_data_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) @@ -58,10 +63,12 @@ class uvme_cva6_cntxt_c extends uvm_object; `uvm_field_event(sample_cfg_e , UVM_DEFAULT) `uvm_field_event(sample_cntxt_e, UVM_DEFAULT) `uvm_field_object(mem, UVM_DEFAULT) + `uvm_field_object(mem_obi, UVM_DEFAULT) `uvm_object_utils_end constraint mem_cfg_cons { mem.mem_default == MEM_DEFAULT_0; + mem_obi.mem_default == MEM_DEFAULT_0; } /** @@ -79,6 +86,8 @@ function uvme_cva6_cntxt_c::new(string name="uvme_cva6_cntxt"); clknrst_cntxt = uvma_clknrst_cntxt_c::type_id::create("clknrst_cntxt"); core_cntrl_cntxt = uvma_cva6_core_cntrl_cntxt_c::type_id::create("core_cntrl_cntxt"); axi_cntxt = uvma_axi_cntxt_c::type_id::create("axi_cntxt"); + obi_memory_instr_cntxt = uvma_obi_memory_cntxt_c::type_id::create("obi_memory_instr_cntxt"); + // TODO:obi_memory_data_cntxt = uvma_obi_memory_cntxt_c::type_id::create("obi_memory_data_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"); @@ -88,6 +97,7 @@ function uvme_cva6_cntxt_c::new(string name="uvme_cva6_cntxt"); sample_cntxt_e = new("sample_cntxt_e"); mem.mem_default = MEM_DEFAULT_0; + mem_obi.mem_default = MEM_DEFAULT_0; endfunction : new diff --git a/verif/env/uvme/uvme_cva6_env.sv b/verif/env/uvme/uvme_cva6_env.sv index 520b89133..d7d0e4c97 100644 --- a/verif/env/uvme/uvme_cva6_env.sv +++ b/verif/env/uvme/uvme_cva6_env.sv @@ -43,6 +43,8 @@ class uvme_cva6_env_c extends uvm_env; // Agents uvma_clknrst_agent_c clknrst_agent; uvma_axi_agent_c axi_agent; + uvma_obi_memory_agent_c obi_memory_instr_agent; + // TODO: uvma_obi_memory_agent_c obi_memory_data_agent; 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; @@ -174,6 +176,10 @@ function void uvme_cva6_env_c::build_phase(uvm_phase phase); end cntxt.axi_cntxt.mem = cntxt.mem; + if (RTLCVA6Cfg.PipelineOnly) begin + cntxt.obi_memory_instr_cntxt.mem = cntxt.mem_obi; + // TODO:cntxt.obi_memory_data_cntxt.mem = cntxt.mem_obi; + end cntxt.interrupt_cntxt.mem = cntxt.mem; // get irq_addr ack from CVA6 UVM env cfg.interrupt_cfg.irq_addr = cfg.get_irq_addr(); @@ -246,6 +252,10 @@ function void uvme_cva6_env_c::assign_cfg(); uvm_config_db#(uvma_axi_cfg_c)::set(this, "*axi_agent", "cfg", cfg.axi_cfg); + uvm_config_db#(uvma_obi_memory_cfg_c)::set(this, "obi_memory_instr_agent", "cfg", cfg.obi_memory_instr_cfg); + + // TODO:uvm_config_db#(uvma_obi_memory_cfg_c)::set(this, "obi_memory_data_agent", "cfg", cfg.obi_memory_data_cfg); + uvm_config_db#(uvma_core_cntrl_cfg_c)::set(this, "core_cntrl_agent", "cfg", cfg); uvm_config_db#(uvma_rvfi_cfg_c#(ILEN,XLEN))::set(this, "*rvfi_agent", "cfg", cfg.rvfi_cfg); @@ -267,6 +277,8 @@ function void uvme_cva6_env_c::assign_cntxt(); uvm_config_db#(uvme_cva6_cntxt_c)::set(this, "*", "cntxt", 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_obi_memory_cntxt_c)::set(this, "obi_memory_instr_agent", "cntxt", cntxt.obi_memory_instr_cntxt); + //uvm_config_db#(uvma_obi_memory_cntxt_c)::set(this, "obi_memory_data_agent", "cntxt", cntxt.obi_memory_data_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); uvm_config_db#(uvma_cvxif_cntxt_c)::set(this, "cvxif_agent", "cntxt", cntxt.cvxif_cntxt); @@ -278,6 +290,8 @@ function void uvme_cva6_env_c::create_agents(); clknrst_agent = uvma_clknrst_agent_c::type_id::create("clknrst_agent", this); axi_agent = uvma_axi_agent_c::type_id::create("axi_agent", this); + obi_memory_instr_agent = uvma_obi_memory_agent_c::type_id::create("obi_memory_instr_agent", this); + // TODO:obi_memory_data_agent = uvma_obi_memory_agent_c::type_id::create("obi_memory_data_agent", this); 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); @@ -372,6 +386,8 @@ function void uvme_cva6_env_c::assemble_vsequencer(); vsequencer.clknrst_sequencer = clknrst_agent.sequencer; vsequencer.axi_vsequencer = axi_agent.vsequencer; vsequencer.interrupt_sequencer = interrupt_agent.sequencer; + vsequencer.obi_memory_instr_sequencer = obi_memory_instr_agent.sequencer; + // TODO: vsequencer.obi_memory_data_sequencer = obi_memory_data_agent.sequencer; vsequencer.cvxif_vsequencer = cvxif_agent.vsequencer; endfunction: assemble_vsequencer @@ -379,6 +395,10 @@ endfunction: assemble_vsequencer task uvme_cva6_env_c::run_phase(uvm_phase phase); + uvma_obi_memory_fw_preload_seq_c fw_preload_seq; + uvma_obi_memory_slv_seq_c instr_slv_seq; +// uvma_obi_memory_slv_seq_c data_slv_seq; + fork begin @@ -402,6 +422,26 @@ task uvme_cva6_env_c::run_phase(uvm_phase phase); cvxif_vseq = uvme_cvxif_vseq_c::type_id::create("cvxif_vseq"); cvxif_vseq.start(cvxif_agent.vsequencer); end + + begin : spawn_obi_instr_fw_preload_thread + if(cfg.obi_memory_instr_cfg.is_active == UVM_ACTIVE) begin + fw_preload_seq = uvma_obi_memory_fw_preload_seq_c::type_id::create("fw_preload_seq"); + if (!fw_preload_seq.randomize()) begin + `uvm_fatal("FWPRELOAD", "Randomize failed"); + end + fw_preload_seq.start(obi_memory_instr_agent.sequencer); + end + end + + begin : obi_instr_slv_thread + if(cfg.obi_memory_instr_cfg.is_active == UVM_ACTIVE) begin + instr_slv_seq = uvma_obi_memory_slv_seq_c::type_id::create("instr_slv_seq"); + if (!instr_slv_seq.randomize()) begin + `uvm_fatal("INSTRSLVSEQ", "Randomize failed"); + end + instr_slv_seq.start(obi_memory_instr_agent.sequencer); + end + end join_none endtask diff --git a/verif/env/uvme/uvme_cva6_pkg.sv b/verif/env/uvme/uvme_cva6_pkg.sv index b77c5655b..665171046 100644 --- a/verif/env/uvme/uvme_cva6_pkg.sv +++ b/verif/env/uvme/uvme_cva6_pkg.sv @@ -47,6 +47,7 @@ package uvme_cva6_pkg; import uvml_trn_pkg ::*; import uvma_clknrst_pkg::*; import uvma_axi_pkg::*; + import uvma_obi_memory_pkg::*; import uvml_mem_pkg ::*; import uvma_core_cntrl_pkg::*; import uvma_rvfi_pkg::*; @@ -119,6 +120,8 @@ package uvme_cva6_pkg; `include "uvme_cva6_base_vseq.sv" `include "uvme_cva6_reset_vseq.sv" `include "uvme_axi_fw_preload_seq.sv" + `include "uvme_obi_fw_preload_seq.sv" + `include "uvme_obi_slv_seq.sv" // `include "uvme_cva6_interrupt_noise_vseq.sv" `include "uvme_cva6_vseq_lib.sv" diff --git a/verif/env/uvme/uvme_cva6_vsqr.sv b/verif/env/uvme/uvme_cva6_vsqr.sv index d28b5073a..431c4650f 100644 --- a/verif/env/uvme/uvme_cva6_vsqr.sv +++ b/verif/env/uvme/uvme_cva6_vsqr.sv @@ -39,6 +39,8 @@ class uvme_cva6_vsqr_c extends uvm_sequencer#( uvma_axi_vsqr_c axi_vsequencer; uvma_interrupt_sqr_c interrupt_sequencer; uvma_cvxif_vsqr_c cvxif_vsequencer; + uvma_obi_memory_sqr_c obi_memory_instr_sequencer; + // TODO:uvma_obi_memory_sqr_c obi_memory_instr_sequencer; `uvm_component_utils_begin(uvme_cva6_vsqr_c) diff --git a/verif/env/uvme/vseq/uvme_obi_fw_preload_seq.sv b/verif/env/uvme/vseq/uvme_obi_fw_preload_seq.sv new file mode 100644 index 000000000..2a87f34c0 --- /dev/null +++ b/verif/env/uvme/vseq/uvme_obi_fw_preload_seq.sv @@ -0,0 +1,81 @@ +// 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: Alae Eddine EZ ZEJJARI (alae-eddine.ez-zejjari@external.thalesgroup.com) – sub-contractor MU-Electronics for Thales group + + +`ifndef __UVME_OBI_FW_PRELOAD_SEQ_SV__ +`define __UVME_OBI_FW_PRELOAD_SEQ_SV__ + + +/** + * Virtual sequence preloads the CVA6 memory. + */ +class uvme_obi_fw_preload_seq_c extends uvma_obi_memory_fw_preload_seq_c; + + uvml_mem_c mem; + static uvm_cmdline_processor uvcl = uvm_cmdline_processor::get_inst(); + + bit[63:0] value; + logic [7:0][7:0] mem_row; + string binary = ""; + longint address; + longint len; + byte buffer[]; + + `uvm_object_utils(uvme_obi_fw_preload_seq_c) + + /** + * Default constructor. + */ + extern function new(string name="uvma_obi_fw_preload_seq"); + + extern virtual task body(); + +endclass : uvme_obi_fw_preload_seq_c + +function uvme_obi_fw_preload_seq_c::new(string name="uvma_obi_fw_preload_seq"); + + super.new(name); + +endfunction : new + +task uvme_obi_fw_preload_seq_c::body(); + + void'(uvcl.get_arg_value("+elf_file=", binary)); + + if (binary != "") begin + read_elf(binary); + wait(p_sequencer.cntxt.vif.clk); + // while there are more sections to process + while (get_section(address, len)) begin + automatic int num_words0 = (len+7)/8; + `uvm_info( "Core Test", $sformatf("Loading Address: %x, Length: %x", address, len), UVM_HIGH) + buffer = new [num_words0*8]; + read_section_sv(address, buffer); + // preload memories + // 64-bit + for (int i = 0; i < num_words0; i++) begin + mem_row = '0; + for (int j = 0; j < 8; j++) begin + mem_row[j] = buffer[i*8 + j]; + end + p_sequencer.cntxt.mem.write(address + i*8 + 0, mem_row[0]); + p_sequencer.cntxt.mem.write(address + i*8 + 1, mem_row[1]); + p_sequencer.cntxt.mem.write(address + i*8 + 2, mem_row[2]); + p_sequencer.cntxt.mem.write(address + i*8 + 3, mem_row[3]); + p_sequencer.cntxt.mem.write(address + i*8 + 4, mem_row[4]); + p_sequencer.cntxt.mem.write(address + i*8 + 5, mem_row[5]); + p_sequencer.cntxt.mem.write(address + i*8 + 6, mem_row[6]); + p_sequencer.cntxt.mem.write(address + i*8 + 7, mem_row[7]); + end + end + end + +endtask : body + +`endif // __UVME_OBI_FW_PRELOAD_SEQ_SV__ diff --git a/verif/env/uvme/vseq/uvme_obi_slv_seq.sv b/verif/env/uvme/vseq/uvme_obi_slv_seq.sv new file mode 100644 index 000000000..92367d701 --- /dev/null +++ b/verif/env/uvme/vseq/uvme_obi_slv_seq.sv @@ -0,0 +1,78 @@ +// +// Copyright 2021 OpenHW Group +// Copyright 2021 Datum Technology Corporation +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the "License"); you may +// not use this file except in compliance with the License, or, at your option, +// the Apache License version 2.0. You may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work +// 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 __UVME_OBI_SLV_SEQ_SV__ +`define __UVME_OBI_SLV_SEQ_SV__ + + +/** + * Virtual sequence implementing the cva6 virtual peripherals. + */ +class uvme_obi_slv_seq_c extends uvma_obi_memory_slv_seq_c; + + + `uvm_object_utils_begin(uvme_obi_slv_seq_c) + `uvm_object_utils_end + + function new(string name="uvme_obi_slv_seq_c"); + super.new(name); + endfunction : new + + + task do_mem_operation(ref uvma_obi_memory_mon_trn_c mon_req); + bit [31:0] word_aligned_addr; + + uvma_obi_memory_slv_seq_item_c slv_rsp; + `uvm_create(slv_rsp) + slv_rsp.orig_trn = mon_req; + slv_rsp.access_type = mon_req.access_type; + + word_aligned_addr = { mon_req.address[31:3], 3'h0 }; + + `uvm_info("SLV_SEQ", $sformatf("Performing operation:\n%s", mon_req.sprint()), UVM_HIGH) + if (mon_req.access_type == UVMA_OBI_MEMORY_ACCESS_WRITE) begin + if (mon_req.be[7]) cntxt.mem.write(word_aligned_addr+7, mon_req.data[63:56]); + if (mon_req.be[6]) cntxt.mem.write(word_aligned_addr+6, mon_req.data[55:48]); + if (mon_req.be[5]) cntxt.mem.write(word_aligned_addr+5, mon_req.data[47:40]); + if (mon_req.be[4]) cntxt.mem.write(word_aligned_addr+4, mon_req.data[39:32]); + if (mon_req.be[3]) cntxt.mem.write(word_aligned_addr+3, mon_req.data[31:24]); + if (mon_req.be[2]) cntxt.mem.write(word_aligned_addr+2, mon_req.data[23:16]); + if (mon_req.be[1]) cntxt.mem.write(word_aligned_addr+1, mon_req.data[15:08]); + if (mon_req.be[0]) cntxt.mem.write(word_aligned_addr+0, mon_req.data[07:00]); + end + else begin + if (mon_req.be[7]) slv_rsp.rdata[63:56] = cntxt.mem.read(word_aligned_addr+7); + if (mon_req.be[6]) slv_rsp.rdata[55:48] = cntxt.mem.read(word_aligned_addr+6); + if (mon_req.be[5]) slv_rsp.rdata[47:40] = cntxt.mem.read(word_aligned_addr+5); + if (mon_req.be[4]) slv_rsp.rdata[39:32] = cntxt.mem.read(word_aligned_addr+4); + if (mon_req.be[3]) slv_rsp.rdata[31:24] = cntxt.mem.read(word_aligned_addr+3); + if (mon_req.be[2]) slv_rsp.rdata[23:16] = cntxt.mem.read(word_aligned_addr+2); + if (mon_req.be[1]) slv_rsp.rdata[15:08] = cntxt.mem.read(word_aligned_addr+1); + if (mon_req.be[0]) slv_rsp.rdata[07:00] = cntxt.mem.read(word_aligned_addr+0); + end + + add_r_fields(mon_req, slv_rsp); + slv_rsp.set_sequencer(p_sequencer); + `uvm_send(slv_rsp) + + endtask : do_mem_operation + + +endclass : uvme_obi_slv_seq_c +`endif // __UVME_OBI_SLV_SEQ_SV__ diff --git a/verif/sim/Makefile b/verif/sim/Makefile index 802ad02c1..c8627bd6f 100644 --- a/verif/sim/Makefile +++ b/verif/sim/Makefile @@ -171,6 +171,7 @@ export DV_UVML_TRN_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_trn export DV_UVML_MEM_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_mem export DV_UVML_LOGS_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_logs export DV_UVML_SB_PATH = $(CORE_V_VERIF)/lib/uvm_libs/uvml_sb +export DV_UVMA_OBI_MEMORY_PATH= $(CORE_V_VERIF)/lib/uvm_agents/uvma_obi_memory export CV_CORE_PKG = $(CORE_V_VERIF)/core-v-cores/$(CV_CORE_LC) export DESIGN_RTL_DIR = $(CV_CORE_PKG)/rtl diff --git a/verif/tb/uvmt/cva6_tb_wrapper.sv b/verif/tb/uvmt/cva6_tb_wrapper.sv index 708267b96..c156146ef 100644 --- a/verif/tb/uvmt/cva6_tb_wrapper.sv +++ b/verif/tb/uvmt/cva6_tb_wrapper.sv @@ -76,6 +76,7 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #( uvma_debug_if debug_if, uvma_axi_intf axi_slave, uvma_cvxif_intf cvxif_if, + uvma_obi_memory_if obi_fetch_slave, uvmt_axi_switch_intf axi_switch_vif, uvmt_default_inputs_intf default_inputs_vif ); @@ -256,6 +257,66 @@ module cva6_tb_wrapper import uvmt_cva6_pkg::*; #( assign cvxif_if.commit_req = cvxif_req.commit; assign cvxif_if.result_ready = cvxif_req.result_ready; + //Obi Interface + if (CVA6Cfg.PipelineOnly) begin + assign obi_fetch_slave.req = i_cva6.obi_fetch_req_if_cache.req; + assign obi_fetch_slave.addr = i_cva6.obi_fetch_req_if_cache.a.addr; + assign obi_fetch_slave.we = i_cva6.obi_fetch_req_if_cache.a.we; + assign obi_fetch_slave.be = i_cva6.obi_fetch_req_if_cache.a.be; + assign obi_fetch_slave.wdata = i_cva6.obi_fetch_req_if_cache.a.wdata; + assign obi_fetch_slave.auser = i_cva6.obi_fetch_req_if_cache.a.a_optional.auser; + assign obi_fetch_slave.wuser = i_cva6.obi_fetch_req_if_cache.a.a_optional.wuser; + assign obi_fetch_slave.aid = i_cva6.obi_fetch_req_if_cache.a.aid; + assign obi_fetch_slave.atop = i_cva6.obi_fetch_req_if_cache.a.a_optional.atop; + assign obi_fetch_slave.memtype = i_cva6.obi_fetch_req_if_cache.a.a_optional.memtype; + assign obi_fetch_slave.prot = i_cva6.obi_fetch_req_if_cache.a.a_optional.prot; + assign obi_fetch_slave.reqpar = i_cva6.obi_fetch_req_if_cache.reqpar; + assign obi_fetch_slave.achk = i_cva6.obi_fetch_req_if_cache.a.a_optional.achk; + assign obi_fetch_slave.rready = i_cva6.obi_fetch_req_if_cache.rready; + assign obi_fetch_slave.rreadypar = i_cva6.obi_fetch_req_if_cache.rreadypar; + assign i_cva6.obi_fetch_rsp_cache_if.gnt = obi_fetch_slave.gnt; + assign i_cva6.obi_fetch_rsp_cache_if.gntpar = obi_fetch_slave.gntpar; + assign i_cva6.obi_fetch_rsp_cache_if.rvalid = obi_fetch_slave.rvalid; + assign i_cva6.obi_fetch_rsp_cache_if.r.rdata = obi_fetch_slave.rdata; + assign i_cva6.obi_fetch_rsp_cache_if.r.err = obi_fetch_slave.err; + assign i_cva6.obi_fetch_rsp_cache_if.r.r_optional.ruser = obi_fetch_slave.ruser; + assign i_cva6.obi_fetch_rsp_cache_if.r.rid = obi_fetch_slave.rid; + assign i_cva6.obi_fetch_rsp_cache_if.r.r_optional.exokay = obi_fetch_slave.exokay; + assign i_cva6.obi_fetch_rsp_cache_if.rvalidpar = obi_fetch_slave.rvalidpar; + assign i_cva6.obi_fetch_rsp_cache_if.r.r_optional.rchk = obi_fetch_slave.rchk; + initial begin // TODO: workaround, need to emulate with OBI agent + force i_cva6.fetch_dreq_cache_if.ready = 1; + force i_cva6.fetch_dreq_cache_if.invalid_data = 0; + end + end else begin //OBI in PASSIVE mode + assign obi_fetch_slave.req = i_cva6.obi_fetch_req_if_cache.req; + assign obi_fetch_slave.addr = i_cva6.obi_fetch_req_if_cache.a.addr; + assign obi_fetch_slave.we = i_cva6.obi_fetch_req_if_cache.a.we; + assign obi_fetch_slave.be = i_cva6.obi_fetch_req_if_cache.a.be; + assign obi_fetch_slave.wdata = i_cva6.obi_fetch_req_if_cache.a.wdata; + assign obi_fetch_slave.auser = i_cva6.obi_fetch_req_if_cache.a.a_optional.auser; + assign obi_fetch_slave.wuser = i_cva6.obi_fetch_req_if_cache.a.a_optional.wuser; + assign obi_fetch_slave.aid = i_cva6.obi_fetch_req_if_cache.a.aid; + assign obi_fetch_slave.atop = i_cva6.obi_fetch_req_if_cache.a.a_optional.atop; + assign obi_fetch_slave.memtype = i_cva6.obi_fetch_req_if_cache.a.a_optional.memtype; + assign obi_fetch_slave.prot = i_cva6.obi_fetch_req_if_cache.a.a_optional.prot; + assign obi_fetch_slave.reqpar = i_cva6.obi_fetch_req_if_cache.reqpar; + assign obi_fetch_slave.achk = i_cva6.obi_fetch_req_if_cache.a.a_optional.achk; + assign obi_fetch_slave.rready = i_cva6.obi_fetch_req_if_cache.rready; + assign obi_fetch_slave.rreadypar = i_cva6.obi_fetch_req_if_cache.rreadypar; + assign obi_fetch_slave.gnt = i_cva6.obi_fetch_rsp_cache_if.gnt; + assign obi_fetch_slave.gntpar = i_cva6.obi_fetch_rsp_cache_if.gntpar; + assign obi_fetch_slave.rvalid = i_cva6.obi_fetch_rsp_cache_if.rvalid; + assign obi_fetch_slave.rdata = i_cva6.obi_fetch_rsp_cache_if.r.rdata; + assign obi_fetch_slave.err = i_cva6.obi_fetch_rsp_cache_if.r.err; + assign obi_fetch_slave.ruser = i_cva6.obi_fetch_rsp_cache_if.r.r_optional.ruser; + assign obi_fetch_slave.rid = i_cva6.obi_fetch_rsp_cache_if.r.rid; + assign obi_fetch_slave.exokay = i_cva6.obi_fetch_rsp_cache_if.r.r_optional.exokay; + assign obi_fetch_slave.rvalidpar = i_cva6.obi_fetch_rsp_cache_if.rvalidpar; + assign obi_fetch_slave.rchk = i_cva6.obi_fetch_rsp_cache_if.r.r_optional.rchk; + end + ///assign obi_fetch_slave.mid = i_cva6.obi_fetch_rsp_cache_if.a.a_optional.mid; + ///assign obi_fetch_slave.dbg = i_cva6.obi_fetch_rsp_cache_if.a.a_optional.dbg; AXI_BUS #( diff --git a/verif/tb/uvmt/uvmt_cva6.flist b/verif/tb/uvmt/uvmt_cva6.flist index f8a7640a7..bd95c19ac 100644 --- a/verif/tb/uvmt/uvmt_cva6.flist +++ b/verif/tb/uvmt/uvmt_cva6.flist @@ -33,6 +33,17 @@ -f ${DV_UVMC_RVFI_SCOREBOARD_PATH}/uvmc_rvfi_scoreboard_pkg.flist -f ${CVA6_UVME_PATH}/uvma_interrupt/uvma_interrupt_pkg.flist ++define+UVMA_OBI_MEMORY_AUSER_DEFAULT_WIDTH=64 // Width of the auser signal. ++define+UVMA_OBI_MEMORY_WUSER_DEFAULT_WIDTH=64 // Width of the wuser signal. ++define+UVMA_OBI_MEMORY_RUSER_DEFAULT_WIDTH=64 // Width of the ruser signal. ++define+UVMA_OBI_MEMORY_ADDR_DEFAULT_WIDTH=32 // Width of the addr signal. ++define+UVMA_OBI_MEMORY_DATA_DEFAULT_WIDTH=64 // Width of the rdata and wdata signals. be width is DATA_WIDTH / 8. Valid DATA_WIDTH settings are 32 and 64. ++define+UVMA_OBI_MEMORY_ID_DEFAULT_WIDTH=10 // Width of the aid and rid signals. ++define+UVMA_OBI_MEMORY_ACHK_DEFAULT_WIDTH=10 // Width of the achk signal. ++define+UVMA_OBI_MEMORY_RCHK_DEFAULT_WIDTH=10 // Width of the rchk signal. + +-f ${DV_UVMA_OBI_MEMORY_PATH}/src/uvma_obi_memory_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 e82e80652..8bc495a0c 100644 --- a/verif/tb/uvmt/uvmt_cva6_dut_wrap.sv +++ b/verif/tb/uvmt/uvmt_cva6_dut_wrap.sv @@ -30,6 +30,7 @@ module uvmt_cva6_dut_wrap # ( ( uvma_clknrst_if clknrst_if, uvma_axi_intf axi_if, + uvma_obi_memory_if obi_fetch_if, uvmt_axi_switch_intf axi_switch_vif, uvmt_default_inputs_intf default_inputs_vif, uvme_cva6_core_cntrl_if core_cntrl_if, @@ -64,6 +65,7 @@ module uvmt_cva6_dut_wrap # ( .debug_if ( debug_if ), .axi_slave ( axi_if ), .cvxif_if ( cvxif_vif ), + .obi_fetch_slave ( obi_fetch_if ), .axi_switch_vif ( axi_switch_vif ), .default_inputs_vif ( default_inputs_vif ), .tb_exit_o ( tb_exit_o ), diff --git a/verif/tb/uvmt/uvmt_cva6_pkg.sv b/verif/tb/uvmt/uvmt_cva6_pkg.sv index 9641dfc41..c7e106d78 100644 --- a/verif/tb/uvmt/uvmt_cva6_pkg.sv +++ b/verif/tb/uvmt/uvmt_cva6_pkg.sv @@ -30,6 +30,7 @@ `include "uvmt_axi_switch_intf.sv" `include "uvmt_default_inputs_intf.sv" `include "uvma_axi_intf.sv" +`include "uvma_obi_memory_if.sv" /** * Encapsulates all the types and test cases for the verification of an diff --git a/verif/tb/uvmt/uvmt_cva6_tb.sv b/verif/tb/uvmt/uvmt_cva6_tb.sv index 0bde61c74..ab3c7b284 100644 --- a/verif/tb/uvmt/uvmt_cva6_tb.sv +++ b/verif/tb/uvmt/uvmt_cva6_tb.sv @@ -75,6 +75,25 @@ module uvmt_cva6_tb; .reset_n(clknrst_if.reset_n) ); + //OBI in monitor mode + uvma_obi_memory_if obi_fetch_if ( + .clk(clknrst_if.clk), + .reset_n(clknrst_if.reset_n) + ); + + + //bind assertion module for obi interface + bind uvmt_cva6_dut_wrap uvma_obi_memory_assert_if_wrp #( + .AUSER_WIDTH(CVA6Cfg.ObiFetchbusCfg.OptionalCfg.AUserWidth), + .WUSER_WIDTH(CVA6Cfg.ObiFetchbusCfg.OptionalCfg.WUserWidth), + .RUSER_WIDTH(CVA6Cfg.ObiFetchbusCfg.OptionalCfg.RUserWidth), + .ADDR_WIDTH(CVA6Cfg.ObiFetchbusCfg.AddrWidth), + .DATA_WIDTH(CVA6Cfg.ObiFetchbusCfg.DataWidth), + .ID_WIDTH(CVA6Cfg.ObiFetchbusCfg.IdWidth), + .ACHK_WIDTH(CVA6Cfg.ObiFetchbusCfg.OptionalCfg.AChkWidth), + .RCHK_WIDTH(CVA6Cfg.ObiFetchbusCfg.OptionalCfg.RChkWidth), + .IS_1P2(1)) obi_fetch_assert(.obi(obi_fetch_if)); + uvmt_axi_switch_intf axi_switch_vif(); uvme_cva6_core_cntrl_if core_cntrl_if(); uvma_rvfi_instr_if #( @@ -127,6 +146,7 @@ module uvmt_cva6_tb; .clknrst_if(clknrst_if), .debug_if(debug_if), .axi_if (axi_if), + .obi_fetch_if (obi_fetch_if), .axi_switch_vif (axi_switch_vif), .default_inputs_vif (default_inputs_vif), .core_cntrl_if(core_cntrl_if), @@ -395,6 +415,7 @@ module uvmt_cva6_tb; uvm_config_db#(virtual uvma_cvxif_intf)::set(.cntxt(null), .inst_name("*"), .field_name("vif"), .value(cvxif_vif)); uvm_config_db#(virtual uvmt_tb_exit_if)::set(.cntxt(null), .inst_name("*"), .field_name("tb_exit_vif"), .value(tb_exit_if)); + uvm_config_db#(virtual uvma_obi_memory_if)::set(.cntxt(null), .inst_name("*obi_memory_instr_agent"), .field_name("vif"), .value(obi_fetch_if)); // DUT and ENV parameters uvm_config_db#(int)::set(.cntxt(null), .inst_name("*"), .field_name("ENV_PARAM_INSTR_ADDR_WIDTH"), .value(ENV_PARAM_INSTR_ADDR_WIDTH) ); diff --git a/verif/tests/uvmt/base-tests/uvmt_cva6_base_test.sv b/verif/tests/uvmt/base-tests/uvmt_cva6_base_test.sv index ffcac3a18..22f153144 100644 --- a/verif/tests/uvmt/base-tests/uvmt_cva6_base_test.sv +++ b/verif/tests/uvmt/base-tests/uvmt_cva6_base_test.sv @@ -263,6 +263,8 @@ function void uvmt_cva6_base_test_c::build_phase(uvm_phase phase); if(!env_cfg.axi_cfg.preload_mem) begin factory.set_type_override_by_name("uvma_axi_fw_preload_seq_c", "uvme_axi_fw_preload_seq_c"); + factory.set_type_override_by_name("uvma_obi_memory_fw_preload_seq_c", "uvme_obi_fw_preload_seq_c"); + factory.set_type_override_by_name("uvma_obi_memory_slv_seq_c", "uvme_obi_slv_seq_c"); end endfunction : build_phase