@@ -147,3 +147,93 @@ class ibex_valid_na4_stream extends riscv_directed_instr_stream;
147147 endfunction
148148
149149endclass
150+
151+ class ibex_cross_pmp_region_mem_access_stream extends riscv_directed_instr_stream ;
152+ `uvm_object_utils (ibex_cross_pmp_region_mem_access_stream)
153+
154+ int unsigned pmp_region;
155+ int unsigned region_mask;
156+ int unsigned region_size;
157+
158+ function new (string name = " " );
159+ super .new (name);
160+ endfunction
161+
162+ function void calc_region_params ();
163+ int unsigned cur_addr = cfg.pmp_cfg.pmp_cfg[pmp_region].addr;
164+
165+ region_size = 8 ;
166+ region_mask = 32'hfffffffe ;
167+
168+ for (int i = 0 ; i < 29 ; ++ i) begin
169+ if ((cur_addr & 1 ) == 0 ) break ;
170+ region_size * = 2 ;
171+ cur_addr >>= 1 ;
172+ region_mask <<= 1 ;
173+ end
174+ endfunction
175+
176+ function int unsigned pmp_region_top_addr ();
177+ return ((cfg.pmp_cfg.pmp_cfg[pmp_region].addr & region_mask) << 2 ) + region_size;
178+ endfunction
179+
180+ function int unsigned pmp_region_bottom_addr ();
181+ return ((cfg.pmp_cfg.pmp_cfg[pmp_region].addr & region_mask) << 2 );
182+ endfunction
183+
184+ function void post_randomize ();
185+ int unsigned target_addr;
186+ int unsigned offset;
187+ riscv_pseudo_instr la_instr;
188+ riscv_instr mem_instr;
189+ bit access_at_top;
190+
191+ if (! std:: randomize (pmp_region) with {
192+ pmp_region > 1 ;
193+ pmp_region < cfg.pmp_cfg.pmp_num_regions;
194+ cfg.pmp_cfg.pmp_cfg[pmp_region].a == NAPOT ;
195+ } )
196+ begin
197+ `uvm_info (`gfn ,
198+ { " WARNING: Cannot choose random NAPOT PMP region, skipping cross PMP region access " ,
199+ " generation" } , UVM_LOW )
200+ return ;
201+ end
202+
203+ initialize_instr_list (2 );
204+
205+ calc_region_params ();
206+
207+ mem_instr = riscv_instr :: get_load_store_instr ({ LH , LHU , LW , SH , SW } );
208+
209+ std:: randomize (access_at_top);
210+
211+ if (mem_instr.instr_name inside { LW , SW } ) begin
212+ std:: randomize (offset) with { offset < 3 ;offset > 0 ;} ;
213+ end else begin
214+ offset = 1 ;
215+ end
216+
217+ if (access_at_top) begin
218+ target_addr = pmp_region_top_addr () - offset;
219+ end else begin
220+ target_addr = pmp_region_bottom_addr () - offset;
221+ end
222+
223+ la_instr = riscv_pseudo_instr :: type_id :: create (" la_instr" );
224+ la_instr.pseudo_instr_name = LA ;
225+ la_instr.has_label = 1'b0 ;
226+ la_instr.atomic = 1'b1 ;
227+ la_instr.imm_str = $sformatf (" 0x%x " , target_addr);
228+ la_instr.rd = cfg.gpr[1 ];
229+
230+ randomize_gpr (mem_instr);
231+ mem_instr.has_imm = 0 ;
232+ mem_instr.imm_str = " 0" ;
233+ mem_instr.rs1 = cfg.gpr[1 ];
234+
235+ instr_list = { la_instr, mem_instr} ;
236+
237+ super .post_randomize ();
238+ endfunction
239+ endclass
0 commit comments