blob: 2abc71d5fb61325a18442608d703c37633fe5892 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Pseudo Code
// Backdoor Write to FLASH (Initialize)
// FLASH Read - Compare Frontdoor
// FLASH Erase (Includes Backdoor Erase Check)
// FLASH Program
// FLASH Read - Compare Frontdoor
// Simple sw_op test
class flash_ctrl_sw_op_vseq extends flash_ctrl_base_vseq;
`uvm_object_utils(flash_ctrl_sw_op_vseq)
// Class Members
flash_op_t flash_op;
uint bank;
// Bit vector representing which of the mp region cfg CSRs to enable.
bit [flash_ctrl_pkg::MpRegions-1:0] en_mp_regions;
// Indicates whether to poll before writing to the prog_fifo or reading from the rd_fifo. If interupts are
// enabled, the interrupt signals will be used instead. When set to 0, it will continuously write
// to prog_fifo / read from rd_fifo, relying on their natural backpressure mechanism.
bit poll_fifo_status;
// Flash Data Queue
rand data_q_t flash_op_data;
`uvm_object_new
// Configure sequence knobs to tailor it to this seq.
virtual function void configure_vseq();
// Enable NO memory protection regions.
cfg.seq_cfg.num_en_mp_regions = 0;
cfg.seq_cfg.poll_fifo_status_pc = 0;
cfg.seq_cfg.check_mem_post_tran = 1;
// Do Not enable access to any of the information partitions.
foreach (cfg.seq_cfg.mp_info_page_en_pc[i, j]) begin
cfg.seq_cfg.mp_info_page_en_pc[i][j] = 0;
end
endfunction
// Body
task body();
logic [TL_DW-1:0] rdata;
logic [TL_DW-1:0] exp_data [$];
mubi4_t default_region_read_en;
mubi4_t default_region_program_en;
mubi4_t default_region_erase_en;
// Configure the FLASH Controller
// Memory protection regions settings. One MP region, Single Page
flash_mp_region_cfg_t mp_regions [flash_ctrl_pkg::MpRegions];
foreach (mp_regions[i]) begin
mp_regions[i].en = mubi4_bool_to_mubi(en_mp_regions[i]);
mp_regions[i].read_en = MuBi4True;
mp_regions[i].program_en = MuBi4True;
mp_regions[i].erase_en = MuBi4True;
mp_regions[i].start_page = MuBi4False;
mp_regions[i].num_pages = MuBi4True;
end
default_region_read_en = MuBi4True;
default_region_program_en = MuBi4True;
default_region_erase_en = MuBi4True;
// Configure the flash based on the given settings
foreach (mp_regions[i]) begin
flash_ctrl_mp_region_cfg(i, mp_regions[i]);
end
flash_ctrl_default_region_cfg(.read_en(default_region_read_en),
.program_en(default_region_program_en),
.erase_en(default_region_erase_en));
// TEST SETUP
bank = 0; // Bank 0
flash_op.addr = 0; // Start Address
flash_op.partition = FlashPartData; // Data Partition
flash_op.num_words = 10; // Number Of Words
poll_fifo_status = 0; // FIFO Poll Status
// INITIALIZE FLASH
// Randomize Write Data
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(flash_op_data, flash_op_data.size == flash_op.num_words;)
// Invalidate the flash mem contents. We do this because we operate on and check a specific
// chunk of space. The rest of the flash mem is essentially dont-care. If the flash ctrl
// does not work correctly, the check will result in an access from the invalidated mem
// region exposing the issue.
cfg.flash_mem_bkdr_init(flash_op.partition, FlashMemInitInvalidate);
`uvm_info(`gfn, $sformatf("Starting backdoor write operation with random values"), UVM_LOW)
cfg.flash_mem_bkdr_write(.flash_op(flash_op), .scheme(FlashMemInitRandomize));
// FLASH READ 1
// Read Frontdoor, Compare Backdoor
// Select FLASH Read Operation
flash_op.op = flash_ctrl_pkg::FlashOpRead;
// Start Controller
flash_ctrl_start_op(flash_op);
flash_ctrl_read(flash_op.num_words, flash_op_data, poll_fifo_status);
wait_flash_op_done();
if (cfg.seq_cfg.check_mem_post_tran) cfg.flash_mem_bkdr_read_check(flash_op, flash_op_data);
// FLASH ERASE
// Select FLASH Read Operation
flash_op.op = flash_ctrl_pkg::FlashOpErase;
// Select Page Erase
flash_op.erase_type = flash_ctrl_pkg::FlashErasePage;
// Start Controller
flash_ctrl_start_op(flash_op);
wait_flash_op_done(.timeout_ns(cfg.seq_cfg.erase_timeout_ns));
if (cfg.seq_cfg.check_mem_post_tran) cfg.flash_mem_bkdr_erase_check(flash_op, exp_data);
// FLASH PROGRAM
// Write Frontdoor, Read backdoor
// Select FLASH Operation
flash_op.op = flash_ctrl_pkg::FlashOpProgram;
// Randomize Write Data
`DV_CHECK_MEMBER_RANDOMIZE_WITH_FATAL(flash_op_data, flash_op_data.size == flash_op.num_words;)
// Calculate expected data for post-transaction checks
exp_data = cfg.calculate_expected_data(flash_op, flash_op_data);
// Start Controller
flash_ctrl_start_op(flash_op);
flash_ctrl_write(flash_op_data, poll_fifo_status);
wait_flash_op_done(.timeout_ns(cfg.seq_cfg.prog_timeout_ns));
if (cfg.seq_cfg.check_mem_post_tran) cfg.flash_mem_bkdr_read_check(flash_op, exp_data);
// FLASH READ 2
// Read Frontdoor, Compare Backdoor
// Select FLASH Read Operation
flash_op.op = flash_ctrl_pkg::FlashOpRead;
// Start Controller
flash_ctrl_start_op(flash_op);
flash_ctrl_read(flash_op.num_words, flash_op_data, poll_fifo_status);
wait_flash_op_done();
if (cfg.seq_cfg.check_mem_post_tran) cfg.flash_mem_bkdr_read_check(flash_op, flash_op_data);
endtask : body
endclass : flash_ctrl_sw_op_vseq