Skip to content

Array subscripting in coverpoints broken with with_sample() (arr[0], arr[idx]) #259

@BanuAdrian

Description

@BanuAdrian

Description

When using with_sample() with vsc.list_t() arrays and creating coverpoints on array elements (either with constant index arr[0] or variable index arr[idx]), PyVSC fails with errors or produces incorrect coverage results.

Minimal Reproducible Example

import vsc
from vsc import CoverageRegistry

CoverageRegistry.clear()

print("=" * 60)
print("TEST: All array subscripting scenarios")
print("=" * 60)

# Test 1: Array with constant index
@vsc.covergroup
class test1_cg():
  def __init__(self):
    self.with_sample(dict(
      arr = vsc.list_t(vsc.uint8_t(), sz=3)
    ))
    self.arr_0_cp = vsc.coverpoint(self.arr[0], bins={
        "low": vsc.bin([0, 50]),
        "high": vsc.bin([51, 255])
    })

# Test 2: Array with variable index
@vsc.covergroup
class test2_cg():
  def __init__(self):
    self.with_sample(dict(
      arr = vsc.list_t(vsc.uint8_t(), sz=3),
      idx = vsc.uint8_t()
    ))
    self.arr_idx_cp = vsc.coverpoint(self.arr[self.idx], bins={
        "low": vsc.bin([0, 50]),
        "high": vsc.bin([51, 255])
    })

print("\n--- Test 1: Constant index arr[0] ---")
try:
    cg1 = test1_cg()
    
    arr = vsc.list_t(vsc.uint8_t(), sz=3)
    arr[0] = 10   # low
    cg1.sample(arr)
    
    arr[0] = 100  # high
    cg1.sample(arr)
    
    arr[0] = 200  # high
    cg1.sample(arr)
    
    print("Expected: low=1, high=2")
    vsc.report_coverage(details=True)
    print("PASS")
except Exception as e:
    print(f"FAIL: {e}")

CoverageRegistry.clear()

print("\n--- Test 2: Variable index arr[idx] ---")
try:
    cg2 = test2_cg()
    
    arr = vsc.list_t(vsc.uint8_t(), sz=3)
    arr[0] = 10   # low
    arr[1] = 100  # high
    arr[2] = 200  # high
    
    cg2.sample(arr, 0)  # arr[0]=10 -> low
    cg2.sample(arr, 1)  # arr[1]=100 -> high
    cg2.sample(arr, 2)  # arr[2]=200 -> high
    
    print("Expected: low=1, high=2")
    vsc.report_coverage(details=True)
    print("PASS")
except Exception as e:
    print(f"FAIL: {e}")

Expected Behavior

Both tests should produce correct coverage:

  • Test 1: low: 1, high: 2 (sampled values: 10, 100, 200)
  • Test 2: low: 1, high: 2 (arr[0]=10, arr[1]=100, arr[2]=200)

Actual Behavior

Bug 1: TypeError: 'ValueScalar' object is not callable

--- Test 1: Constant index arr[0] ---
FAIL: 'ValueScalar' object is not callable

--- Test 2: Variable index arr[idx] ---
FAIL: 'ValueScalar' object is not callable

Cause: In expr_array_subscript_model.py line 63, .val() is called as a method, but val is a property.

Possible Fix in vsc/model/expr_array_subscript_model.py:

def val(self):
    index = int(self.rhs.val())
    if isinstance(self.lhs, ExprFieldRefModel):
        # return self.lhs.fm.field_l[index].val()  # BUG: val is a property, not a method
        return self.lhs.fm.field_l[index].val      # FIX
    else:
        raise NotImplementedError("Cannot subscript an lvalue of type " + str(type(self.lhs)))

Bug 2: Incorrect coverage values (all samples go to low bin)

After fixing Bug 1 locally, coverage is still incorrect:

--- Test 1: Constant index arr[0] ---
Expected: low=1, high=2
    Bins:
        low : 3
        high : 0

Cause: In coverage.py, the sample() method replaces the entire array model using set_field(), but the coverpoint still holds a reference to the old array model with uninitialized values (0).

Possible Fix in vsc/coverage.py, method sample():

Add import at top:

from vsc.model.field_array_model import FieldArrayModel

Replace:

if isinstance(ex_f, FieldCompositeModel):
    model.set_field(i, args[i].get_model())

With:

if isinstance(ex_f, FieldArrayModel):
    # Copy values element by element to preserve references
    src_model = args[i].get_model()
    for j in range(len(ex_f.field_l)):
        ex_f.field_l[j].set_val(src_model.field_l[j].val.val)
elif isinstance(ex_f, FieldCompositeModel):
    model.set_field(i, args[i].get_model())

After Both Fixes

--- Test 1: Constant index arr[0] ---
Expected: low=1, high=2
    Bins:
        low : 1
        high : 2
PASS

--- Test 2: Variable index arr[idx] ---
Expected: low=1, high=2
    Bins:
        low : 1
        high : 2
PASS

Impact

  • Array subscripting in coverpoints with with_sample() is completely broken
  • Users cannot create coverage for array elements
  • Both constant (arr[0]) and variable (arr[idx]) index access are affected

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions