[flash_ctrl] ADD TEST FOR THE HOST CTRL ARBITER
Perform operations via the Flash Software Interface, and at the same time invoke a
Hardware RMA operation. This verifies the arbitration within the Flash Protocol
Controller. The arbiter should allow any outstanding Software operations to complete
before the RMA starts. When the RMA completes the RMA FSM remains in its final state
until Reset and Software access is blocked.
Signed-off-by: TIM EWINS <tim.ewins@ensilica.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl_testplan.hjson b/hw/ip/flash_ctrl/data/flash_ctrl_testplan.hjson
index d198aac..2bf179c 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl_testplan.hjson
+++ b/hw/ip/flash_ctrl/data/flash_ctrl_testplan.hjson
@@ -60,7 +60,7 @@
{
name: rma_hw_if
desc: '''
- Perform RMA entry requests and check afterwards that the software has no access to
+ Perform RMA entry requests and check afterwards that the software has no access to
the Flash. After RMA entry, verify that the content of the flash is wiped out.
'''
milestone: V2
@@ -69,11 +69,14 @@
{
name: host_controller_arb
desc: '''
- Perform back-to-back operations via Software Interface and via Hardware Interface(key
- manager,life cycle) in order to test arbitration within Flash Protocol Controller.
+ Perform operations via the Flash Software Interface, and at the same time invoke a
+ Hardware RMA operation. This verifies the arbitration within the Flash Protocol
+ Controller. The arbiter should allow any outstanding Software operations to complete
+ before the RMA starts. When the RMA completes the RMA FSM remains in its final state
+ until Reset and software access is blocked.
'''
milestone: V2
- tests: []
+ tests: ["flash_ctrl_host_ctrl_arb"]
}
{
name: erase_suspend
@@ -123,14 +126,14 @@
{
name: host_interleave
desc: '''
- At same time, perform two read operations and the same time via hardware host and via
- controller. At same time, perform read operation via hardware host and program
+ At same time, perform two read operations and the same time via host and via
+ controller. At same time, perform read operation via host and program
operation via controller. Perform mentioned parallel operations at different addresses
- and on the same address (i.e. seed material). Expect that operations are successfully
+ and on the same address. Expect that operations are successfully
executed.
'''
milestone: V2
- tests: []
+ tests: ["flash_ctrl_phy_arb"]
}
{
name: memory_protection
@@ -146,7 +149,7 @@
{
name: fetch_code
desc: '''
- Test code fetch feature.
+ Test code fetch feature.
'''
milestone: V2
tests: []
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env.core b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env.core
index 917d08d..d10ec42 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env.core
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env.core
@@ -41,6 +41,7 @@
- seq_lib/flash_ctrl_hw_sec_otp_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_erase_suspend_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_hw_rma_vseq.sv: {is_include_file: true}
+ - seq_lib/flash_ctrl_host_ctrl_arb_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource
generate:
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv
index d11f1c8..93c363c 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv
@@ -147,7 +147,7 @@
for (int i = 0; i < flash_op.num_words; i++) begin
data[i] = mem_bkdr_util_h[flash_op.partition][addr_attrs.bank].read32(read_addr);
`uvm_info(`gfn, $sformatf(
- "flash_mem_bkdr_read: partition = %s , {%s} = 0x%0h",
+ "flash_mem_bkdr_read: partition = %s, {%s} = 0x%0h",
flash_op.partition.name(),
addr_attrs.sprint(),
data[i]
@@ -195,7 +195,7 @@
_flash_full_write(flash_op.partition, addr_attrs.bank, addr_attrs.bank_addr, loc_data);
`uvm_info(`gfn, $sformatf(
- "flash_mem_bkdr_write: partition = %s , {%s} = 0x%0h",
+ "flash_mem_bkdr_write: partition = %s, {%s} = 0x%0h",
flash_op.partition.name(),
addr_attrs.sprint(),
loc_data
@@ -321,7 +321,7 @@
`uvm_info(`gfn, $sformatf(
{
"flash_mem_bkdr_erase_check: Erase type = %s, bank = %0d, ",
- "partition = %s , %snum_words = %0d"
+ "partition = %s, %snum_words = %0d"
},
flash_op.erase_type.name(),
addr_attrs.bank,
@@ -336,7 +336,7 @@
`uvm_info(`gfn, $sformatf(
{
"flash_mem_bkdr_erase_check: Erase type = %s, bank: %0d, ",
- "partition: %s , %saddr: 0x%0h, data: 0x%0h"
+ "partition: %s, %saddr: 0x%0h, data: 0x%0h"
},
flash_op.erase_type.name(),
addr_attrs.bank,
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
index 7221c9d..1054cbd 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
@@ -173,6 +173,13 @@
// types
typedef class flash_ctrl_scoreboard;
+ // Parameter for Probing into the DUT RMA FSM
+ parameter string PRB_RMA_FSM = "tb.dut.u_flash_hw_if.state_q";
+ // Taken from enum type lcmgr_state_e in flash_ctrl_lcmgr.sv
+ parameter uint RMA_FSM_STATE_ST_RMA_RSP = 11'b10100100001;
+
+ // functions
+
// package sources
`include "flash_mem_bkdr_util.sv"
`include "flash_mem_addr_attrs.sv"
diff --git a/hw/ip/flash_ctrl/dv/env/flash_ctrl_if.sv b/hw/ip/flash_ctrl/dv/env/flash_ctrl_if.sv
index 8591a5f..282a9ae 100644
--- a/hw/ip/flash_ctrl/dv/env/flash_ctrl_if.sv
+++ b/hw/ip/flash_ctrl/dv/env/flash_ctrl_if.sv
@@ -32,7 +32,7 @@
otp_ctrl_pkg::flash_otp_key_req_t otp_req;
otp_ctrl_pkg::flash_otp_key_rsp_t otp_rsp = flash_ctrl_env_pkg::FLASH_OTP_RSP_DEFAULT;
- //JTAG
+ // JTAG
logic cio_tck;
logic cio_tms;
logic cio_tdi;
@@ -42,4 +42,4 @@
// alert
ast_dif_t flash_alert;
-endinterface
+endinterface : flash_ctrl_if
diff --git a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv
index 8c49f70..3e9684b 100644
--- a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv
+++ b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv
@@ -921,4 +921,15 @@
endtask : send_rma_req
+ // Task to Enable/Disable the 'Info' Partitions, Creator, Owner and Isolated, via the Lifetime
+ // Controller Interface
+ virtual task en_sw_rw_part_info (input flash_op_t flash_op, input lc_ctrl_pkg::lc_tx_t val);
+ if (flash_op.partition == FlashPartInfo) begin
+ cfg.flash_ctrl_vif.lc_creator_seed_sw_rw_en = val;
+ cfg.flash_ctrl_vif.lc_owner_seed_sw_rw_en = val;
+ cfg.flash_ctrl_vif.lc_iso_part_sw_rd_en = val;
+ cfg.flash_ctrl_vif.lc_iso_part_sw_wr_en = val;
+ end
+ endtask : en_sw_rw_part_info
+
endclass : flash_ctrl_base_vseq
diff --git a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_host_ctrl_arb_vseq.sv b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_host_ctrl_arb_vseq.sv
new file mode 100644
index 0000000..fa5e226
--- /dev/null
+++ b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_host_ctrl_arb_vseq.sv
@@ -0,0 +1,427 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+// name: host_controller_arb
+// desc: '''
+// Perform operations via the Flash Software Interface, and at the same time invoke a
+// Hardware RMA operation. This verifies the arbitration within the Flash Protocol
+// Controller. The arbiter should allow any outstanding Software operations to complete
+// before the RMA starts. When the RMA completes the RMA FSM remains in its final state
+// until Reset and software access is blocked.
+// '''
+// milestone: V2
+// tests: ["flash_ctrl_host_ctrl_arb"]
+
+// flash_ctrl_host_ctrl_arb Test
+
+// Pseudo Code
+// Initialise (All)
+// Loop (2) {
+// Initialize Flash Regions (Enable All MP Regions)
+// Number of Flash Operations is set to 64
+// Select a Flash Operation when to Apply an RMA (random)
+// loop (64) {
+// Do SW Flash Operation (random)
+// Apply RMA Request during Flash Operation (at selected point)
+// SW Flash Operations should complete successfully before and during
+// initial RMA Request period, after that when RMA is active, Software
+// is denied access. This remains valid until the DUT is Reset
+// }
+// Check that the RMA FSM Remains in its final state.
+// Reset DUT
+// Repeat
+// }
+
+import lc_ctrl_pkg::*;
+
+class flash_ctrl_host_ctrl_arb_vseq extends flash_ctrl_base_vseq;
+ `uvm_object_utils(flash_ctrl_host_ctrl_arb_vseq)
+
+ `uvm_object_new
+
+ // Class Members
+ bit poll_fifo_status = 0; // Turn off to make access more atomic
+ rand data_q_t flash_op_data;
+
+ rand flash_op_t flash_op;
+ rand uint bank;
+
+ // Class Constraints
+
+ // Constraint for Bank.
+ constraint bank_c {
+ bank inside {[0 : flash_ctrl_pkg::NumBanks - 1]};
+ }
+
+ // Constraint for controller address to be in relevant range the for the selected partition.
+ constraint addr_c {
+ solve bank before flash_op;
+ flash_op.addr inside {[BytesPerBank * bank : BytesPerBank * (bank + 1)]};
+ if (flash_op.partition != FlashPartData) {
+ flash_op.addr inside
+ {[0:InfoTypeBytes[flash_op.partition>>1]-1],
+ [BytesPerBank:BytesPerBank+InfoTypeBytes[flash_op.partition>>1]-1]};
+ }
+ }
+
+ // Constraint for the Flash Operation
+ constraint flash_op_c {
+ // Bank Erase is only supported for Data & 1st Info Partitions
+ flash_op.partition != FlashPartData && flash_op.partition != FlashPartInfo ->
+ flash_op.erase_type == flash_ctrl_pkg::FlashErasePage;
+
+ if (cfg.seq_cfg.op_readonly_on_info_partition) {
+ flash_op.partition == FlashPartInfo ->
+ flash_op.op == flash_ctrl_pkg::FlashOpRead;
+ }
+
+ if (cfg.seq_cfg.op_readonly_on_info1_partition) {
+ flash_op.partition == FlashPartInfo1 ->
+ flash_op.op == flash_ctrl_pkg::FlashOpRead;
+ }
+
+ if (flash_op.partition == FlashPartRedundancy) {
+ flash_op.op == flash_ctrl_pkg::FlashOpRead;
+ }
+
+ flash_op.op inside {[flash_ctrl_pkg::FlashOpRead : flash_ctrl_pkg::FlashOpErase]};
+ (flash_op.op == flash_ctrl_pkg::FlashOpErase) ->
+ flash_op.erase_type dist {
+ flash_ctrl_pkg::FlashErasePage :/ (100 - cfg.seq_cfg.op_erase_type_bank_pc),
+ flash_ctrl_pkg::FlashEraseBank :/ cfg.seq_cfg.op_erase_type_bank_pc
+ };
+
+ flash_op.num_words inside {[10 : FlashNumBusWords - flash_op.addr[TL_AW-1:TL_SZW]]};
+ flash_op.num_words <= cfg.seq_cfg.op_max_words;
+ flash_op.num_words < FlashPgmRes - flash_op.addr[TL_SZW+:FlashPgmResWidth];
+ }
+
+ // Flash ctrl operation data queue - used for programing or reading the flash.
+ constraint flash_op_data_c {
+ solve flash_op before flash_op_data;
+ if (flash_op.op inside {flash_ctrl_pkg::FlashOpRead, flash_ctrl_pkg::FlashOpProgram}) {
+ flash_op_data.size() == flash_op.num_words;
+ } else {
+ flash_op_data.size() == 0;
+ }
+ }
+
+ // Bit vector representing which of the mp region cfg CSRs to enable.
+ rand bit [flash_ctrl_pkg::MpRegions-1:0] en_mp_regions;
+
+ // Memory Protection Regions
+ constraint en_mp_regions_c {$countones(en_mp_regions) == cfg.seq_cfg.num_en_mp_regions;}
+
+ rand flash_mp_region_cfg_t mp_regions[flash_ctrl_pkg::MpRegions];
+
+ constraint mp_regions_c {
+ solve en_mp_regions before mp_regions;
+
+ foreach (mp_regions[i]) {
+ mp_regions[i].en == en_mp_regions[i];
+ mp_regions[i].read_en == 1;
+ mp_regions[i].program_en == 1;
+ mp_regions[i].erase_en == 1;
+ mp_regions[i].scramble_en == 0;
+ mp_regions[i].ecc_en == 0;
+ mp_regions[i].he_en dist {
+ 0 :/ (100 - cfg.seq_cfg.mp_region_he_en_pc),
+ 1 :/ cfg.seq_cfg.mp_region_he_en_pc
+ };
+
+ mp_regions[i].start_page inside {[0 : FlashNumPages - 1]};
+ mp_regions[i].num_pages inside {[1 : FlashNumPages - mp_regions[i].start_page]};
+ mp_regions[i].num_pages <= cfg.seq_cfg.mp_region_max_pages;
+
+ // If overlap is not allowed, then each configured region is uniquified.
+ // This creates an ascending order of mp_regions that are configured, so we shuffle it in
+ // post_randomize.
+ if (!cfg.seq_cfg.allow_mp_region_overlap) {
+ foreach (mp_regions[j]) {
+ if (i != j) {
+ !mp_regions[i].start_page inside {
+ [mp_regions[j].start_page:mp_regions[j].start_page + mp_regions[j].num_pages]
+ };
+ }
+ }
+ }
+ }
+ }
+
+ // Information partitions memory protection settings.
+ rand flash_bank_mp_info_page_cfg_t
+ mp_info_pages[flash_ctrl_pkg::NumBanks][flash_ctrl_pkg::InfoTypes][$];
+
+ constraint mp_info_pages_c {
+
+ foreach (mp_info_pages[i, j]) {
+ mp_info_pages[i][j].size() == flash_ctrl_pkg::InfoTypeSize[j];
+ foreach (mp_info_pages[i][j][k]) {
+ mp_info_pages[i][j][k].en == 1;
+ mp_info_pages[i][j][k].read_en == 1;
+ mp_info_pages[i][j][k].program_en == 1;
+ mp_info_pages[i][j][k].erase_en == 1;
+ mp_info_pages[i][j][k].scramble_en == 0;
+ mp_info_pages[i][j][k].ecc_en == 0;
+ mp_info_pages[i][j][k].he_en dist {
+ 0 :/ (100 - cfg.seq_cfg.mp_info_page_he_en_pc[i][j]),
+ 1 :/ cfg.seq_cfg.mp_info_page_he_en_pc[i][j]
+ };
+ }
+ }
+ }
+
+ rand bit default_region_read_en;
+ rand bit default_region_program_en;
+ rand bit default_region_erase_en;
+ bit default_region_scramble_en;
+ rand bit default_region_he_en;
+ rand bit default_region_ecc_en;
+
+ constraint default_region_read_en_c {default_region_read_en == 1;}
+ constraint default_region_program_en_c {default_region_program_en == 1;}
+ constraint default_region_erase_en_c {default_region_erase_en == 1;}
+
+ // Bank Erasability.
+ rand bit [flash_ctrl_pkg::NumBanks-1:0] bank_erase_en;
+
+ constraint bank_erase_en_c {
+ foreach (bank_erase_en[i]) {
+ bank_erase_en[i] == 1;
+ }
+ }
+
+ // High Endurance
+ constraint default_region_he_en_c {
+ default_region_he_en dist {
+ 1 :/ cfg.seq_cfg.default_region_he_en_pc,
+ 0 :/ (100 - cfg.seq_cfg.default_region_he_en_pc)
+ };
+ }
+
+ constraint default_region_ecc_en_c {default_region_ecc_en == 0;}
+
+ // Configure sequence knobs to tailor it to smoke seq.
+ virtual function void configure_vseq();
+
+ // Do no more than 16 words per op.
+ cfg.seq_cfg.op_max_words = 16;
+
+ // Enable NO memory protection regions
+ cfg.seq_cfg.num_en_mp_regions = 0;
+
+ // Enable High Endurance
+ cfg.seq_cfg.mp_region_he_en_pc = 50;
+ cfg.seq_cfg.default_region_he_en_pc = 50;
+
+ // Enable Read Only on Info Partitions
+ cfg.seq_cfg.op_readonly_on_info_partition = 1;
+ cfg.seq_cfg.op_readonly_on_info1_partition = 1;
+
+ endfunction : configure_vseq
+
+ // Body
+ virtual task body();
+
+ // Local Variables
+ bit result;
+ uint apply_rma;
+ uint num_ops;
+ event ev_rma_req;
+ string dut_prb;
+ uint rd_prb;
+ logic [RmaSeedWidth-1:0] rma_seed;
+
+ `uvm_info(`gfn, $sformatf("HOST CONTROL ARB TEST"), UVM_LOW)
+
+ // Iterate (Fixed to 2) Per Run
+ for (int i=0; i<2; i++)
+ begin
+
+ `uvm_info(`gfn, $sformatf("Iteration : %0d", i), UVM_LOW)
+
+ // Enable All Regions
+ init_flash_regions();
+
+ `uvm_info(`gfn, "Start SW Flash Operations, then randomly apply an RMA Request", UVM_HIGH)
+
+ // Define Number of Flash Operations, and when to apply the RMA Request in parallel
+ num_ops = 64;
+ apply_rma = $urandom_range((num_ops/2)-16, (num_ops/2)+16);
+
+ `uvm_info(`gfn, $sformatf("Apply RMA at Flash Operation : %0d", apply_rma+1), UVM_LOW)
+
+ // Perform random Flash Operations, and send an RMA Request when required
+ fork
+ begin
+ for (int op_cnt=0; op_cnt<num_ops; op_cnt++) begin
+ if (op_cnt == apply_rma) -> ev_rma_req;
+ do_sw_op(op_cnt, apply_rma, num_ops);
+ end
+ end
+ begin
+ @(ev_rma_req);
+ cfg.clk_rst_vif.wait_clks($urandom_range(5, 10));
+ `uvm_info(`gfn, "RMA REQUEST", UVM_LOW)
+ rma_seed = $urandom;
+ send_rma_req(rma_seed);
+ end
+ join
+
+ // Check the End State Of the RMA FSM - Uses Internal DUT Probing
+ dut_prb = PRB_RMA_FSM;
+
+ repeat (16)
+ begin
+ #($urandom_range(1000, 5000)*1us);
+ if (!uvm_hdl_read(dut_prb, rd_prb))
+ `uvm_error(`gfn, $sformatf("Unable to Read from DUT Probe : %s, FAIL", dut_prb))
+
+ if (rd_prb == RMA_FSM_STATE_ST_RMA_RSP)
+ `uvm_info(`gfn, "RMA FSM Remains in Final State 'StRmaRsp' - PASS", UVM_LOW)
+ else
+ `uvm_error(`gfn, "RMA FSM NOT in Final State 'StRmaRsp' - FAIL")
+ end
+
+ // RESET DUT
+
+ `uvm_info(`gfn, "RESET DUT", UVM_LOW)
+ lc_ctrl_if_rst(); // Restore lc_ctrl_if to Reset Values
+ apply_reset();
+
+ end
+
+ endtask : body
+
+ // Task to do a Software Flash Operation, checking arbitration between SW and RMA
+ virtual task do_sw_op(input uint op_cnt, input uint apply_rma, input uint num_ops);
+
+ // Local Variables
+ data_q_t exp_data;
+
+ // Randomize The Members of the Class
+ `DV_CHECK_RANDOMIZE_FATAL(this)
+ `uvm_info(`gfn, $sformatf(
+ "Flash Operation : Bank: %0d, flash_op: %0p, flash_op_data: %0p",
+ bank, flash_op, flash_op_data), UVM_LOW)
+
+ // If the 'Info' Partition is Selected, Turn On the HW Access Signals
+ // to allow SW access to Creator, Owner and Isolation Partitions
+ en_sw_rw_part_info(flash_op, lc_ctrl_pkg::On);
+
+ // Note: Once the RMA has started, these backdoor calls fail,
+ // so only apply them when SW has access
+ if (op_cnt <= apply_rma) begin
+ // Initialise Flash Content
+ cfg.flash_mem_bkdr_init(flash_op.partition, FlashMemInitInvalidate);
+ if (flash_op.op == flash_ctrl_pkg::FlashOpProgram) begin
+ cfg.flash_mem_bkdr_write(.flash_op(flash_op), .scheme(FlashMemInitSet));
+ end else begin
+ cfg.flash_mem_bkdr_write(.flash_op(flash_op), .scheme(FlashMemInitRandomize));
+ end
+ end
+
+ `uvm_info(`gfn, $sformatf("Flash Operation : %0d / %0d", op_cnt+1, num_ops), UVM_LOW)
+
+ // Start Controller Read, Program or Erase
+ unique case (flash_op.op)
+
+ FlashOpRead :
+ begin
+ flash_op_data.delete();
+ flash_ctrl_start_op(flash_op);
+ if (op_cnt <= apply_rma) begin // Expect Success
+ flash_ctrl_read(flash_op.num_words, flash_op_data, poll_fifo_status);
+ wait_flash_op_done();
+ `uvm_info(`gfn, $sformatf("Read Data : %0p", flash_op_data), UVM_LOW)
+ cfg.flash_mem_bkdr_read_check(flash_op, flash_op_data);
+ end else begin // Expect Fail
+ expect_flash_op_fail();
+ end
+ end
+
+ FlashOpProgram :
+ begin
+ exp_data = cfg.calculate_expected_data(flash_op, flash_op_data);
+ flash_ctrl_start_op(flash_op);
+ if (op_cnt <= apply_rma) begin // Expect Success
+ flash_ctrl_write(flash_op_data, poll_fifo_status);
+ wait_flash_op_done(.timeout_ns(cfg.seq_cfg.prog_timeout_ns));
+ `uvm_info(`gfn, $sformatf("Program Data : %0p", flash_op_data), UVM_LOW)
+ cfg.flash_mem_bkdr_read_check(flash_op, flash_op_data);
+ end else begin // Expect Fail
+ expect_flash_op_fail();
+ end
+ end
+
+ FlashOpErase :
+ begin
+ flash_ctrl_start_op(flash_op);
+ if (op_cnt <= apply_rma) begin // Expect Success
+ wait_flash_op_done(.timeout_ns(cfg.seq_cfg.erase_timeout_ns));
+ `uvm_info(`gfn, "Erase Data", UVM_LOW)
+ cfg.flash_mem_bkdr_erase_check(flash_op, exp_data);
+ end else begin // Expect Fail
+ expect_flash_op_fail();
+ end
+ end
+
+ default : `uvm_fatal(`gfn, "Flash Operation Unrecognised, FAIL")
+
+ endcase
+
+ // If the 'Info' Partition is Selected, Turn Off the HW Access Signals
+ // to disallow SW access to Creator, Owner and Isolation Partitions
+ en_sw_rw_part_info (flash_op, lc_ctrl_pkg::Off);
+
+ // Delay and resync to clk
+ #($urandom_range(100, 500)*0.01ms);
+ cfg.clk_rst_vif.wait_clks(1);
+
+ endtask : do_sw_op
+
+ // Task to initialize the Flash Access (Enable All Regions)
+ virtual task init_flash_regions();
+
+ // Scramble Disable
+ default_region_scramble_en = 0;
+
+ // Enable Bank Erase
+ flash_ctrl_bank_erase_cfg(.bank_erase_en(bank_erase_en));
+
+ // Initialize MP Regions
+ foreach (mp_regions[k]) begin
+ flash_ctrl_mp_region_cfg(k, mp_regions[k]);
+ `uvm_info(`gfn, $sformatf("MP regions values %p", mp_regions[k]), UVM_HIGH)
+ end
+
+ // Initialize Default Regions
+ flash_ctrl_default_region_cfg(
+ .read_en (default_region_read_en), .program_en (default_region_program_en),
+ .erase_en(default_region_erase_en), .scramble_en(default_region_scramble_en),
+ .ecc_en (default_region_ecc_en), .he_en (default_region_he_en));
+
+ // Initialize Info MP Regions
+ foreach (mp_info_pages[i, j, k]) begin
+ flash_ctrl_mp_info_page_cfg(i, j, k, mp_info_pages[i][j][k]);
+ `uvm_info(`gfn, $sformatf("MP INFO regions values %p", mp_info_pages[i][j][k]), UVM_HIGH)
+ end
+
+ endtask : init_flash_regions
+
+ // Task to wait for a Flash Operation Fail, and display this status
+ virtual task expect_flash_op_fail();
+
+ // Local Variables
+ bit result;
+
+ wait_flash_op_done_expect_timeout(.timeout_ns(100000), .result(result));
+ if (result == 1) // Expect a Timeout
+ `uvm_info(`gfn, "Timeout Seen - RMA is Blocking SW Access, Expected, PASS", UVM_LOW)
+ else
+ `uvm_error(`gfn, "Timeout Not Seen - RMA is NOT Blocking SW Access, Unexpected, FAIL")
+
+ endtask : expect_flash_op_fail
+
+endclass : flash_ctrl_host_ctrl_arb_vseq
diff --git a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_vseq_list.sv b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_vseq_list.sv
index 361ba66..6928e82 100644
--- a/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_vseq_list.sv
+++ b/hw/ip/flash_ctrl/dv/env/seq_lib/flash_ctrl_vseq_list.sv
@@ -16,3 +16,4 @@
`include "flash_ctrl_hw_sec_otp_vseq.sv"
`include "flash_ctrl_erase_suspend_vseq.sv"
`include "flash_ctrl_hw_rma_vseq.sv"
+`include "flash_ctrl_host_ctrl_arb_vseq.sv"
diff --git a/hw/ip/flash_ctrl/dv/flash_ctrl_sim_cfg.hjson b/hw/ip/flash_ctrl/dv/flash_ctrl_sim_cfg.hjson
index af8a3ec..6f2a758 100644
--- a/hw/ip/flash_ctrl/dv/flash_ctrl_sim_cfg.hjson
+++ b/hw/ip/flash_ctrl/dv/flash_ctrl_sim_cfg.hjson
@@ -108,7 +108,13 @@
run_opts: ["+test_timeout_ns=10000000000"]
reseed: 3
}
-
+ {
+ name: flash_ctrl_host_ctrl_arb
+ uvm_test_seq: flash_ctrl_host_ctrl_arb_vseq
+ run_opts: ["+zero_delays=1", "+test_timeout_ns=10000000000"]
+ reseed: 3
+ }
+
]
// List of regressions.