Skip to content

Commit f1dc9d0

Browse files
gautschimivogelpi
authored andcommitted
[dv,flash_ctrl] add basic rw test
Adds a basic test that 1. configures scramble, ecc_en 2. programs the flash, 3. read back memory over the host interface, 4. read backs the memory over the controller interface Signed-off-by: Michael Gautschi <[email protected]>
1 parent 44a0b23 commit f1dc9d0

18 files changed

+630
-129
lines changed

hw/ip_templates/flash_ctrl/dv/env/flash_ctrl_env.core.tpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ filesets:
9696
- seq_lib/flash_ctrl_hw_read_seed_err_vseq.sv: {is_include_file: true}
9797
- seq_lib/flash_ctrl_hw_prog_rma_wipe_err_vseq.sv: {is_include_file: true}
9898
- seq_lib/flash_ctrl_rd_ooo_vseq.sv: {is_include_file: true}
99+
- seq_lib/flash_ctrl_basic_rw_vseq.sv: {is_include_file: true}
99100
file_type: systemVerilogSource
100101

101102
generate:

hw/ip_templates/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,6 @@ class flash_ctrl_env_cfg extends cip_base_env_cfg #(
699699
`uvm_create_obj(flash_otf_item, item)
700700
flash_mem_otf_read(flash_op, item.fq);
701701
flash_op.otf_addr = flash_op.addr;
702-
flash_op.otf_addr[BusAddrByteW-2:OTFHostId] = 'h0;
703702

704703
item.region.scramble_en = MuBi4True;
705704
item.region.ecc_en = (ecc_en)? MuBi4True : MuBi4False;

hw/ip_templates/flash_ctrl/dv/env/seq_lib/flash_ctrl_base_vseq.sv

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -331,26 +331,26 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
331331
update_mp_region_cfg_mubifalse(region_cfg);
332332
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].en, data,
333333
region_cfg.en);
334-
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].rd_en, data,
335-
region_cfg.read_en);
336-
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].prog_en, data,
337-
region_cfg.program_en);
338-
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].erase_en, data,
339-
region_cfg.erase_en);
340-
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].scramble_en,
341-
data, region_cfg.scramble_en);
342-
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].ecc_en, data,
343-
region_cfg.ecc_en);
344-
data = data | get_csr_val_with_updated_field(ral.mp_region_cfg[index].he_en, data,
345-
region_cfg.he_en);
334+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].rd_en, data,
335+
region_cfg.read_en);
336+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].prog_en, data,
337+
region_cfg.program_en);
338+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].erase_en, data,
339+
region_cfg.erase_en);
340+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].scramble_en,
341+
data, region_cfg.scramble_en);
342+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].ecc_en, data,
343+
region_cfg.ecc_en);
344+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].he_en, data,
345+
region_cfg.he_en);
346346
csr_wr(.ptr(ral.mp_region_cfg[index]), .value(data));
347347

348348
// reset for base/size register
349349
data = 0;
350350
data = get_csr_val_with_updated_field(ral.mp_region[index].base, data,
351351
region_cfg.start_page);
352-
data = data | get_csr_val_with_updated_field(ral.mp_region[index].size, data,
353-
region_cfg.num_pages);
352+
data = get_csr_val_with_updated_field(ral.mp_region[index].size, data,
353+
region_cfg.num_pages);
354354
csr_wr(.ptr(ral.mp_region[index]), .value(data));
355355
endtask : flash_ctrl_mp_region_cfg
356356

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

374374
data = get_csr_val_with_updated_field(ral.default_region.rd_en, data, read_en);
375-
data = data |
376-
get_csr_val_with_updated_field(ral.default_region.prog_en, data, program_en);
377-
data = data |
378-
get_csr_val_with_updated_field(ral.default_region.erase_en, data, erase_en);
379-
data = data |
380-
get_csr_val_with_updated_field(ral.default_region.scramble_en, data, scramble_en);
381-
data = data | get_csr_val_with_updated_field(ral.default_region.ecc_en, data, ecc_en);
382-
data = data | get_csr_val_with_updated_field(ral.default_region.he_en, data, he_en);
375+
data = get_csr_val_with_updated_field(ral.default_region.prog_en, data, program_en);
376+
data = get_csr_val_with_updated_field(ral.default_region.erase_en, data, erase_en);
377+
data = get_csr_val_with_updated_field(ral.default_region.scramble_en, data, scramble_en);
378+
data = get_csr_val_with_updated_field(ral.default_region.ecc_en, data, ecc_en);
379+
data = get_csr_val_with_updated_field(ral.default_region.he_en, data, he_en);
383380
csr_wr(.ptr(ral.default_region), .value(data));
384381
endtask : flash_ctrl_default_region_cfg
385382

@@ -401,19 +398,20 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
401398
`uvm_info("mp_info_page_cfg", $sformatf("%s: %p", csr_name, page_cfg), UVM_DEBUG)
402399
csr = ral.get_reg_by_name(csr_name);
403400
update_mp_info_cfg_mubifalse(page_cfg);
404-
data = get_csr_val_with_updated_field(csr.get_field_by_name("en"), data, page_cfg.en);
405-
data = data |
406-
get_csr_val_with_updated_field(csr.get_field_by_name("rd_en"), data, page_cfg.read_en);
407-
data = data |
408-
get_csr_val_with_updated_field(csr.get_field_by_name("prog_en"), data, page_cfg.program_en);
409-
data = data |
410-
get_csr_val_with_updated_field(csr.get_field_by_name("erase_en"), data, page_cfg.erase_en);
411-
data = data | get_csr_val_with_updated_field(csr.get_field_by_name("scramble_en"), data,
412-
page_cfg.scramble_en);
413-
data = data |
414-
get_csr_val_with_updated_field(csr.get_field_by_name("ecc_en"), data, page_cfg.ecc_en);
415-
data = data |
416-
get_csr_val_with_updated_field(csr.get_field_by_name("he_en"), data, page_cfg.he_en);
401+
data = get_csr_val_with_updated_field(csr.get_field_by_name("en"),
402+
data, page_cfg.en);
403+
data = get_csr_val_with_updated_field(csr.get_field_by_name("rd_en"),
404+
data, page_cfg.read_en);
405+
data = get_csr_val_with_updated_field(csr.get_field_by_name("prog_en"),
406+
data, page_cfg.program_en);
407+
data = get_csr_val_with_updated_field(csr.get_field_by_name("erase_en"),
408+
data, page_cfg.erase_en);
409+
data = get_csr_val_with_updated_field(csr.get_field_by_name("scramble_en"),
410+
data, page_cfg.scramble_en);
411+
data = get_csr_val_with_updated_field(csr.get_field_by_name("ecc_en"),
412+
data, page_cfg.ecc_en);
413+
data = get_csr_val_with_updated_field(csr.get_field_by_name("he_en"),
414+
data, page_cfg.he_en);
417415
csr_wr(.ptr(csr), .value(data));
418416
endtask : flash_ctrl_mp_info_page_cfg
419417

@@ -510,12 +508,12 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
510508
partition_sel = flash_part_e'(|flash_op.partition);
511509
info_sel = flash_op.partition >> 1;
512510
data = get_csr_val_with_updated_field(ral.control.start, data, 1'b1);
513-
data = data | get_csr_val_with_updated_field(ral.control.op, data, flash_op.op);
514-
data = data | get_csr_val_with_updated_field(ral.control.prog_sel, data, flash_op.prog_sel);
515-
data = data | get_csr_val_with_updated_field(ral.control.erase_sel, data, flash_op.erase_type);
516-
data = data | get_csr_val_with_updated_field(ral.control.partition_sel, data, partition_sel);
517-
data = data | get_csr_val_with_updated_field(ral.control.info_sel, data, info_sel);
518-
data = data | get_csr_val_with_updated_field(ral.control.num, data, flash_op.num_words - 1);
511+
data = get_csr_val_with_updated_field(ral.control.op, data, flash_op.op);
512+
data = get_csr_val_with_updated_field(ral.control.prog_sel, data, flash_op.prog_sel);
513+
data = get_csr_val_with_updated_field(ral.control.erase_sel, data, flash_op.erase_type);
514+
data = get_csr_val_with_updated_field(ral.control.partition_sel, data, partition_sel);
515+
data = get_csr_val_with_updated_field(ral.control.info_sel, data, info_sel);
516+
data = get_csr_val_with_updated_field(ral.control.num, data, flash_op.num_words - 1);
519517
csr_wr(.ptr(ral.control), .value(data));
520518
endtask : flash_ctrl_start_op
521519

@@ -1169,7 +1167,6 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
11691167

11701168
if (cfg.seq_cfg.check_mem_post_tran) begin
11711169
flash_op_copy.otf_addr = flash_op_copy.addr;
1172-
flash_op_copy.otf_addr[BusAddrByteW-2:OTFHostId] = 'h0;
11731170
cfg.flash_mem_bkdr_read_check(flash_op_copy, exp_data, check_match, scr_en, ecc_en);
11741171
end
11751172
endtask : flash_ctrl_write_extra
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
// flash_ctrl_basic_rw
6+
7+
// This test does the following in a loop:
8+
// 0. randomize scramble_en, ecc_en, data, address
9+
// 1. initialize flash with all ones
10+
// 2. program flash with random data
11+
// 3. read back data through host interface
12+
// 4. read back data through controller interface
13+
14+
class flash_ctrl_basic_rw_vseq extends flash_ctrl_base_vseq;
15+
`uvm_object_utils(flash_ctrl_basic_rw_vseq)
16+
17+
`uvm_object_new
18+
19+
// Class Members
20+
rand data_q_t flash_op_data;
21+
rand flash_op_t flash_op;
22+
rand uint bank;
23+
rand mubi4_t instr_type;
24+
rand uint num_trans;
25+
rand mubi4_t scramble_en, ecc_en;
26+
27+
constraint bank_c {bank inside {[0 : flash_ctrl_top_specific_pkg::NumBanks - 1]};}
28+
constraint scramble_c {scramble_en inside {MuBi4True, MuBi4False};}
29+
constraint ecc_c {ecc_en inside {MuBi4True, MuBi4False};}
30+
31+
constraint num_trans_c {num_trans < 100;}
32+
33+
// Constraint for controller address to be in relevant range for the selected partition.
34+
constraint addr_c {
35+
solve bank before flash_op;
36+
flash_op.addr inside {[BytesPerBank * bank : BytesPerBank * (bank + 1)]};
37+
flash_op.addr[2:0] == '0;
38+
}
39+
40+
constraint flash_op_c {
41+
// Bank Erase is only supported for Data & 1st Info Partitions
42+
flash_op.partition == FlashPartData;
43+
44+
flash_op.op inside {flash_ctrl_top_specific_pkg::FlashOpProgram,
45+
flash_ctrl_top_specific_pkg::FlashOpRead};
46+
47+
flash_op.num_words >= 10;
48+
flash_op.num_words <= (FlashNumBusWords - flash_op.addr[TL_AW-1:TL_SZW]);
49+
flash_op.num_words <= 256;
50+
flash_op.num_words < (FlashPgmRes - flash_op.addr[TL_SZW+:FlashPgmResWidth]);
51+
}
52+
53+
// Flash ctrl operation data queue - used for programming or reading the flash.
54+
constraint flash_op_data_c {
55+
solve flash_op before flash_op_data;
56+
57+
flash_op_data.size() == flash_op.num_words;
58+
}
59+
60+
// Body
61+
virtual task body();
62+
63+
// Local Variables
64+
addr_t read_addr;
65+
data_t rdata;
66+
bit comp, exp_err;
67+
data_q_t flash_op_rdata;
68+
69+
// Scoreboard knob for Blocking Read Data Checking
70+
// Checks performed in this test
71+
cfg.block_host_rd = 0;
72+
73+
// enable code execution
74+
csr_wr(.ptr(ral.exec), .value(CODE_EXEC_KEY));
75+
76+
// Enable All Regions
77+
78+
// disable randomization for num_trans (loop variable)
79+
num_trans.rand_mode(0);
80+
81+
for (int k = 0; k < num_trans; k++) begin
82+
83+
// re-randomize all variables
84+
randomize();
85+
86+
// 0. initialize regions
87+
init_flash_regions(scramble_en, ecc_en);
88+
89+
// 1. init flash memory to all ones
90+
cfg.flash_mem_bkdr_init(FlashPartData, FlashMemInitSet);
91+
92+
// 2. program random data to flash
93+
for (int i = 0; i < flash_op.num_words; i++) begin
94+
`uvm_info(`gfn, $sformatf("DATA %p", flash_op_data[i]), UVM_HIGH)
95+
end
96+
flash_op.op = flash_ctrl_top_specific_pkg::FlashOpProgram;
97+
flash_ctrl_base_vseq::flash_ctrl_write_extra(flash_op, flash_op_data, 1,
98+
mubi4_test_true_strict(scramble_en),
99+
mubi4_test_true_strict(ecc_en));
100+
101+
exp_err = 0;
102+
103+
// 3. Read from memory interface (direct read)
104+
for (int i = 0; i < flash_op.num_words; i++) begin
105+
read_addr = flash_op.addr + 4 * i;
106+
instr_type = get_rand_mubi4_val(.t_weight(2),
107+
.f_weight(2),
108+
.other_weight(0));
109+
110+
111+
do_direct_read(.addr(read_addr), .mask('1), .blocking(cfg.block_host_rd), .check_rdata(1),
112+
.instr_type(instr_type), .rdata(rdata), .exp_rdata(flash_op_data[i]),
113+
.exp_err_rsp(exp_err), .completed(comp));
114+
cfg.clk_rst_vif.wait_clks($urandom_range(1, 10));
115+
end
116+
csr_utils_pkg::wait_no_outstanding_access();
117+
118+
// 4. Read from controller interface
119+
flash_op.op = flash_ctrl_top_specific_pkg::FlashOpRead;
120+
flash_ctrl_read_extra(flash_op, flash_op_rdata);
121+
for (int i = 0; i < flash_op.num_words; i++) begin
122+
if (flash_op_data[i] !== flash_op_rdata[i])
123+
`uvm_error("rd-err", $sformatf("Read-back error: exp: %x is: %x", flash_op_data[i],
124+
flash_op_rdata[i]))
125+
csr_utils_pkg::wait_no_outstanding_access();
126+
end
127+
end
128+
129+
endtask : body
130+
131+
// Task to initialize the Flash Access
132+
virtual task init_flash_regions(mubi4_t scramble_en, mubi4_t ecc_en);
133+
134+
// Memory Protection Regions
135+
flash_mp_region_cfg_t mp_regions[flash_ctrl_top_specific_pkg::MpRegions];
136+
137+
for (int i = 0; i<flash_ctrl_top_specific_pkg::MpRegions; i++) begin
138+
mp_regions[i].en = MuBi4False;
139+
mp_regions[i].read_en = MuBi4True;
140+
mp_regions[i].program_en = MuBi4True;
141+
mp_regions[i].erase_en = MuBi4True;
142+
mp_regions[i].scramble_en = scramble_en;
143+
mp_regions[i].ecc_en = ecc_en;
144+
mp_regions[i].he_en = MuBi4False;
145+
mp_regions[i].start_page = 0;
146+
mp_regions[i].num_pages = FlashNumPages;
147+
end
148+
mp_regions[0].en = MuBi4True;
149+
150+
// Initialize MP Regions
151+
foreach (mp_regions[k]) begin
152+
flash_ctrl_mp_region_cfg(k, mp_regions[k]);
153+
`uvm_info(`gfn, $sformatf("MP regions values %p", mp_regions[k]), UVM_HIGH)
154+
end
155+
156+
// Initialize Default Regions
157+
flash_ctrl_default_region_cfg(
158+
.read_en(MuBi4True), .program_en(MuBi4True),
159+
.erase_en(MuBi4True), .scramble_en(scramble_en),
160+
.ecc_en(ecc_en), .he_en(MuBi4False));
161+
162+
endtask : init_flash_regions
163+
164+
endclass : flash_ctrl_basic_rw_vseq

hw/ip_templates/flash_ctrl/dv/env/seq_lib/flash_ctrl_vseq_list.sv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@
6565
`include "flash_ctrl_hw_read_seed_err_vseq.sv"
6666
`include "flash_ctrl_hw_prog_rma_wipe_err_vseq.sv"
6767
`include "flash_ctrl_rd_ooo_vseq.sv"
68+
`include "flash_ctrl_basic_rw_vseq.sv"

hw/ip_templates/flash_ctrl/dv/flash_ctrl_base_sim_cfg.hjson.tpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,11 @@
473473
"+otf_num_hr=100", "+en_always_read=1"]
474474
reseed: 3
475475
}
476+
{
477+
name: flash_ctrl_basic_rw
478+
uvm_test_seq: flash_ctrl_basic_rw_vseq
479+
reseed: 3
480+
}
476481
]
477482

478483
// List of regressions.

hw/top_earlgrey/ip_autogen/flash_ctrl/dv/env/flash_ctrl_env.core

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ filesets:
9696
- seq_lib/flash_ctrl_hw_read_seed_err_vseq.sv: {is_include_file: true}
9797
- seq_lib/flash_ctrl_hw_prog_rma_wipe_err_vseq.sv: {is_include_file: true}
9898
- seq_lib/flash_ctrl_rd_ooo_vseq.sv: {is_include_file: true}
99+
- seq_lib/flash_ctrl_basic_rw_vseq.sv: {is_include_file: true}
99100
file_type: systemVerilogSource
100101

101102
generate:

hw/top_earlgrey/ip_autogen/flash_ctrl/dv/env/flash_ctrl_env_cfg.sv

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,6 @@ class flash_ctrl_env_cfg extends cip_base_env_cfg #(
699699
`uvm_create_obj(flash_otf_item, item)
700700
flash_mem_otf_read(flash_op, item.fq);
701701
flash_op.otf_addr = flash_op.addr;
702-
flash_op.otf_addr[BusAddrByteW-2:OTFHostId] = 'h0;
703702

704703
item.region.scramble_en = MuBi4True;
705704
item.region.ecc_en = (ecc_en)? MuBi4True : MuBi4False;

0 commit comments

Comments
 (0)