mciepluc / cocotb-coverage

Functional Coverage and Constrained Randomization Extensions for Cocotb
BSD 2-Clause "Simplified" License
100 stars 15 forks source link

Coverage cross from two separate coverage_section's? #50

Closed sjalloq closed 2 years ago

sjalloq commented 3 years ago

Hi,

just starting to use the coverage module and have a question regarding whether it's possible to cross coverpoints that aren't sampled together.

Imagine I have a BusTransaction that I'm sampling and I've got {READ,WRITE} bins. I also have some clock config that I'm sampling where I might have bins for FREQ and CLKDIVRATIO, for example. How would I go about creating crosses for these two coverpoints?

I guess in the example I've given I've got one dynamic transaction and one that is static. I could work around this by creating a specific coverage sampling method that was passed in the bus transaction, then generated local static attributes for the frequency and clock ratio fields. I'd still need a single coverage_section though.

I'm assuming that if you've got two separate transactions that are generated independently, there's no way to sample them together? How is this done in the SV world? It's been a while since I looked at how it's done.

mciepluc commented 3 years ago

Sampling is a critical part of the coverage. Coverage sampling must be synchronized, because you may imagine hundreds of cases where something may go wrong (races etc.). There is no option to de-synchronize coverage cross here or anywhere else according to my knowledge. Practically, the problem similar to described by you is being resolved by assigning the same coverage primitives to multiple sampling events.


cp1 = CoverPoint(...)
cp2 = CoverPoint(...)
xc = CoverCross(...)

s1 = coverage_section(
  CoverPoint(...)
  CoverPoint(...)
  CoverCross(...)
)

...
@cp1
@s1
def sampling1():
   ...

@cp1
@cp2
@xc
def sampling2():
   ...
sjalloq commented 3 years ago

But in your example, there's no way to create a cross between s1.coverpoint and cp1? You're just sampling them at the same time when sampling1() is called?

To fix that I'd have to create a combined sampling method like:

cp_bus = CoverPoint(...)
cp_clock = CoverPoint(...)
xc = CoverCross( items = [ cp_bus, cp_clock ] )

def some_method_that_gets_a_bus_transaction(bus_trxn):
    # Create a transaction that contains the current clock config
    clk_trxn = ClockTransaction( clk_freq=current_clock_freq, clk_div=current_clk_div )

    # Sample the events
    sample_two_independent_covergroups(bus_trxn, clk_trxn)

@xc
def sample_two_independent_covergroups( bus_trxn, clk_trxn ):
    pass
mciepluc commented 3 years ago

What you suggest is correct. I suggested that a single coverpoint may be sampled at multiple calls - in that case different crosses may (re)use it.