I have a randomized sequence with multiple foreach loops within inline constraints.
The simulation time is increased due to multiple foreach loops in the constraint. Is there a way to optimize the code in SystemVerilog to reduce the simulation time?
Without knowing what you are trying to accomplish, it is difficult to provide any recommendations.
It seems like the constraints are just doing assignments to elements of a configuration object. Can you skip the randomization and just do the assignments? Or do the assignments first, disable the randomization for those elements, and then call randomize()?
Sorry I should have added more information earlier. I have added more code below:
I have dut_cfg class of uvm_object type which I want to randomize.
This dut_cfg class has ingress_traffic_cfg and link_cfg classes of uvm_object type. Both are of rand type.
The ingress_traffic_cfg and link_cfg has its own random variables. I am trying to set some of these random variables in foreach loop within the constraints.
class test_cfg extends uvm_object
`uvm_object_utils(test_cfg)
dut_cfg m_dut_cfg;
...........
endclass
class dut_cfg extends uvm_object;
`uvm_object_utils(dut_cfg)
rand ingress_traffic_cfg ingress_traffic_cfg_h;
rand link_cfg link_cfg_h;
.......
endclass
class ingress_traffic_cfg extends traffic_cfg;
`uvm_object_utils(ingress_traffic_cfg);
rand bit[47:0] da_pool [MAC_FILT_RULES_NUM]; // 32 unique randomized addresses when no multicast
rand int da_index[NUM_B][MAX_NUM_OF_INGRESS_STREAMS];
rand bit[47:0] mac_filt_mask [MAC_FILT_RULES_NUM];
rand int num_mac_port_da[NUM_OF_ETHERNET_LINKS];
rand int num_hp_da;
rand int num_da[NUM_B];
rand int num_hp_mcast_da;
rand int num_mcast_da[NUM_B];
constraint no_eth_adddress_overlap_con {
foreach (da_pool[i]) {
foreach (da_pool[j]) {
if (vlan_based_routing)
da_pool[i] == da_pool[j];
else {
if (i != j)
da_pool[i] != da_pool[j];
da_pool[i][40] == 0;
}
}
}
foreach (mac_filt_mask_m[i]) {
soft mac_filt_mask_m[i] == '0;
}
}
constraint eth_da_con {
foreach (num_mac_port_da[i]) {
num_mac_port_da[i] > 0;
num_mac_port_da[i] < MAC_FILT_RULES_NUM;
}
num_hp_da > 0;
num_hp_da < MAC_FILT_RULES_NUM;
foreach (num_da[i]) {
num_da[i] > 0;
num_da[i] < MAC_FILT_RULES_NUM;
}
if (enable_ing_hp_multiport) {
num_hp_mcast_da > 0;
num_hp_mcast_da < MAC_FILT_RULES_NUM;
} else {
num_hp_mcast_da == 0;
}
foreach (num_mcast_da[i]) {
if (enable_ing_multiport) {
num_mcast_da[i] > 0;
num_mcast_da[i] < MAC_FILT_RULES_NUM;
} else {
num_mcast_da[i] == 0;
}
}
num_da.sum() + num_hp_da + num_hp_mcast_da + num_mcast_da.sum() + num_mac_port_da.sum() <= MAC_FILT_RULES_NUM;
foreach (num_da[i]) {
foreach (str[j]) {
solve num_da before da_index[i][j];
if (enable_ing_multiport) {
da_index[i][j] < num_mcast_da[i];
da_index[i][j] >= 0;
} else {
da_index[i][j] < num_da[i];
da_index[i][j] >= 0;
}
}
}
}
........
endclass
class link_cfg extends uvm_object;
`uvm_object_utils(link_cfg);
rand bit[MAX_SWITCH_PORTS_NUM-1:0] ing_mcast_dest_port_ena[NUM_B][MAC_FILT_RULES_NUM];
rand int b_nr [NUM_OF_ETHERNET_LINKS];
constraint ing_mc_con {
foreach (ing_mcast_dest_port_ena[i, j]) {
if (i > PORT_NUMBER_USED_HIGH) {
ing_mcast_dest_port_ena[i][j] == 0; // Unused (or monitor) ports
}
if (i >= PORT_NUMBER_LOW && i <= PORT_NUMBER_HIGH) {
ing_mcast_dest_port_ena[i][j] == 1;
}
}
}
bit b[NUM_B]; // Used only for constraint loop
constraint b_nr_limit_con {
b_nr[0] == 0; // Constraint link0 to bip0 due to legacy code from ethss2.0
foreach (b_nr[i]) {
b_nr[i] >= 0;
b_nr[i] < NUM_B;
}
foreach(b[i]) {
b_nr.sum() with (int'(item == i)) >= 1;
}
}
.........
endclass
class base_seq extends base_vseq;
`uvm_object_utils(base_seq)
int link_nr [NUM_LINKS];
bit [MAX_SWITCH_PORTS_NUM - 1:0] ing_mcast_dest_port[NUM_B][];
rand int m_num_mac_port_da[NUM_LINKS];
rand int m_num_da[NUM_B];
rand int m_num_hp_da;
rand int m_num_hp_mcast_da;
rand int m_num_mcast_da[NUM_B];
rand bit [47:0] mac_filt_mask_m[MAC_FILT_RULES_NUM];
rand bit [47:0] da_pool_m [MAC_FILT_RULES_NUM];
rand int da_index_m[NUM_B][MAX_NUM_OF_INGRESS_STREAMS];
extern virtual function void randomize_cfg();
....
endclass
function void base_seq::randomize_cfg();
if (!p_sequencer.p_test_cfg.m_dut_cfg.randomize() with {
foreach (link_nr[i])
link_cfg_h.b_nr[i] == link_nr[i];
if (ingress_streams) {
foreach (da_pool_m[i])
ingress_traffic_cfg_h.da_pool[i] == da_pool_m[i];
foreach (da_index_m[i, j])
ingress_traffic_cfg_h.da_index[i][j] == da_index_m[i][j];
foreach (mac_filt_mask_m[i])
ingress_traffic_cfg_h.mac_filt_mask[i] == mac_filt_mask_m[i];
foreach (m_num_mac_port_da[i])
ingress_traffic_cfg_h.num_mac_port_da[i] == m_num_mac_port_da[i];
foreach (m_num_da[i])
ingress_traffic_cfg_h.num_da[i] == m_num_da[i];
ingress_traffic_cfg_h.num_hp_da == m_num_hp_da;
ingress_traffic_cfg_h.num_hp_mcast_da == m_num_hp_mcast_da;
foreach (m_num_mcast_da[i])
ingress_traffic_cfg_h.num_mcast_da[i] == m_num_mcast_da[i];
foreach (ing_mcast_dest_port[b_nr, i])
link_cfg_h.ing_dest_port_ena[b_nr][i] == ing_mcast_dest_port[b_nr][i];
}
}) begin
`uvm_fatal(`MSG_ID, "Failed to randomize dut_cfg")
end
endfunction : randomize_cfg
More number of foreach loops in the randomize_cfg function above is slowing down the simulation. I checked this with profiler on questa.