diff --git a/dv/uvm/icache/data/ibex_icache_testplan.hjson b/dv/uvm/icache/data/ibex_icache_testplan.hjson index f25a1e1a..d8c5b129 100644 --- a/dv/uvm/icache/data/ibex_icache_testplan.hjson +++ b/dv/uvm/icache/data/ibex_icache_testplan.hjson @@ -36,7 +36,7 @@ could check this, but the unconstrained branch addresses mean it's very unlikely to see much caching going on.''' milestone: V2 - tests: [] + tests: ["ibex_icache_passthru"] } { diff --git a/dv/uvm/icache/dv/env/ibex_icache_env.core b/dv/uvm/icache/dv/env/ibex_icache_env.core index ac29f9e8..51c2ce1a 100644 --- a/dv/uvm/icache/dv/env/ibex_icache_env.core +++ b/dv/uvm/icache/dv/env/ibex_icache_env.core @@ -20,6 +20,7 @@ filesets: - seq_lib/ibex_icache_vseq_list.sv: {is_include_file: true} - seq_lib/ibex_icache_base_vseq.sv: {is_include_file: true} - seq_lib/ibex_icache_sanity_vseq.sv: {is_include_file: true} + - seq_lib/ibex_icache_passthru_vseq.sv: {is_include_file: true} file_type: systemVerilogSource targets: diff --git a/dv/uvm/icache/dv/env/seq_lib/ibex_icache_passthru_vseq.sv b/dv/uvm/icache/dv/env/seq_lib/ibex_icache_passthru_vseq.sv new file mode 100644 index 00000000..952b9f24 --- /dev/null +++ b/dv/uvm/icache/dv/env/seq_lib/ibex_icache_passthru_vseq.sv @@ -0,0 +1,34 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +class ibex_icache_passthru_vseq extends ibex_icache_base_vseq; + + `uvm_object_utils(ibex_icache_passthru_vseq) + `uvm_object_new + + // A passthru sequence for the core agent and a basic slave sequence for the memory agent + ibex_icache_core_passthru_seq core_seq; + ibex_icache_mem_resp_seq mem_seq; + + task body(); + // Start the core and memory sequences. We use fork/join_any so that we don't wait for the + // memory sequence (which is reactive so will never finish). + fork + begin + `uvm_create_on(core_seq, p_sequencer.core_sequencer_h) + `DV_CHECK_RANDOMIZE_FATAL(core_seq) + core_seq.start(p_sequencer.core_sequencer_h); + end + begin + `uvm_create_on(mem_seq, p_sequencer.mem_sequencer_h) + // Increase the frequency of seed updates + mem_seq.gap_between_seeds = 49; + + `DV_CHECK_RANDOMIZE_FATAL(mem_seq) + mem_seq.start(p_sequencer.mem_sequencer_h); + end + join_any + endtask : body + +endclass : ibex_icache_passthru_vseq diff --git a/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv b/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv index ea3a00bf..2965d6db 100644 --- a/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv +++ b/dv/uvm/icache/dv/env/seq_lib/ibex_icache_vseq_list.sv @@ -4,3 +4,4 @@ `include "ibex_icache_base_vseq.sv" `include "ibex_icache_sanity_vseq.sv" +`include "ibex_icache_passthru_vseq.sv" diff --git a/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_agent.core b/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_agent.core index 33cd1c97..2d540a0b 100644 --- a/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_agent.core +++ b/dv/uvm/icache/dv/ibex_icache_core_agent/ibex_icache_core_agent.core @@ -24,6 +24,7 @@ filesets: - ibex_icache_core_agent.sv: {is_include_file: true} - seq_lib/ibex_icache_core_base_seq.sv: {is_include_file: true} - seq_lib/ibex_icache_core_sanity_seq.sv: {is_include_file: true} + - seq_lib/ibex_icache_core_passthru_seq.sv: {is_include_file: true} - seq_lib/ibex_icache_core_seq_list.sv: {is_include_file: true} file_type: systemVerilogSource diff --git a/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv index 03cd31af..e892fa47 100644 --- a/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv +++ b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_base_seq.sv @@ -12,8 +12,85 @@ class ibex_icache_core_base_seq extends dv_base_seq #( `uvm_object_new + // Number of test items (note that a single test item may contain many instruction fetches) + protected rand int count; + constraint c_count { count inside {[800:1000]}; } + + // The base address used when constrain_branches is true. + protected rand bit[31:0] base_addr; + + // If this is set, the next request should be constrained to have trans_type + // ICacheCoreTransTypeBranch. It's initially 1 because the core must start with a branch to tell + // the cache where to fetch from in the first place. + protected bit force_branch = 1'b1; + + // If this is set, any branch target address should be within 64 bytes of base_addr and runs of + // instructions should have a maximum length of 100. + protected bit constrain_branches = 1'b0; + + // A count of the number of instructions fetched since the last branch. This is only important + // when constrain_branches is true, in which case we want to ensure that we don't fetch too much + // in a straight line between branches. + protected int unsigned insns_since_branch = 0; + + // If this bit is set, we will never enable the cache + protected bit force_disable = 1'b0; + virtual task body(); `uvm_fatal(`gtn, "Need to override this when you extend from this class!") endtask + // Generate and run a single item using class parameters + protected task run_req(ibex_icache_core_req_item req, ibex_icache_core_rsp_item rsp); + start_item(req); + + if (constrain_branches && insns_since_branch >= 100) + force_branch = 1'b1; + + `DV_CHECK_RANDOMIZE_WITH_FATAL( + req, + + // Force a branch if necessary + force_branch -> req.trans_type == ICacheCoreTransTypeBranch; + + // If this is a branch and constrain_branches is true then constrain any branch target. + (constrain_branches && (req.trans_type == ICacheCoreTransTypeBranch)) -> + req.branch_addr inside {[base_addr:(base_addr + 64)]}; + + // If this is a branch and constrain_branches is true, we can ask for up to 100 instructions + // (independent of insns_since_branch) + (constrain_branches && (req.trans_type == ICacheCoreTransTypeBranch)) -> + num_insns <= 100; + + // If this isn't a branch and constrain_branches is true, we can ask for up to 100 - + // insns_since_branch instructions. This will be positive because of the check above. + (constrain_branches && (req.trans_type != ICacheCoreTransTypeBranch)) -> + num_insns <= 100 - insns_since_branch; + + force_disable -> !toggle_enable; + ) + + finish_item(req); + get_response(rsp); + + // The next transaction must start with a branch if this one ended with an error + force_branch = rsp.saw_error; + + // Update insns_since_branch. Note that this will be an overestimate if we saw an error, but + // that doesn't matter because we'll force a branch next time either way. + insns_since_branch = (((req.trans_type == ICacheCoreTransTypeBranch) ? 0 : insns_since_branch) + + req.num_insns); + endtask + + // Generate and run count items. Subclasses probably want to configure the parameters above before + // running this. + protected task run_reqs(); + req = ibex_icache_core_req_item::type_id::create("req"); + rsp = ibex_icache_core_rsp_item::type_id::create("rsp"); + + repeat (count - 1) begin + run_req(req, rsp); + end + endtask + endclass diff --git a/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_passthru_seq.sv b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_passthru_seq.sv new file mode 100644 index 00000000..00346383 --- /dev/null +++ b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_passthru_seq.sv @@ -0,0 +1,21 @@ +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Passthru test sequence +// +// This is used for the passthru test. We constrain branch targets and leave the cache disabled. + +class ibex_icache_core_passthru_seq extends ibex_icache_core_base_seq; + `uvm_object_utils(ibex_icache_core_passthru_seq) + `uvm_object_new + + task body(); + // Overrides for base sequence + constrain_branches = 1'b1; + force_disable = 1'b1; + + run_reqs(); + endtask + +endclass diff --git a/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_sanity_seq.sv b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_sanity_seq.sv index 84dde6b5..bcd79560 100644 --- a/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_sanity_seq.sv +++ b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_sanity_seq.sv @@ -5,34 +5,14 @@ // Sanity test seq // // This is unlikely to find many cache hits (since it branches all over the 4GiB address space). + class ibex_icache_core_sanity_seq extends ibex_icache_core_base_seq; `uvm_object_utils(ibex_icache_core_sanity_seq) `uvm_object_new - rand int count; - constraint c_count { count inside {[800:1000]}; } - task body(); - // If this is set, the next request will be constrained to have trans_type - // ICacheCoreTransTypeBranch. It's initially 1 because the core must start with a branch to tell - // the cache where to fetch from in the first place. - bit force_branch = 1'b1; - - req = ibex_icache_core_req_item::type_id::create("req"); - rsp = ibex_icache_core_rsp_item::type_id::create("rsp"); - - repeat (count - 1) begin - start_item(req); - if (force_branch) begin - `DV_CHECK_RANDOMIZE_WITH_FATAL(req, req.trans_type == ICacheCoreTransTypeBranch;) - end else begin - `DV_CHECK_RANDOMIZE_FATAL(req) - end - finish_item(req); - get_response(rsp); - - // The next transaction must start with a branch if this one ended with an error. - force_branch = rsp.saw_error; - end + // No overrides needed in base sequence + run_reqs(); endtask + endclass diff --git a/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_seq_list.sv b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_seq_list.sv index d0bf8eb6..23cf0e7f 100644 --- a/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_seq_list.sv +++ b/dv/uvm/icache/dv/ibex_icache_core_agent/seq_lib/ibex_icache_core_seq_list.sv @@ -4,3 +4,4 @@ `include "ibex_icache_core_base_seq.sv" `include "ibex_icache_core_sanity_seq.sv" +`include "ibex_icache_core_passthru_seq.sv" diff --git a/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_resp_item.sv b/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_resp_item.sv index 3647d8e8..ccf641cc 100644 --- a/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_resp_item.sv +++ b/dv/uvm/icache/dv/ibex_icache_mem_agent/ibex_icache_mem_resp_item.sv @@ -9,6 +9,7 @@ class ibex_icache_mem_resp_item extends uvm_sequence_item; int unsigned min_response_delay = 0; int unsigned mid_response_delay = 5; int unsigned max_response_delay = 50; + int unsigned gap_between_seeds = 499; // True if this is a granted request. Otherwise, this is the first time we've seen an address (and // we might need to drive the PMP line). @@ -40,7 +41,7 @@ class ibex_icache_mem_resp_item extends uvm_sequence_item; constraint c_seed_dist { seed dist { - 32'd0 :/ 499, + 32'd0 :/ gap_between_seeds, [1:32'hffffffff] :/ 1 }; } diff --git a/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv b/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv index f6f18986..de96756b 100644 --- a/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv +++ b/dv/uvm/icache/dv/ibex_icache_mem_agent/seq_lib/ibex_icache_mem_resp_seq.sv @@ -6,7 +6,12 @@ class ibex_icache_mem_resp_seq extends ibex_icache_mem_base_seq; - ibex_icache_mem_model #(.BusWidth (32)) mem_model; + // Knobs + // + // gap_between_seeds is the expected number of memory fetches between each seed update. + int unsigned gap_between_seeds = 499; + + protected ibex_icache_mem_model #(.BusWidth (32)) mem_model; // We pick new seeds when we spot a request (rather than when we spot a grant) to ensure that // any given fetch corresponds to exactly one seed. Unfortunately, there's a race if these two @@ -37,6 +42,9 @@ class ibex_icache_mem_resp_seq extends ibex_icache_mem_base_seq; ibex_icache_mem_req_item req_item = new("req_item"); ibex_icache_mem_resp_item resp_item = new("resp_item"); + // Set knob to control randomization + resp_item.gap_between_seeds = gap_between_seeds; + forever begin // Wait for a transaction request. p_sequencer.request_fifo.get(req_item); diff --git a/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson b/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson index 185e0629..8f501bdc 100644 --- a/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson +++ b/dv/uvm/icache/dv/ibex_icache_sim_cfg.hjson @@ -22,7 +22,6 @@ // Import additional common sim cfg files. - // TODO: remove imported cfgs that do not apply. import_cfgs: [// Project wide common sim cfg file "{proj_root}/dv/uvm/data/common_sim_cfg.hjson"] @@ -45,14 +44,19 @@ run_opts: ["+test_timeout_ns=1000000000"] } - // TODO: add more tests here + { + name: ibex_icache_passthru + uvm_test_seq: ibex_icache_passthru_vseq + run_opts: ["+test_timeout_ns=1000000000"] + } ] // List of regressions. regressions: [ { name: sanity - tests: ["ibex_icache_sanity"] + tests: ["ibex_icache_sanity", + "ibex_icache_passthru"] } ] }