@@ -147,3 +147,93 @@ class ibex_valid_na4_stream extends riscv_directed_instr_stream;
147
147
endfunction
148
148
149
149
endclass
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