Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions hw/ip_templates/flash_ctrl/dv/env/flash_ctrl_bkdr_util.sv
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ class flash_ctrl_bkdr_util extends mem_bkdr_util;
// TODO; consider changing these functions to member functions and retaining the flash_addr_
// and flash_data_ keys as members.
static function bit [FlashDataWidth-1:0] flash_create_masked_data(
bit [FlashDataWidth-1:0] data, bit [FlashAddrWidth-1:0] byte_addr,
bit [FlashDataWidth-1:0] data, bit [FlashAddrWidth-1:0] word_addr,
bit [FlashKeySize-1:0] flash_addr_key, bit [FlashKeySize-1:0] flash_data_key);
bit [FlashNumRoundsHalf-1:0][FlashDataWidth-1:0] scrambled_data;
bit [FlashDataWidth-1:0] masked_data;
bit [FlashDataWidth-1:0] mask;

mask = flash_galois_multiply(flash_addr_key, byte_addr >> FlashDataByteWidth);
mask = flash_galois_multiply(flash_addr_key, word_addr);
masked_data = data ^ mask;

crypto_dpi_prince_pkg::sv_dpi_prince_encrypt(.plaintext(masked_data), .key(flash_data_key),
Expand All @@ -110,17 +110,19 @@ class flash_ctrl_bkdr_util extends mem_bkdr_util;
endfunction

virtual function void flash_write_scrambled(
bit [FlashDataWidth-1:0] data, bit [FlashAddrWidth-1:0] byte_addr,
bit [FlashDataWidth-1:0] data, bit [FlashAddrWidth-1:0] word_addr,
bit [FlashKeySize-1:0] flash_addr_key, bit [FlashKeySize-1:0] flash_data_key);
bit [FlashDataWidth-1:0] masked_data;
bit [71:0] ecc_72;
bit [75:0] ecc_76;
bit [flash_ctrl_top_specific_pkg::BusAddrByteW-1:0] byte_addr;

masked_data = flash_create_masked_data(data, byte_addr, flash_addr_key, flash_data_key);
masked_data = flash_create_masked_data(data, word_addr, flash_addr_key, flash_data_key);

// ecc functions used are hardcoded to a fixed sized.
ecc_72 = prim_secded_pkg::prim_secded_hamming_72_64_enc(data[63:0]);
ecc_76 = prim_secded_pkg::prim_secded_hamming_76_68_enc({ecc_72[67:64], masked_data[63:0]});
byte_addr = word_addr << FlashDataByteWidth;
write(byte_addr, ecc_76);
endfunction
endclass
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ filesets:
- seq_lib/flash_ctrl_hw_read_seed_err_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_hw_prog_rma_wipe_err_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_rd_ooo_vseq.sv: {is_include_file: true}
- seq_lib/flash_ctrl_basic_rw_vseq.sv: {is_include_file: true}
file_type: systemVerilogSource

generate:
Expand Down
1 change: 0 additions & 1 deletion hw/ip_templates/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,6 @@ class flash_ctrl_env_cfg extends cip_base_env_cfg #(
`uvm_create_obj(flash_otf_item, item)
flash_mem_otf_read(flash_op, item.fq);
flash_op.otf_addr = flash_op.addr;
flash_op.otf_addr[BusAddrByteW-2:OTFHostId] = 'h0;

item.region.scramble_en = MuBi4True;
item.region.ecc_en = (ecc_en)? MuBi4True : MuBi4False;
Expand Down
4 changes: 2 additions & 2 deletions hw/ip_templates/flash_ctrl/dv/env/flash_ctrl_env_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,11 @@ package flash_ctrl_env_pkg;
bit [FlashKeySize-1:0] flash_addr_key, bit [FlashKeySize-1:0] flash_data_key,
bit dis = 1);
bit [FlashDataWidth-1:0] masked_data;
bit [FlashAddrWidth-1:0] word_addr = byte_addr >> FlashDataByteWidth;

masked_data = flash_ctrl_bkdr_util::flash_create_masked_data(data, byte_addr, flash_addr_key,
masked_data = flash_ctrl_bkdr_util::flash_create_masked_data(data, word_addr, flash_addr_key,
flash_data_key);
if (dis) begin
bit [FlashAddrWidth-1:0] word_addr = byte_addr >> FlashDataByteWidth;
`uvm_info("SCR_DBG", $sformatf("addr:%x mask:%x din:%x dout:%x",
word_addr,
flash_ctrl_bkdr_util::flash_galois_multiply(flash_addr_key,
Expand Down
1 change: 1 addition & 0 deletions hw/ip_templates/flash_ctrl/dv/env/flash_otf_item.sv
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ class flash_otf_item extends uvm_object;
data = raw_fq[i][FlashDataWidth-1:0];
if (ecc_en) begin
data_with_icv = prim_secded_pkg::prim_secded_hamming_72_64_enc(raw_fq[i][63:0]);
`uvm_info("icv", $sformatf("ICV:%4b", data_with_icv[67:64]), UVM_DEBUG)
if (add_icv_err) begin
`uvm_info("icv_debug", $sformatf("before:%4b after:%4b",
data_with_icv[67:64], ~data_with_icv[67:64]), UVM_DEBUG)
Expand Down
81 changes: 39 additions & 42 deletions hw/ip_templates/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv
Original file line number Diff line number Diff line change
Expand Up @@ -331,26 +331,26 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
update_mp_region_cfg_mubifalse(region_cfg);
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].en, data,
region_cfg.en);
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].rd_en, data,
region_cfg.read_en);
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].prog_en, data,
region_cfg.program_en);
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].erase_en, data,
region_cfg.erase_en);
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].scramble_en,
data, region_cfg.scramble_en);
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].ecc_en, data,
region_cfg.ecc_en);
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].he_en, data,
region_cfg.he_en);
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].rd_en, data,
region_cfg.read_en);
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].prog_en, data,
region_cfg.program_en);
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].erase_en, data,
region_cfg.erase_en);
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].scramble_en,
data, region_cfg.scramble_en);
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].ecc_en, data,
region_cfg.ecc_en);
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].he_en, data,
region_cfg.he_en);
csr_wr(.ptr(ral.mp_region_cfg[index]), .value(data));

// reset for base/size register
data = 0;
data = get_csr_val_with_updated_field(ral.mp_region[index].base, data,
region_cfg.start_page);
data = data | get_csr_val_with_updated_field(ral.mp_region[index].size, data,
region_cfg.num_pages);
data = get_csr_val_with_updated_field(ral.mp_region[index].size, data,
region_cfg.num_pages);
csr_wr(.ptr(ral.mp_region[index]), .value(data));
endtask : flash_ctrl_mp_region_cfg

Expand All @@ -372,14 +372,11 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
cfg.default_region_cfg.he_en = he_en;

data = get_csr_val_with_updated_field(ral.default_region.rd_en, data, read_en);
data = data |
get_csr_val_with_updated_field(ral.default_region.prog_en, data, program_en);
data = data |
get_csr_val_with_updated_field(ral.default_region.erase_en, data, erase_en);
data = data |
get_csr_val_with_updated_field(ral.default_region.scramble_en, data, scramble_en);
data = data | get_csr_val_with_updated_field(ral.default_region.ecc_en, data, ecc_en);
data = data | get_csr_val_with_updated_field(ral.default_region.he_en, data, he_en);
data = get_csr_val_with_updated_field(ral.default_region.prog_en, data, program_en);
data = get_csr_val_with_updated_field(ral.default_region.erase_en, data, erase_en);
data = get_csr_val_with_updated_field(ral.default_region.scramble_en, data, scramble_en);
data = get_csr_val_with_updated_field(ral.default_region.ecc_en, data, ecc_en);
data = get_csr_val_with_updated_field(ral.default_region.he_en, data, he_en);
csr_wr(.ptr(ral.default_region), .value(data));
endtask : flash_ctrl_default_region_cfg

Expand All @@ -401,19 +398,20 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
`uvm_info("mp_info_page_cfg", $sformatf("%s: %p", csr_name, page_cfg), UVM_DEBUG)
csr = ral.get_reg_by_name(csr_name);
update_mp_info_cfg_mubifalse(page_cfg);
data = get_csr_val_with_updated_field(csr.get_field_by_name("en"), data, page_cfg.en);
data = data |
get_csr_val_with_updated_field(csr.get_field_by_name("rd_en"), data, page_cfg.read_en);
data = data |
get_csr_val_with_updated_field(csr.get_field_by_name("prog_en"), data, page_cfg.program_en);
data = data |
get_csr_val_with_updated_field(csr.get_field_by_name("erase_en"), data, page_cfg.erase_en);
data = data | get_csr_val_with_updated_field(csr.get_field_by_name("scramble_en"), data,
page_cfg.scramble_en);
data = data |
get_csr_val_with_updated_field(csr.get_field_by_name("ecc_en"), data, page_cfg.ecc_en);
data = data |
get_csr_val_with_updated_field(csr.get_field_by_name("he_en"), data, page_cfg.he_en);
data = get_csr_val_with_updated_field(csr.get_field_by_name("en"),
data, page_cfg.en);
data = get_csr_val_with_updated_field(csr.get_field_by_name("rd_en"),
data, page_cfg.read_en);
data = get_csr_val_with_updated_field(csr.get_field_by_name("prog_en"),
data, page_cfg.program_en);
data = get_csr_val_with_updated_field(csr.get_field_by_name("erase_en"),
data, page_cfg.erase_en);
data = get_csr_val_with_updated_field(csr.get_field_by_name("scramble_en"),
data, page_cfg.scramble_en);
data = get_csr_val_with_updated_field(csr.get_field_by_name("ecc_en"),
data, page_cfg.ecc_en);
data = get_csr_val_with_updated_field(csr.get_field_by_name("he_en"),
data, page_cfg.he_en);
csr_wr(.ptr(csr), .value(data));
endtask : flash_ctrl_mp_info_page_cfg

Expand Down Expand Up @@ -510,12 +508,12 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
partition_sel = flash_part_e'(|flash_op.partition);
info_sel = flash_op.partition >> 1;
data = get_csr_val_with_updated_field(ral.control.start, data, 1'b1);
data = data | get_csr_val_with_updated_field(ral.control.op, data, flash_op.op);
data = data | get_csr_val_with_updated_field(ral.control.prog_sel, data, flash_op.prog_sel);
data = data | get_csr_val_with_updated_field(ral.control.erase_sel, data, flash_op.erase_type);
data = data | get_csr_val_with_updated_field(ral.control.partition_sel, data, partition_sel);
data = data | get_csr_val_with_updated_field(ral.control.info_sel, data, info_sel);
data = data | get_csr_val_with_updated_field(ral.control.num, data, flash_op.num_words - 1);
data = get_csr_val_with_updated_field(ral.control.op, data, flash_op.op);
data = get_csr_val_with_updated_field(ral.control.prog_sel, data, flash_op.prog_sel);
data = get_csr_val_with_updated_field(ral.control.erase_sel, data, flash_op.erase_type);
data = get_csr_val_with_updated_field(ral.control.partition_sel, data, partition_sel);
data = get_csr_val_with_updated_field(ral.control.info_sel, data, info_sel);
data = get_csr_val_with_updated_field(ral.control.num, data, flash_op.num_words - 1);
csr_wr(.ptr(ral.control), .value(data));
endtask : flash_ctrl_start_op

Expand Down Expand Up @@ -1169,7 +1167,6 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(

if (cfg.seq_cfg.check_mem_post_tran) begin
flash_op_copy.otf_addr = flash_op_copy.addr;
flash_op_copy.otf_addr[BusAddrByteW-2:OTFHostId] = 'h0;
cfg.flash_mem_bkdr_read_check(flash_op_copy, exp_data, check_match, scr_en, ecc_en);
end
endtask : flash_ctrl_write_extra
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// flash_ctrl_basic_rw

// This test does the following in a loop:
// 0. randomize scramble_en, ecc_en, data, address
// 1. initialize flash with all ones
// 2. program flash with random data
// 3. read back data through host interface
// 4. read back data through controller interface

class flash_ctrl_basic_rw_vseq extends flash_ctrl_base_vseq;
`uvm_object_utils(flash_ctrl_basic_rw_vseq)

`uvm_object_new

// Class Members
rand data_q_t flash_op_data;
rand flash_op_t flash_op;
rand uint bank;
rand mubi4_t instr_type;
rand uint num_trans;
rand mubi4_t scramble_en, ecc_en;

constraint bank_c {bank inside {[0 : flash_ctrl_top_specific_pkg::NumBanks - 1]};}
constraint scramble_c {scramble_en inside {MuBi4True, MuBi4False};}
constraint ecc_c {ecc_en inside {MuBi4True, MuBi4False};}

constraint num_trans_c {num_trans < 100;}

// Constraint for controller address to be in relevant range for the selected partition.
constraint addr_c {
solve bank before flash_op;
flash_op.addr inside {[BytesPerBank * bank : BytesPerBank * (bank + 1)]};
flash_op.addr[2:0] == '0;
}

constraint flash_op_c {
// Bank Erase is only supported for Data & 1st Info Partitions
flash_op.partition == FlashPartData;

flash_op.op inside {flash_ctrl_top_specific_pkg::FlashOpProgram,
flash_ctrl_top_specific_pkg::FlashOpRead};

flash_op.num_words >= 10;
flash_op.num_words <= (FlashNumBusWords - flash_op.addr[TL_AW-1:TL_SZW]);
flash_op.num_words <= 256;
flash_op.num_words < (FlashPgmRes - flash_op.addr[TL_SZW+:FlashPgmResWidth]);
}

// Flash ctrl operation data queue - used for programming or reading the flash.
constraint flash_op_data_c {
solve flash_op before flash_op_data;

flash_op_data.size() == flash_op.num_words;
}

// Body
virtual task body();

// Local Variables
addr_t read_addr;
data_t rdata;
bit comp, exp_err;
data_q_t flash_op_rdata;

// Scoreboard knob for Blocking Read Data Checking
// Checks performed in this test
cfg.block_host_rd = 0;

// enable code execution
csr_wr(.ptr(ral.exec), .value(CODE_EXEC_KEY));

// Enable All Regions

// disable randomization for num_trans (loop variable)
num_trans.rand_mode(0);

for (int k = 0; k < num_trans; k++) begin

// re-randomize all variables
randomize();

// 0. initialize regions
init_flash_regions(scramble_en, ecc_en);

// 1. init flash memory to all ones
cfg.flash_mem_bkdr_init(FlashPartData, FlashMemInitSet);

// 2. program random data to flash
for (int i = 0; i < flash_op.num_words; i++) begin
`uvm_info(`gfn, $sformatf("DATA %p", flash_op_data[i]), UVM_HIGH)
end
flash_op.op = flash_ctrl_top_specific_pkg::FlashOpProgram;
flash_ctrl_base_vseq::flash_ctrl_write_extra(flash_op, flash_op_data, 1,
mubi4_test_true_strict(scramble_en),
mubi4_test_true_strict(ecc_en));

exp_err = 0;

// 3. Read from memory interface (direct read)
for (int i = 0; i < flash_op.num_words; i++) begin
read_addr = flash_op.addr + 4 * i;
instr_type = get_rand_mubi4_val(.t_weight(2),
.f_weight(2),
.other_weight(0));


do_direct_read(.addr(read_addr), .mask('1), .blocking(cfg.block_host_rd), .check_rdata(1),
.instr_type(instr_type), .rdata(rdata), .exp_rdata(flash_op_data[i]),
.exp_err_rsp(exp_err), .completed(comp));
cfg.clk_rst_vif.wait_clks($urandom_range(1, 10));
end
csr_utils_pkg::wait_no_outstanding_access();

// 4. Read from controller interface
flash_op.op = flash_ctrl_top_specific_pkg::FlashOpRead;
flash_ctrl_read_extra(flash_op, flash_op_rdata);
for (int i = 0; i < flash_op.num_words; i++) begin
if (flash_op_data[i] !== flash_op_rdata[i])
`uvm_error("rd-err", $sformatf("Read-back error: exp: %x is: %x", flash_op_data[i],
flash_op_rdata[i]))
csr_utils_pkg::wait_no_outstanding_access();
end
end

endtask : body

// Task to initialize the Flash Access
virtual task init_flash_regions(mubi4_t scramble_en, mubi4_t ecc_en);

// Memory Protection Regions
flash_mp_region_cfg_t mp_regions[flash_ctrl_top_specific_pkg::MpRegions];

for (int i = 0; i<flash_ctrl_top_specific_pkg::MpRegions; i++) begin
mp_regions[i].en = MuBi4False;
mp_regions[i].read_en = MuBi4True;
mp_regions[i].program_en = MuBi4True;
mp_regions[i].erase_en = MuBi4True;
mp_regions[i].scramble_en = scramble_en;
mp_regions[i].ecc_en = ecc_en;
mp_regions[i].he_en = MuBi4False;
mp_regions[i].start_page = 0;
mp_regions[i].num_pages = FlashNumPages;
end
mp_regions[0].en = MuBi4True;

// 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(MuBi4True), .program_en(MuBi4True),
.erase_en(MuBi4True), .scramble_en(scramble_en),
.ecc_en(ecc_en), .he_en(MuBi4False));

endtask : init_flash_regions

endclass : flash_ctrl_basic_rw_vseq
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@
`include "flash_ctrl_hw_read_seed_err_vseq.sv"
`include "flash_ctrl_hw_prog_rma_wipe_err_vseq.sv"
`include "flash_ctrl_rd_ooo_vseq.sv"
`include "flash_ctrl_basic_rw_vseq.sv"
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@
name: flash_ctrl_rw_evict_all_en
uvm_test_seq: flash_ctrl_rw_evict_vseq
run_opts: ["+scb_otf_en=1", "+ecc_mode=1", "+en_always_read=1",
"+en_always_prog=1", "en_rnd_data=0"]
"+en_always_prog=1", "+en_rnd_data=0"]
reseed: 40
}
{
Expand Down Expand Up @@ -473,6 +473,11 @@
"+otf_num_hr=100", "+en_always_read=1"]
reseed: 3
}
{
name: flash_ctrl_basic_rw
uvm_test_seq: flash_ctrl_basic_rw_vseq
reseed: 3
}
]

// List of regressions.
Expand Down
Loading
Loading