PyVSC Methods

Randomization Methods

In addition to the randomize and randomize_with methods provided by the randobj class, PyVSC provides global methods for randomizing variables.

a = vsc.rand_uint8_t()
b = vsc.rand_uint8_t()

vsc.randomize(a, b)

The global randomize method randomizes the list of PyVSC variables, both scalar and composite.

a = vsc.rand_uint8_t()
b = vsc.rand_uint8_t()

for i in range(10):
    with vsc.randomize_with(a, b):
        a < b

The global randomize_with method randomizes the list of PyVSC variables, both scalar and composite, subject to the inline constraints.

Managing Random Stability

Each PyVSC rand_obj instance maintains its own random state. The random state for each rand_obj can be established explicitly by the user. If the random state has not been initialized at the time of the first call to randomize on a object, the random state will be automatically derived using the Python random package.

PyVSC uses the RandState class to store and manipulate random state. The rand_obj class provides functions for obtaining a copy of the current random state, and for setting the current random state to that of a previously-obtained random state.

The example below shows using a RandState object to produce the same sequence of random number twice.

@vsc.randobj
class item_c(object):

    def __init__(self):
        self.a = vsc.rand_uint8_t()
        self.b = vsc.rand_uint8_t()

    @vsc.constraint
    def ab_c(self):
        self.a < self.b

ci = item_c()

v1 = []
v2 = []

print("Iteration 1")
rs1 = RandState.mkFromSeed(0)
ci.set_randstate(rs1)
for _ in range(10):
    ci.randomize()
    v1.append((ci.a,ci.b))

print("Iteration 2")
ci.set_randstate(rs1)
for _ in range(10):
    ci.randomize()
    v2.append((ci.a,ci.b))

The RandSeed.mkFromSeed method is the preferred way to create a random state object from user-specified values. The mkFromSeed method accepts an integer seed and an optional string. The example below shows producing the same sequence of random values based on two independently-created random state objects.

@vsc.randobj
class item_c(object):

    def __init__(self):
        self.a = vsc.rand_uint8_t()
        self.b = vsc.rand_uint8_t()

    @vsc.constraint
    def ab_c(self):
        self.a < self.b

ci = item_c()

v1 = []
v2 = []

print("Iteration 1")
rs1 = RandState.mkFromSeed(10, "abc")
ci.set_randstate(rs1)
for _ in range(10):
    ci.randomize()
    v1.append((ci.a,ci.b))

print("Iteration 2")
rs2 = RandState.mkFromSeed(10, "abc")
ci.set_randstate(rs2)
for _ in range(10):
    ci.randomize()
    v2.append((ci.a,ci.b))

Weighted-Random Selection Methods

It is often useful to perform a weighted-random selection in procedural code. SystemVerilog provides the randcase construct for this purpose. PyVSC provides two methods for performing a weighted-random selection from a set of candidates.

distselect

The distselect method accepts a list of weights and returns the selected index.

hist = [0]*4

for i in range(100):
    idx = vsc.distselect([1, 1, 10, 10])
    hist[idx] += 1

print("hist: " + str(hist))

In the example above, the index returned will vary 0..3.

randselect

The randselect method accepts a list of weight/lambda tuples. It performs a weighted selection and calls the selected lambda. In most cases, the lambda will need to call a function to perform useful work.

hist = [0]*4

def task(idx):
    hist[idx] += 1

for i in range(100):
    vsc.randselect([
           (1, lambda: task(0)),
           (1, lambda: task(1)),
           (10, lambda: task(2)),
           (10, lambda: task(3))])
print("hist: " + str(hist))

In the example above, the lambda functions invoke the same Python method with different arguments. Different methods could be called instead.