Skip to content

Commit 0f3144b

Browse files
martin-velayrswarbrick
authored andcommitted
[acrc,dv] Prepare for smoke test
- add a bunch of random variables to base_vseq - add tasks to configure the related DUT CSRs from base_vseq - prepare the SCB to detect these CSRs updates - at this point I can run a very constraint sequence and see acrc_smoke activity on the filtered TL bus. - /!\ no checks are performed from the SCB,it doesn't even detect any activity on the bus! Signed-off-by: Martin Velay <[email protected]>
1 parent fd566bf commit 0f3144b

File tree

11 files changed

+594
-80
lines changed

11 files changed

+594
-80
lines changed

hw/ip_templates/ac_range_check/dv/env/ac_range_check_env_pkg.sv

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
package ac_range_check_env_pkg;
6+
// Dep packages
7+
import uvm_pkg::*;
8+
import top_pkg::*;
9+
import dv_utils_pkg::*;
10+
import tl_agent_pkg::*;
11+
import dv_lib_pkg::*;
12+
import cip_base_pkg::*;
13+
import dv_base_reg_pkg::*;
14+
import csr_utils_pkg::*;
15+
import ac_range_check_ral_pkg::*;
16+
17+
// Macro includes
18+
`include "uvm_macros.svh"
19+
`include "dv_macros.svh"
20+
21+
// Imports from packages
22+
import prim_mubi_pkg::mubi4_t;
23+
import prim_mubi_pkg::mubi4_bool_to_mubi;
24+
import prim_mubi_pkg::mubi4_logic_test_true_strict;
25+
import prim_mubi_pkg::mubi8_t;
26+
import prim_mubi_pkg::MuBi8False;
27+
28+
// Parameters
29+
parameter uint NUM_ALERTS = 2;
30+
parameter string LIST_OF_ALERTS[] = {"recov_ctrl_update_err", "fatal_fault"};
31+
parameter uint NUM_RANGES = ${num_ranges};
32+
33+
// Types
34+
typedef enum int {
35+
DenyCntReached = 0
36+
} ac_range_check_intr_e;
37+
38+
typedef struct packed {
39+
bit log_denied_access;
40+
bit execute_access;
41+
bit write_access;
42+
bit read_access;
43+
bit enable;
44+
} range_perm_t;
45+
46+
typedef struct packed {
47+
bit [15:0] write_perm;
48+
bit [15:0] read_perm;
49+
} racl_policy_t;
50+
51+
typedef struct packed {
52+
bit rand_write;
53+
bit write;
54+
bit rand_addr;
55+
bit [AddrWidth-1:0] addr;
56+
bit rand_mask;
57+
bit [MaskWidth-1:0] mask;
58+
bit rand_data;
59+
bit [DataWidth-1:0] data;
60+
} tl_main_vars_t;
61+
62+
typedef enum bit [1:0] {
63+
AddrRead = 0,
64+
AddrWrite = 1,
65+
DataRead = 2,
66+
DataWrite = 3
67+
} tl_phase_e;
68+
69+
// Functions
70+
// Retrieve the index of the CSR based on its name
71+
function automatic int get_csr_idx(string csr_ral_name, string csr_name);
72+
string csr_name_with_idx;
73+
for (int idx=0; idx<NUM_RANGES; idx++) begin
74+
csr_name_with_idx = $sformatf("%0s_%0d", csr_name, idx);
75+
if (csr_name_with_idx == csr_ral_name) begin
76+
return idx;
77+
end
78+
end
79+
return -1;
80+
endfunction : get_csr_idx
81+
82+
// Package sources
83+
`include "ac_range_check_env_cfg.sv"
84+
`include "ac_range_check_env_cov.sv"
85+
`include "ac_range_check_virtual_sequencer.sv"
86+
`include "ac_range_check_scoreboard.sv"
87+
`include "ac_range_check_env.sv"
88+
`include "ac_range_check_vseq_list.sv"
89+
endpackage : ac_range_check_env_pkg

hw/ip_templates/ac_range_check/dv/env/ac_range_check_scoreboard.sv

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,51 +94,100 @@ endtask : process_tl_filt_fifo
9494
task ac_range_check_scoreboard::process_tl_access(tl_seq_item item,
9595
tl_channels_e channel,
9696
string ral_name);
97-
uvm_reg csr;
98-
bit do_read_check = 1'b1;
99-
bit write = item.is_write();
100-
uvm_reg_addr_t csr_addr = cfg.ral_models[ral_name].get_word_aligned_addr(item.a_addr);
101-
102-
bit addr_phase_read = (!write && channel == AddrChannel);
103-
bit addr_phase_write = ( write && channel == AddrChannel);
104-
bit data_phase_read = (!write && channel == DataChannel);
105-
bit data_phase_write = ( write && channel == DataChannel);
97+
uvm_reg csr;
98+
string csr_name;
99+
int csr_idx = -1;
100+
bit do_read_check = 1'b1;
101+
bit write = item.is_write();
102+
uvm_reg_addr_t csr_addr = cfg.ral_models[ral_name].get_word_aligned_addr(item.a_addr);
103+
tl_phase_e tl_phase;
104+
105+
if (!write && channel == AddrChannel) tl_phase = AddrRead;
106+
if ( write && channel == AddrChannel) tl_phase = AddrWrite;
107+
if (!write && channel == DataChannel) tl_phase = DataRead;
108+
if ( write && channel == DataChannel) tl_phase = DataWrite;
106109

107110
// If access was to a valid csr, get the csr handle
108111
if (csr_addr inside {cfg.ral_models[ral_name].csr_addrs}) begin
109112
csr = cfg.ral_models[ral_name].default_map.get_reg_by_offset(csr_addr);
110113
`DV_CHECK_NE_FATAL(csr, null)
114+
// When the CSR is defined as an array, simplify the name to make it generic. This will be
115+
// useful if the template parameter "num_ranges" is changed.
116+
if (csr.get_type_name() == "ac_range_check_reg_range_regwen") begin
117+
csr_name = "range_regwen";
118+
end else if (csr.get_type_name() == "ac_range_check_reg_range_base") begin
119+
csr_name = "range_base";
120+
end else if (csr.get_type_name() == "ac_range_check_reg_range_limit") begin
121+
csr_name = "range_limit";
122+
end else if (csr.get_type_name() == "ac_range_check_reg_range_perm") begin
123+
csr_name = "range_perm";
124+
end else if (csr.get_type_name() == "ac_range_check_reg_range_racl_policy_shadowed") begin
125+
csr_name = "range_racl_policy_shadowed";
126+
end else begin
127+
csr_name = csr.get_name();
128+
end
111129
end else begin
112130
`uvm_fatal(`gfn, $sformatf("Access unexpected addr 0x%0h", csr_addr))
113131
end
114132

133+
csr_idx = get_csr_idx(csr.get_name(), csr_name);
134+
115135
// If incoming access is a write to a valid csr, then make updates right away
116-
if (addr_phase_write) begin
136+
if (tl_phase == AddrWrite) begin
117137
void'(csr.predict(.value(item.a_data), .kind(UVM_PREDICT_WRITE), .be(item.a_mask)));
118138
end
119139

120140
// Process the csr req:
121141
// - for write, update local variable and fifo at address phase
122142
// - for read, update predication at address phase and compare at data phase
123-
case (csr.get_name())
143+
case (csr_name)
124144
// Add individual case item for each csr
125145
"intr_state": begin
126146
// FIXME TODO MVy
127-
do_read_check = 1'b0;
128147
end
129148
"intr_enable": begin
130149
// FIXME TODO MVy
131150
end
132151
"intr_test": begin
133152
// FIXME TODO MVy
134153
end
154+
"alert_test": begin
155+
// FIXME TODO MVy
156+
end
157+
"alert_status": begin
158+
// FIXME TODO MVy
159+
end
160+
"log_config": begin
161+
// FIXME TODO MVy
162+
end
163+
"log_status": begin
164+
// FIXME TODO MVy
165+
end
166+
"log_address": begin
167+
// FIXME TODO MVy
168+
end
169+
"range_regwen": begin
170+
// FIXME TODO MVy
171+
end
172+
"range_base": begin
173+
// FIXME TODO MVy
174+
end
175+
"range_limit": begin
176+
// FIXME TODO MVy
177+
end
178+
"range_perm": begin
179+
// FIXME TODO MVy
180+
end
181+
"range_racl_policy_shadowed": begin
182+
// FIXME TODO MVy
183+
end
135184
default: begin
136185
`uvm_fatal(`gfn, $sformatf("invalid csr: %0s", csr.get_full_name()))
137186
end
138187
endcase
139188

140189
// On reads, if do_read_check, is set, then check mirrored_value against item.d_data
141-
if (data_phase_read) begin
190+
if (tl_phase == DataRead) begin
142191
if (do_read_check) begin
143192
`DV_CHECK_EQ(csr.get_mirrored_value(), item.d_data,
144193
$sformatf("reg name: %0s", csr.get_full_name()))

hw/ip_templates/ac_range_check/dv/env/seq_lib/ac_range_check_base_vseq.sv

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
// SPDX-License-Identifier: Apache-2.0
44

5+
// Base sequence from which all other sequences must be derived. It contains the instantiation of
6+
// the "dut_cfg" class which itself contains all variables relating to the DUT configuration.
7+
// By default, we keep TL transactions random, as this can easily be overridden by derived
8+
// sequences if required, as the constraints are declared "soft".
59
class ac_range_check_base_vseq extends cip_base_vseq #(
610
.RAL_T (ac_range_check_reg_block),
711
.CFG_T (ac_range_check_env_cfg),
@@ -13,15 +17,39 @@ class ac_range_check_base_vseq extends cip_base_vseq #(
1317
// Various knobs to enable certain routines
1418
bit do_ac_range_check_init = 1'b1;
1519

20+
// Randomized variables
21+
rand tl_main_vars_t tl_main_vars;
22+
rand bit [TL_DW-1:0] range_base[NUM_RANGES]; // Granularity is 32-bit words, 2-LSBs are ignored
23+
rand bit [TL_DW-1:0] range_limit[NUM_RANGES]; // Granularity is 32-bit words, 2-LSBs are ignored
24+
rand range_perm_t range_perm[NUM_RANGES];
25+
rand racl_policy_t range_racl_policy[NUM_RANGES];
26+
27+
// Constraints
28+
extern constraint tl_main_vars_c;
29+
1630
// Standard SV/UVM methods
1731
extern function new(string name="");
1832

1933
// Class specific methods
2034
extern task dut_init(string reset_kind = "HARD");
2135
extern task ac_range_check_init();
36+
extern task cfg_range_base();
37+
extern task cfg_range_limit();
38+
extern task cfg_range_perm();
39+
extern task cfg_range_racl_policy();
40+
extern task send_single_tl_unfilt_tr(tl_main_vars_t main_vars);
41+
extern task tl_filt_device_auto_resp(int min_rsp_delay = 0, int max_rsp_delay = 80,
42+
int rsp_abort_pct = 25, int d_error_pct = 0, int d_chan_intg_err_pct = 0);
2243
endclass : ac_range_check_base_vseq
2344

2445

46+
constraint ac_range_check_base_vseq::tl_main_vars_c {
47+
soft tl_main_vars.rand_write == 1;
48+
soft tl_main_vars.rand_addr == 1;
49+
soft tl_main_vars.rand_mask == 1;
50+
soft tl_main_vars.rand_data == 1;
51+
}
52+
2553
function ac_range_check_base_vseq::new(string name="");
2654
super.new(name);
2755
endfunction : new
@@ -31,11 +59,88 @@ task ac_range_check_base_vseq::dut_init(string reset_kind = "HARD");
3159
if (do_ac_range_check_init) begin
3260
ac_range_check_init();
3361
end
62+
63+
// Spawns off a thread to auto-respond to incoming TL accesses on the Filtered host interface.
64+
// Note: the fork is required as the called sequence will loop indefinitely.
65+
fork
66+
tl_filt_device_auto_resp();
67+
join_none
3468
endtask : dut_init
3569

3670
task ac_range_check_base_vseq::ac_range_check_init();
37-
bit [TL_DW-1:0] tmp_test;
38-
csr_wr(.ptr(ral.range_base[0]), .value(32'hABCD_1234));
39-
csr_rd(.ptr(ral.range_base[0]), .value(tmp_test));
40-
`uvm_info(`gfn, $sformatf("tmp_test=%0h", tmp_test), UVM_LOW)
71+
// This fork will ensure that configuration takes place in "disorder", as the TL register
72+
// sequencer will have to deal with parallel requests (and random delays).
73+
fork
74+
cfg_range_base();
75+
cfg_range_limit();
76+
cfg_range_perm();
77+
cfg_range_racl_policy();
78+
join
79+
// TODO lastly, randomly lock the configuration with RANGE_REGWEN
4180
endtask : ac_range_check_init
81+
82+
// Only update registers whose value does not match the new one (usage of set+update instead write)
83+
task ac_range_check_base_vseq::cfg_range_base();
84+
foreach (range_base[i]) begin
85+
ral.range_base[i].set(range_base[i]);
86+
csr_update(.csr(ral.range_base[i]));
87+
end
88+
endtask : cfg_range_base
89+
90+
task ac_range_check_base_vseq::cfg_range_limit();
91+
foreach (range_limit[i]) begin
92+
ral.range_limit[i].set(range_limit[i]);
93+
csr_update(.csr(ral.range_limit[i]));
94+
end
95+
endtask : cfg_range_limit
96+
97+
task ac_range_check_base_vseq::cfg_range_perm();
98+
foreach (range_perm[i]) begin
99+
ral.range_perm[i].set(mubi4_bool_to_mubi(range_perm[i].log_denied_access));
100+
ral.range_perm[i].set(mubi4_bool_to_mubi(range_perm[i].execute_access ));
101+
ral.range_perm[i].set(mubi4_bool_to_mubi(range_perm[i].write_access ));
102+
ral.range_perm[i].set(mubi4_bool_to_mubi(range_perm[i].read_access ));
103+
ral.range_perm[i].set(mubi4_bool_to_mubi(range_perm[i].enable ));
104+
csr_update(.csr(ral.range_perm[i]));
105+
end
106+
endtask : cfg_range_perm
107+
108+
task ac_range_check_base_vseq::cfg_range_racl_policy();
109+
foreach (range_racl_policy[i]) begin
110+
ral.range_racl_policy_shadowed[i].set(range_racl_policy[i]);
111+
// Shadowed register: the 2 writes are automatically managed by the csr_utils_pkg
112+
csr_update(.csr(ral.range_racl_policy_shadowed[i]));
113+
end
114+
endtask : cfg_range_racl_policy
115+
116+
task ac_range_check_base_vseq::send_single_tl_unfilt_tr(tl_main_vars_t main_vars);
117+
tl_host_single_seq tl_unfilt_host_seq;
118+
`uvm_create_on(tl_unfilt_host_seq, p_sequencer.tl_unfilt_sqr)
119+
`DV_CHECK_RANDOMIZE_WITH_FATAL( tl_unfilt_host_seq,
120+
(!main_vars.rand_write) -> (write == main_vars.write);
121+
(!main_vars.rand_addr ) -> (addr == main_vars.addr);
122+
(!main_vars.rand_mask ) -> (mask == main_vars.mask);
123+
(!main_vars.rand_data ) -> (data == main_vars.data);)
124+
125+
csr_utils_pkg::increment_outstanding_access();
126+
`uvm_info(`gfn, "Starting tl_unfilt_host_seq", UVM_MEDIUM)
127+
`DV_SPINWAIT(`uvm_send(tl_unfilt_host_seq), "Timed out when sending fetch request")
128+
csr_utils_pkg::decrement_outstanding_access();
129+
endtask : send_single_tl_unfilt_tr
130+
131+
task ac_range_check_base_vseq::tl_filt_device_auto_resp(int min_rsp_delay = 0,
132+
int max_rsp_delay = 80,
133+
int rsp_abort_pct = 25,
134+
int d_error_pct = 0,
135+
int d_chan_intg_err_pct = 0);
136+
cip_tl_device_seq tl_filt_device_seq;
137+
tl_filt_device_seq = cip_tl_device_seq::type_id::create("tl_filt_device_seq");
138+
tl_filt_device_seq.min_rsp_delay = min_rsp_delay;
139+
tl_filt_device_seq.max_rsp_delay = max_rsp_delay;
140+
tl_filt_device_seq.rsp_abort_pct = rsp_abort_pct;
141+
tl_filt_device_seq.d_error_pct = d_error_pct;
142+
tl_filt_device_seq.d_chan_intg_err_pct = d_chan_intg_err_pct;
143+
`DV_CHECK_RANDOMIZE_FATAL(tl_filt_device_seq)
144+
`uvm_info(`gfn, "Starting tl_filt_device_seq", UVM_MEDIUM)
145+
tl_filt_device_seq.start(p_sequencer.tl_filt_sqr);
146+
endtask : tl_filt_device_auto_resp

0 commit comments

Comments
 (0)