Question:

Does SystemVerilog support cross coverage between two different covergroups?

This was one of the question raised on verification academy.

Following is the code snippet provided by the author to clarify the question.

Answer:

SystemVerilog’s covergroup, does not support the cross coverage between two different covergroups as clarified by Dave.

No, the above code will not compile. The cross a1b1 from covergroup ab1 is used in the different covergroup ab1c1. The cross a1b1 is used in creating cross a1b1c1 in the covergroup ab1c1. Referencing is done in object oriented way ab1.a1b1. Please note the SystemVerilog covergroups are not object oriented. Lack of this support manifests as inability to reuse the cross across covergroups.

One of the key reasons for not supporting reuse of cross across covergroups is, what if the sampling events across the covergroups are different.

But what if they are same or it does not matter in specific case of reuse? In that case, why it cannot be reused?

Before we get in to that real question is, are there sufficient real life use cases for this reuse?

Couple of real life use case scenarios are following:

Solution:

Simple solution for the above problem is to duplicate the reused coverpoints and crosses in the target covergroups.

In the above example the target covergroup will have to be rewritten as following to make it work. Note that coverpoint a1, coverpoint b1 and cross a1b1 are duplicated in covergroup ab1c1 from covergroup ab1.

This is a manual effort. Whenever the reused crosses are changed it has to be manually updated in all the reused covergroups. For simple designs with fewer reused crosses it may not be big deal but for complex designs this can be highly error prone manual update process. Any compromise on functional coverage quality directly reflects on the quality of the verification.

Automation:

Our Curiosity framework supports the object-oriented covergroup. Here you can easily reuse the crosses across covergroups. We treat cross also as an object that belongs to covergroup object as a composition internally. So now crosses can be reused across the covergroups.

If the sampling events are different between the two covergroups tool will automatically warn you about it.

The tool automatically copies all the coverpoints used in reused cross and its coverpoints from source covergroup to target covergroup. As an user you don’t have to worry about manually duplicating the coverpoints.

Following code shows both the python input and generated SystemVerilog code output.


#!/home/utils/Python-2.7.5/bin/python
########################################################################################
#
#  Copyright (C) VerifSudha Technologies Pvt. Ltd.  - All Rights Reserved 2018
#  Unauthorized copying of this file, via any medium is strictly prohibited
#  Proprietary and confidential
#  Written by Anand Shirahatti,
# 
#  Title: Cross coverage between two different covergroups 
#  Description:
#  Reusing the cross across two different covergroups 
#  - Coverpoints and cross from source covergroup is automatically duplicated in
#    in the target covergroup 
#  Category: LRM 
#  Status: PUBLISH 
#
########################################################################################

from curiosity_user_common_utils import *
 
class curiosity_dut_lib(curiosity_user_lib):
 
    def set_dut_spec(self, **dut_spec_dict):
         self.dut_spec =  copy.deepcopy(dut_spec_dict)
   
         # Set default value for all entries
         self.set_default_value_wbv_entry(
            WBV_CLOCK = self.dut_spec['__DUT_CLK__'],
            WBV_RESET = self.dut_spec['__DUT_RSTN__'],
            WBV_USR_META_VAR2VAL = self.dut_spec,
            WBV_LOOP_LIST        = [''],)
 
 
    def gen_coverage(self):

        # Python covergroup object for ab1
        with add_wbv_entry(self,
             WBV_NAME             = 'ab1',
             WBV_TYPE             = 'WBV_SIGNAL_VALUE',
             WBV_FUNCTIONAL_COV   = '1',
             WBV_DESCRIPTION      = 'covergroup containing cross being reused') as wbv_entry:

             # add the coverpoints 
             wbv_entry.add_wbv_si_entry(
               SI_NAME           = 'a1',
               SIGNAL_OR_EXPR    = 'a',
               WBV_CP_COV_USER   = [{'BIN_NAME': 'a1', 'BIN_TYPE' : 'LEGAL', 'BIN_RANGE' : '[0:7]'}])

             wbv_entry.add_wbv_si_entry(
               SI_NAME           = 'b1',
               SIGNAL_OR_EXPR    = 'b',
               WBV_CP_COV_USER   = [{'BIN_NAME': 'b1', 'BIN_TYPE' : 'LEGAL', 'BIN_RANGE' : '[0:7]'}])

             # Cross is an object that can be reused
             with add_cross_entry(wbv_entry,
               CROSS_NAME = 'a1b1',
               WBV_CR_COV_USER = [{'BIN_NAME'  : 'a1b1_1', 'BIN_TYPE': 'LEGAL', 
                                   'BIN_RANGE' : 'binsof(a1.a1) & binsof(b1) intersect {4}'}],
             ) as wbv_cross_entry:
          
                # add the coverpoint or cross to be used in cross 
                wbv_cross_entry.add_coverpoint(
                     COVERPOINT_NAME = self.get_cp_name_str('ab1', 'a1'))
 
                wbv_cross_entry.add_coverpoint(
                     COVERPOINT_NAME = self.get_cp_name_str('ab1', 'b1'))     

        # Python covergroup object for ab1c1
        with add_wbv_entry(self,
             WBV_NAME           = 'ab1c1',
             WBV_TYPE           = 'WBV_SIGNAL_VALUE',
             WBV_FUNCTIONAL_COV = '1', 
             WBV_DESCRIPTION    = 'cross of cross from different covergroup') as wbv_entry:

             wbv_entry.add_wbv_si_entry(
               SI_NAME         = 'c1',
               SIGNAL_OR_EXPR  = 'c',
               WBV_CP_COV_USER = [{'BIN_NAME': 'c1', 'BIN_TYPE': 'LEGAL', 'BIN_RANGE': '[0:7]'}])         
            
             # Create cross of coverpoint and reused cross
             with add_cross_entry(wbv_entry,
                 CROSS_NAME      = 'a1b1c1',
                 WBV_CR_COV_USER = [{'BIN_NAME': 'a1b1c1', 'BIN_TYPE': 'LEGAL', 
                                     'BIN_RANGE': 'binsof(ab1.a1b1_1) && binsof(c1)'}]
              ) as wbv_cross_entry:

              wbv_cross_entry.add_coverpoint(
                 COVERPOINT_NAME = self.get_cp_name_str('ab1c1', 'c1'))
           
              # Cross from different covergroup is reused
              wbv_cross_entry.add_cross(
                 CROSS_NAME = self.get_cr_name_str('ab1', 'a1b1')) 
     


def main():
    curiosity_dut_cov_obj = curiosity_dut_lib() # Create the user lib for easing the wb_input entries creation
 
    # Setup DUT attributes  
    curiosity_dut_cov_obj.set_dut_spec(
        __DUT_CLK__            = 'dut.clk',
        __DUT_RSTN__           = '!dut.resetn',

    )  
 
    curiosity_dut_cov_obj.gen_coverage()
 
 
## Call the main ##
 
if __name__ == '__main__':
    main()
//##################################################################################################################
//
//  Copyright (C) VerifSudha Technologies Pvt. Ltd.  - All Rights Reserved 2018
//  Unauthorized copying of this file, via any medium is strictly prohibited
//  Proprietary and confidential
//  Written by curiosity ,
//
//  Generated file - Donot edit manually. It will be overwritten !
//
//  File generated with the command:
//  ./curiosity --ip_black_box ../../examples/curiosity_ex_lrm_cross_of_cross_w_bin.py --op_dir ./curiosity_op
//
//##################################################################################################################
covergroup bb_ab1;
	option.comment = "covergroup containing cross being reused";
	option.name = "ab1";
	option.per_instance = 1;

	// Cover points 
	cp_a1 : coverpoint a iff (!dut.resetn){

		  bins a1 = {[0:7]};
	}

	cp_b1 : coverpoint b iff (!dut.resetn){

		  bins b1 = {[0:7]};
	}

	// Cross coverage 
	a1b1 : cross cp_a1, cp_b1 {

		bins a1b1_1 = binsof(a1.a1) & binsof(b1) intersect {4};
	}


endgroup : bb_ab1



covergroup bb_ab1c1;
	option.comment = "cross of cross from different covergroup";
	option.name = "ab1c1";
	option.per_instance = 1;

	// Cover points 
	cp_c1 : coverpoint c iff (!dut.resetn){

		  bins c1 = {[0:7]};
	}

	cp_a1 : coverpoint a iff (!dut.resetn){

		  bins a1 = {[0:7]};
	}

	cp_b1 : coverpoint b iff (!dut.resetn){

		  bins b1 = {[0:7]};
	}

	// Cross coverage 
	a1b1c1 : cross cp_c1,a1b1 {

		bins a1b1c1 = binsof(ab1.a1b1_1) && binsof(c1);
	}

	a1b1 : cross cp_a1, cp_b1 {

		bins a1b1_1 = binsof(a1.a1) & binsof(b1) intersect {4};
	}


endgroup : bb_ab1c1