fvutils / pyvsc

Python packages providing a library for Verification Stimulus and Coverage
https://fvutils.github.io/pyvsc
Apache License 2.0
113 stars 26 forks source link

not_inside constraint unexpectedly reducing output set significantly #199

Closed apaiva closed 10 months ago

apaiva commented 11 months ago

Here's an example ( on version pyvsc 0.8.6.6319294550) a 'not_inside' constraint is reducing a rand enum's set down to almost nothing, where I'd expect it to only exclude the specified values. You can see in the output below that the first set of randomizations (without the not_inside constraint) give a nice distribution; however the second set 'op2' result in only 'C'.

Output

op1:L op1:M op1:I op1:B op1:M op1:C op1:M op1:D op1:J op1:L op2:C op2:C op2:C op2:C op2:C op2:C op2:C op2:C op2:C op2:C

Code Example

`import vsc from enum import IntEnum, auto

class TestIntEnum(IntEnum): A = 0 # B = 1 # C = 2 # D = 3 # E = 11 # F = 5 # G = 6 # H = 7 # I = 15 # J = 10 # K = 14 # L = 8 # M = 9 # N = 4 # O = 128 # P = 129 # Q = 0x82 # R = 0x8A # S = 0xff #

@vsc.randobj(srcinfo=False) class RandOp:

def __init__(self):
    self.r_op = vsc.rand_enum_t(TestIntEnum)

@vsc.constraint
def c_op(self):
    self.r_op.inside(vsc.rangelist(
        TestIntEnum.A,
        TestIntEnum.B,
        TestIntEnum.C,
        TestIntEnum.D,
        TestIntEnum.E,
        TestIntEnum.F,
        TestIntEnum.G,
        TestIntEnum.H,
        TestIntEnum.I,
        TestIntEnum.J,
        TestIntEnum.K,
        TestIntEnum.L,
        TestIntEnum.M ))

@vsc.randobj() class RandOp2(RandOp):

@vsc.constraint
def c_op2(self):
    self.r_op.not_inside(vsc.rangelist(
        TestIntEnum.A,
        TestIntEnum.B))

if name == 'main': for _ in range(10): rand_op = RandOp() rand_op.randomize() print(f"op1:{rand_op.r_op.name:s}")

for _ in range(10):
   rand_op = RandOp2()
   rand_op.randomize()
   print(f"op2:{rand_op.r_op.name:s}")`
mballance commented 10 months ago

Good catch on this one, @apaiva, and many thanks for the easy-to-reproduce testcase. not_inside is represented as !inside internally, and the randomization code was incorrectly treating !inside the same as inside. For now, PyVSC simply provides no special handling for !inside. This results in much better distribution than you were seeing previously. However, there is a visible 'spike' in the histogram. Let me give some thought to how to improve this. I've released 0.8.7 with the improvements. Feel free to give it a try!