PyVSC Data Types

Generating good random data requires characterizing the data to be randomized. PyVSC provides specific data types to characterize the size and signedness of fields to be used in constraints.

First, a quick example

@vsc.randobj
class my_s(object):

    def __init__(self):
        self.a = vsc.rand_bit_t(8)
        self.b = vsc.rand_bit_t(8)
        self.c = vsc.rand_bit_t(8)
        self.d = vsc.rand_bit_t(8)

    @vsc.constraint
    def ab_c(self):

        self.a in vsc.rangelist(1, 2, 4, 8)

        self.c != 0
        self.d != 0

        self.c < self.d
        self.b in vsc.rangelist(vsc.rng(self.c,self.d))

The example above shows using the rand_bit_t type to specify class attributes that are random, unsigned (bit), and 8-bits wide.

In much the same way that C/C++ and SystemVerilog provide more than one way to capture types that are equivalent, PyVSC provides several ways of capturing the same type information.

Scalar Standard-Width Attributes

PyVSC provides a set of standard-width data types, modeled after the types defined in stdint.h. Both random and non-random variants of these attribute classes are provided.

Width

Signed

Random

Non-Random

8

Y

rand_int8_t

int8_t

8

N

rand_uint8_t

uint8_t

16

Y

rand_int16_t

int16_t

16

N

rand_uint16_t

uint16_t

32

Y

rand_int32_t

int32_t

32

N

rand_uint32_t

uint32_t

64

Y

rand_int64_t

int64_t

64

N

rand_uint64_t

uint64_t

The constructor for the classes above accepts the initial value for the class attribute. By default, the initial value will be 0.

@vsc.randobj
class my_s(object):

    def __init__(self):
        self.a = vsc.rand_uint8_t()
        self.b = vsc.uint16_t(2)
        self.c = vsc.rand_int64_t()

In the example above, a random unsigned 8-bit field, a non-random unsigned 16-bit field, and a random signed 64-bit field is created.

Scalar Arbitrary-Width Attributes

PyVSC provides four classes for constructing arbitrary-width scalar class attributes. The first parameter of the class constructor is the width. The second parameter specifies the initial value for the attribute.

Signed

Random

Non-Random

Y

rand_int_t

int_t

N

rand_bit_t

bit_t

@vsc.randobj
class my_s(object):

    def __init__(self):
        self.a = vsc.rand_int_t(27)
        self.b = vsc.rand_bit_t(12)

The example above creates a random signed 27-bit attribute and a random unsigned 12-bit attribute.

Enum-type Attributes

PyVSC supports Python Enum and IntEnum enumerated types. Attributes are declared using the enum_t and rand_enum_t classes.

class my_e(Enum):
  A = auto()
  B = auto()

@vsc.randobj
class my_s(object):

    def __init__(self):
        self.a = vsc.rand_enum_t(my_e)
        self.b = vsc.enum_t(my_e)

Class-type Attributes

Random and non-random class attributes can be created using classes decorated with randobj. Non-random class attributes can optionally be decorated with attr.

@vsc.randobj
class my_sub_s(object):
    def __init__(self):
        self.a = vsc.rand_uint8_t()
        self.b = vsc.rand_uint8_t()

@vsc.randobj
class my_s(object):

    def __init__(self):
        self.i1 = vsc.rand_attr(my_sub_s())
        self.i2 = vsc.attr(my_sub_s())

Accessing Attribute Values

The value of scalar attributes can be accessed in two ways. All PyVSC scalar attribute types provide a get_val() and set_val() method. These methods can be called to get or set the current value.

PyVSC also provides operator overloading for randobj-decorated classes that allows the value of class attributes to be accessed directly.

List-type Attributes

Random and non-random class attributes of list type can be created using the list_t class. The size of the list can be later changed by appending or removing elements, or clearing the list. Randomizing the array will not change its size.

@vsc.randobj
class my_item_c(object):
    def __init__(self):
      self.my_l = vsc.rand_list_t(vsc.uint8_t(), 4)

The randsz_list_t class creates a list whose size will be randomized when the list is randomized. A list with a randomized size must have a top-level constraint bounding the list size.

@vsc.randobj
class my_item_c(object):
    def __init__(self):
      self.my_l = vsc.randsz_list_t(vsc.uint8_t())

    @vsc.constraint
    def my_l_c(self):
        self.my_l.size in vsc.rangelist((1,10))

The list_t class must be used for any list that will be used in constraints.

@vsc.randobj
class my_item_c(object):
    def __init__(self):
      self.a = vsc.rand_uint8_t()
      self.my_l = vsc.list_t(vsc.uint8_t(), 4)

      for i in range(10):
          self.my_l.append(i)

    @vsc.constraint
    def a_c(self):
      self.a in self.my_l

it = my_item_c()
it.my_l.append(20)

with it.randomize_with():
  it.a == 20