Skip to content

Commit 0a0c41a

Browse files
committed
[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 ba301ee commit 0a0c41a

18 files changed

+618
-132
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: 31 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -328,29 +328,28 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
328328
flash_mp_region_cfg_t region_cfg = cfg.default_region_cfg);
329329
uvm_reg_data_t data;
330330
uvm_reg csr;
331-
update_mp_region_cfg_mubifalse(region_cfg);
332331
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].en, data,
333332
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);
333+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].rd_en, data,
334+
region_cfg.read_en);
335+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].prog_en, data,
336+
region_cfg.program_en);
337+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].erase_en, data,
338+
region_cfg.erase_en);
339+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].scramble_en,
340+
data, region_cfg.scramble_en);
341+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].ecc_en, data,
342+
region_cfg.ecc_en);
343+
data = get_csr_val_with_updated_field(ral.mp_region_cfg[index].he_en, data,
344+
region_cfg.he_en);
346345
csr_wr(.ptr(ral.mp_region_cfg[index]), .value(data));
347346

348347
// reset for base/size register
349348
data = 0;
350349
data = get_csr_val_with_updated_field(ral.mp_region[index].base, data,
351350
region_cfg.start_page);
352-
data = data | get_csr_val_with_updated_field(ral.mp_region[index].size, data,
353-
region_cfg.num_pages);
351+
data = get_csr_val_with_updated_field(ral.mp_region[index].size, data,
352+
region_cfg.num_pages);
354353
csr_wr(.ptr(ral.mp_region[index]), .value(data));
355354
endtask : flash_ctrl_mp_region_cfg
356355

@@ -372,14 +371,11 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
372371
cfg.default_region_cfg.he_en = he_en;
373372

374373
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);
374+
data = get_csr_val_with_updated_field(ral.default_region.prog_en, data, program_en);
375+
data = get_csr_val_with_updated_field(ral.default_region.erase_en, data, erase_en);
376+
data = get_csr_val_with_updated_field(ral.default_region.scramble_en, data, scramble_en);
377+
data = get_csr_val_with_updated_field(ral.default_region.ecc_en, data, ecc_en);
378+
data = get_csr_val_with_updated_field(ral.default_region.he_en, data, he_en);
383379
csr_wr(.ptr(ral.default_region), .value(data));
384380
endtask : flash_ctrl_default_region_cfg
385381

@@ -400,20 +396,13 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
400396
end
401397
`uvm_info("mp_info_page_cfg", $sformatf("%s: %p", csr_name, page_cfg), UVM_DEBUG)
402398
csr = ral.get_reg_by_name(csr_name);
403-
update_mp_info_cfg_mubifalse(page_cfg);
404399
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);
400+
data = get_csr_val_with_updated_field(csr.get_field_by_name("rd_en"), data, page_cfg.read_en);
401+
data = get_csr_val_with_updated_field(csr.get_field_by_name("prog_en"), data, page_cfg.program_en);
402+
data = get_csr_val_with_updated_field(csr.get_field_by_name("erase_en"), data, page_cfg.erase_en);
403+
data = get_csr_val_with_updated_field(csr.get_field_by_name("scramble_en"), data, page_cfg.scramble_en);
404+
data = get_csr_val_with_updated_field(csr.get_field_by_name("ecc_en"), data, page_cfg.ecc_en);
405+
data = get_csr_val_with_updated_field(csr.get_field_by_name("he_en"), data, page_cfg.he_en);
417406
csr_wr(.ptr(csr), .value(data));
418407
endtask : flash_ctrl_mp_info_page_cfg
419408

@@ -510,12 +499,12 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
510499
partition_sel = flash_part_e'(|flash_op.partition);
511500
info_sel = flash_op.partition >> 1;
512501
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);
502+
data = get_csr_val_with_updated_field(ral.control.op, data, flash_op.op);
503+
data = get_csr_val_with_updated_field(ral.control.prog_sel, data, flash_op.prog_sel);
504+
data = get_csr_val_with_updated_field(ral.control.erase_sel, data, flash_op.erase_type);
505+
data = get_csr_val_with_updated_field(ral.control.partition_sel, data, partition_sel);
506+
data = get_csr_val_with_updated_field(ral.control.info_sel, data, info_sel);
507+
data = get_csr_val_with_updated_field(ral.control.num, data, flash_op.num_words - 1);
519508
csr_wr(.ptr(ral.control), .value(data));
520509
endtask : flash_ctrl_start_op
521510

@@ -1169,7 +1158,6 @@ class flash_ctrl_base_vseq extends cip_base_vseq #(
11691158

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