Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/vsc/model/rangelist_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,17 @@ def intersect(self, other):
if len(self.range_l) == 0 or len(other.range_l) == 0:
return

rng_i=0
while rng_i < len(self.range_l):
for r in other.range_l:
# Apply each exclusion to every surviving range. _intersect can
# remove the current range and rewind the index for the next one.
for r in other.range_l:
rng_i=0
while rng_i < len(self.range_l):
rng_i = self._intersect(
self.range_l,
rng_i,
self.range_l[rng_i],
r)
rng_i += 1
rng_i += 1

def _intersect(self,
ranges,
Expand Down
48 changes: 48 additions & 0 deletions ve/unit/test_coverage_igore_bins.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,54 @@
#from coverage import covergroup

class TestCoverageIgnoreBins(VscTestCase):

def test_ignore_fully_excluded_bin(self):
self._check_fully_excluded_bin("ignore_bins")

def test_illegal_fully_excluded_bin(self):
self._check_fully_excluded_bin("illegal_bins")

def _check_fully_excluded_bin(self, exclusion_kind):
import vsc

@vsc.covergroup
class cg_t(object):
def __init__(self):
self.with_sample(dict(a=vsc.uint8_t()))
exclusions = dict(zero=vsc.bin(0), one=vsc.bin(1))
self.cp = vsc.coverpoint(self.a,
bins=dict(
min=vsc.bin(0),
mid=vsc.bin([1, 254]),
max=vsc.bin(255)),
**{exclusion_kind: exclusions})

cg = cg_t()
cp = cg.cp.get_model()
self.assertEqual(cp.get_n_bins(), 2)
self.assertEqual(
[cp.get_bin_name(i) for i in range(cp.get_n_bins())],
["mid", "max"])

# Excluded values must not hit the surviving normal bins.
cg.sample(0)
cg.sample(1)
self.assertEqual([cp.get_bin_hits(i) for i in range(2)], [0, 0])
if exclusion_kind == "ignore_bins":
self.assertEqual(cp.get_n_ignore_bins(), 2)
self.assertEqual(
[cp.get_ignore_bin_hits(i) for i in range(2)], [1, 1])
else:
self.assertEqual(cp.get_n_illegal_bins(), 2)
self.assertEqual(
[cp.get_illegal_bin_hits(i) for i in range(2)], [1, 1])

# The partially trimmed bin and the unaffected bin still sample.
cg.sample(2)
cg.sample(254)
cg.sample(255)
self.assertEqual([cp.get_bin_hits(i) for i in range(2)], [2, 1])
self.assertEqual(cp.get_inst_coverage(), 100.0)

def test_smoke(self):
import vsc
Expand Down
35 changes: 35 additions & 0 deletions ve/unit/test_rangelist_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from unittest import TestCase

from vsc.model.rangelist_model import RangelistModel


class TestRangelistModel(TestCase):

def test_intersect_exclusions(self):
cases = [
# Removing a range must not leave an invalid index for the
# next exclusion, including when no ranges remain.
([0], [0, 1], []),
([0, 1], [0, 1], []),
([0, 2, 4], [2, 4], [[0, 0]]),
([0, 1, 2], [0, 1], [[2, 2]]),
# Splits and trims must still apply every exclusion to all
# surviving ranges, regardless of exclusion order.
([[0, 10]], [5, [0, 4], [6, 8]], [[9, 10]]),
([[0, 10]], [[6, 8], [0, 4], 5], [[9, 10]]),
([[0, 10]], [[2, 4], [6, 8]], [[0, 1], [5, 5], [9, 10]]),
([[0, 2], [4, 6]], [[1, 5]], [[0, 0], [6, 6]]),
([], [0, 1], []),
([[0, 2]], [], [[0, 2]]),
]

for ranges, exclusions, expected in cases:
with self.subTest(ranges=ranges, exclusions=exclusions):
model = RangelistModel(ranges)
other = RangelistModel(exclusions)
original_exclusions = other.clone()

model.intersect(other)

self.assertEqual(model.range_l, expected)
self.assertTrue(other.equals(original_exclusions))
Loading