I want to instrument my system verilog model for collecting functional coverage on the packets it processes. Specifically, I want to see of the distribution of the packet length in the incoming packet. However, my naive attempt gives "null reference" on sample method below. What is the way to do this?
class packet;
rand bit[7:0] len;
covergroup packet_len_cg;
coverpoint len;
endgroup
endclass
class model;
// Scoreboard calls this to process the input packet
function void run(packet p1);
p1.packet_len_cg.sample(); //FAILS WITH NULL REFERENCE!!
endfunction
endclass
module test;
model m1;
packet p1;
initial begin
m1 = new();
p1 = new();
assert(p1.randomize());
m1.run(p1);
end
endmodule
My code on edaplayground https://www.edaplayground.com/x/2VPm
You need to construct the covergroup.
class packet;
rand bit[7:0] len;
covergroup packet_len_cg;
coverpoint len;
endgroup
function new;
packet_len_cg = new;
endfunction
endclass
Related
I am trying to write a cover point to check where 2 signals should occurring at the same time or not.
covergroup signal#(posedge clk)
signals : coverpoint (a, b){
bins on_off = {2'b11}
}
I just wanted to know whether it is the correct path of writing the cover point.
I think you meant to write coverpoint {a,b} using concatenation braces. That would work. Another thing you can do is
covergroup signal #(posedge clk);
signals : coverpoint a&b {
bins on = {1};
}
endgroup
How to ignore coverage bin for particular instance;
how to ignore bins one for cov2 instance ?
class cov extends uvm_subscriber # (transfer)
function new(string name, uvm_component parent);
super.new(name,parent);
cov_tr = new();
cov_tr.set_inst_name();
endfunction
function void write(transfer t);
ignore_one = t.ignore_one;
cov_tr.sample();
endfunction
covergroup cov_tr;
option.per_instance = 1;
tr_value : coverpoint tr_val {
bins one : 1;
bins next : [2:7];
}
endgroup
cov cov1,cov2;
master1.connect(cov1.analysis_port);
master2.connect(cov2.analysis_port);
You can use stop method to stop collection of coverage, in a procedural block.
cov2.cov_tr.stop();
This is not possible. Binning must be exactly the same for any instance of a given covergroup.
I'm creating coverage for my design and I want to reuse a covergroup definition for multiple instances. The first instance should use all of the coverpoints as intended, but for the second instance, I want to exclude some of the coverpoints in the covergroup.
I was thinking I could use an input to the covergroup and iff () the unwanted coverpoints such that the first instance ties the input to 1 and the second instance ties the input to 0. However I think this will still show the coverpoints for the second instance as always not hit, and I want them to not be included at all.
covergroup cg_address(input bit enable) # (posedge clock);
address_check: coverpoint (address){
bins addr_0 = {5'd0};
bins addr_1 = {5'd1};
}
data_check: coverpoint (data) iff (enable){
bins data_0 = {10'd0};
bins data_1 = {10'd1};
}
endgroup : cg_address
cg_address cg_address_inst0 = new(1'b1);
cg_address cg_address_inst1 = new(1'b0); //want this one to exclude data_check coverpoint
I know the above code won't work because the second instance will still have the data_check coverpoint, it will just never hit either bin because the enable is tied to 0. Is there any other way I can try to exclude the data_check coverpoint for the second instance?
You need to do two things:
Set the weight of the coverpoint to 0.
Turn on option.per_instance = 1; for the covergroup.
For example:
covergroup cg_address(input bit enable) # (posedge clock);
option.per_instance = 1;
address_check: coverpoint (address){
bins addr_0 = {5'd0};
bins addr_1 = {5'd1};
}
data_check: coverpoint (data) {
option.weight = enable;
bins data_0 = {10'd0};
bins data_1 = {10'd1};
}
endgroup : cg_address
cg_address cg_address_inst0 = new(1);
cg_address cg_address_inst1 = new(0); //want this one to exclude data_check coverpoint
I am getting an error to compile code line 9, so I am not sure how to dynamically access arrays. I have to build logic [255:0] from the received bytes.
(Looks like I have to review data types of SystemVerilog :( ).
Thanks in advance.
module test;
task test_array (logic [7:0] B);
static logic [255:0] l_ar_B;
l_ar_B[7:0] = B;
for(int i=0; i<32; i++)
l_ar_B[(i*8+7) : (i*8)] = B; // Error-[IRIPS] Illegal range in part select
$stop();
endtask
initial begin
$display("Start");
test_array(8'h11);
end
endmodule
When using the range selection with [M : N] syntax, M and N must be be constants. You should use part-select addressing with the syntax [s +: W], where W is a constant for the width and s can be a variable indicating the starting bit position. The +: been around since IEEE Std 1364-2001 (Verilog 2001). See
Indexing vectors and arrays with +:
for(int i=0; i<32; i++)
l_ar_B[(i*8) +: 8] = B;
Since you are doing replication, you can use l_ar_B = {32{B}}; to get the same result in a singe step.
I am trying to create a bin in my coverage group to sample values that are multiple of n (where n is a constant integer in my case 15). So far, I have came
up with the following code:
class rx_port;
int unsigned rx_rates[];
...
covergroup rx_cov with function sample (int unsigned rate);
coverpoint rate{
bins no_rate = {0};
bins mul_of_15 = {SOME_PRE_DEFINED_PATTERN};
}
endgroup;
....
endclass
Where SOME_PRE_DEFINED_PATTERN is an array of int from 0 to a system macro with the step of 15. I am not sure if this is the correct/best way of generating this bin. Any better suggestion?
How about writing some helper functions:
module FIFTEEN;
class rx_port;
typedef enum {IS_ZERO, IS_DIVISIBLE_BY_15, IS_NOT_DIVISIBLE_BY_15} rate_type;
function new;
rx_cov=new;
endfunction
local function rate_type covergroup_helper(input int unsigned i);
if (i==0) return IS_ZERO;
if (i%15==0) return IS_DIVISIBLE_BY_15;
return IS_NOT_DIVISIBLE_BY_15;
endfunction
function sample (input int unsigned i);
rx_cov.sample(covergroup_helper(i));
endfunction
covergroup rx_cov with function sample (rate_type rate);
coverpoint rate;
endgroup;
endclass
rx_port R = new;
initial
begin
void'(R.sample(0));
void'(R.sample(30));
void'(R.sample(31));
$display("coverage R.rx_cov.get_coverage= %f", R.rx_cov.get_coverage);
end
endmodule
https://www.edaplayground.com/x/65v7
Here I've written a function that determines whether its input is divisible by 15 or not and another function which calls that to do the sampling. You could combine those functions together, but I like the division of labour in my example.
It turns out that there is a better way:
module FIFTEEN;
class rx_port;
function new;
rx_cov=new;
endfunction
function sample (input int unsigned i);
rx_cov.sample(i);
endfunction
covergroup rx_cov with function sample (int unsigned rate);
coverpoint rate {
bins IS_ZERO = {0};
bins IS_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)==0);
bins IS_NOT_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)!=0);
}
endgroup;
endclass
rx_port R = new;
initial
begin
void'(R.sample(0));
void'(R.sample(30));
void'(R.sample(31));
$display("coverage R.rx_cov.get_coverage= %f", R.rx_cov.get_coverage);
end
endmodule
https://www.edaplayground.com/x/3T5v
You can use with to specify bins. So
bins IS_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)==0);
gives you a bin that is hit whenever the value is divisible by 15 (but not 0) and
bins IS_NOT_DIVISIBLE_BY_15 = {[1:$]} with ((item % 15)!=0);
gives you a bin that is hit whenever the value is not divisible by 15.