Coverage Confusion

Hello,

I am new to UVM, I thought i’d get started with a simple RAM design to get familiar with the UVM Methodology. My RAM has 512 address spaces. I am generating a sequences that consists of 5 writes and 5 reads. Let’s assume I write the following addresses: 0,2,4,5,6 and I read the following addresses: 2,5,9,10,23.

I have a cover group with no bins. I understand this means implicit bins are created for each one of the address space. If that is the case, my “.get_coverage” method should return a coverage value: (1/512)*8 * 100, which equals to a coverage percent:1.56% (1.56% of the address space), instead, I am getting a constant coverage of 4.25%.

Can any one explain whats happening?

Thanks,
Curiosity

In reply to verify_mars:

Are you calling get_coverage at the covergroup level or at some module instance level?
Is your covergroup declared/instantiated inside the RAM module / TB ?
Did you double check if you have any other cover groups defined apart from the empty covergroup (with no coverpoints/bins) you mentioned?
If you can post the complete code here, it’d help to analyze better.

On the other hand, you can try generating the complete coverage report from the tool to understand why the tool has reported 4.25% as the coverage?
Coverage report should have details of the covergroups, coverpoints etc.

In reply to S.P.Rajkumar.V:

On the other hand, you can try generating the complete coverage report from the tool to understand why the tool has reported 4.25% as the coverage?Coverage report should have details of the covergroups, coverpoints etc

Thanks, that’s wonderful, how do I do that?

If you can post the complete code here, it’d help to analyze better

Here is my coverage class:
####################################################################################################################
class ram_coverage_collector extends uvm_subscriber #(write_transaction);
`uvm_component_utils(ram_coverage_collector);
uvm_analysis_imp #(write_transaction,ram_coverage_collector) port_ramcc_dut_in;
write_transaction cc_write_tx;

covergroup ram_dut_inputs;
	cg_address: coverpoint cc_write_tx.addr;		
endgroup

function new(string name, uvm_component parent);
	super.new(name,parent);
	ram_dut_inputs = new();
endfunction

function void write(write_transaction t);
	cc_write_tx = t;
	ram_dut_inputs.sample();
endfunction

function void build_phase(uvm_phase phase);
	port_ramcc_dut_in = new("port_ramcc_dut_in", this);
endfunction

function void report_phase(uvm_phase phase);
	`uvm_info("COVERAGE",$sformatf("Coverage: %10.10f",this.ram_dut_inputs.get_coverage()),UVM_NONE);
endfunction

endclass
####################################################################################################################

Thanks,
Curiosity

In reply to verify_mars:

I am using modelsim

In reply to verify_mars:

Hi,

If you not defined any bins explicitly and you not used auto_bin_max option in covergroup , The Default bins created will be 64. i.e each bin size will be RAM address space(512) divided by 64.
512/64=8.

Any address value between 0 to 7 will take as bin1, any address value between 8-15 will take as bin2, bin3(16-23) to bin64(504-511) follow the same pattern.

Below is the bin details.
bin1=0-7—>(0,2,4,5,6)–>Pass
bin2=8-15—>(9,10)–>Pass
bin3=16-23–>(23)–>Pass
bin4=24-31—>((No Addresses are exercised)–>Fail


bin64=504-511—>((No Addresses are exercised)–>Fail

bin1,bin2,bin3 will pass.
bin4 to bin64 will fail.(No Addresses are exercised).

You have exercised 0,2,4,5,6,9,10,23. So you have covered 3 bins.
Coverage =(1/64)*3(No of bins hit)*100=4.68%.
You should get 4.68% coverage, But I’m not sure why you are getting 4.25%.

If you need bins for each address then use auto_bin_max option in cover group.
The cover group option auto_bin_max specifies the maximum number of bins to create, with a default of 64 bins.

covergroup ram_dut_inputs;
cg_address: coverpoint cc_write_tx.addr
{ option.auto_bin_max = 512 ; }
endgroup

Best Regards,
Manjunatha HM

The most likely reason for this discrepancy is that the number of bins created is 64, the default value for auto_bins_max, and not 512. This means that each bin represents 8 addresses.

The motivation behind covergroups is to collapse exhaustive testing into meaningful bins of interest. If you need to check that every address in an address range is covered, it would be more efficient to create an array of bits that is set when accessing each address, then array.and() would be 1 if you wrote to all addresses.

Otherwise you can set auto_bin_max to 512.

In reply to manjunathahm:

Manjunatha the “option.auto_bin_max = 512” worked! :D :D Thank you. This forum is fantastic :D

In reply to dave_59:

dave_59 thanks. A few more questions aimed towards understanding the underlying principle.

it would be to create an array of bits that is set when accessing each address

What is the general principle behind deciding what is efficient and what is not efficient? and how do I measure this efficiency? is it based on the number of data points sampled?

Thank you

In reply to verify_mars:

More questions aimed towards understanding the underlying principle, so that I can change the way I think while designing the verification environment

  1. Why would it be more efficient?
  2. How can I measure this efficiency?

In reply to verify_mars:

You need to experiment to measure the efficiency as everybody has very different environments. You will need to compare the CPU time and memory used between the two different styles.

Each bin constructed by a covergroup is an counter, plus some overhead associated with the covergroup. Compare that with a single bit per address.

In reply to dave_59:

ah okay. Thanks