mciepluc / cocotb-coverage

Functional Coverage and Constrained Randomization Extensions for Cocotb
BSD 2-Clause "Simplified" License
100 stars 15 forks source link

What is the proper way to perform list randomization? #87

Open KasperHesse opened 9 months ago

KasperHesse commented 9 months ago

As stated: I want to randomize the contents of a list, applying constraints to each element of the list. The length of the list is not known ahead of time, so I need to pass that as an argument.

Let's say, as an example, that all list elements are in range(10), and that an element's value should not equal adjacent elements in the list. My attempt at doing this would look as follows

class CCList(Randomized):
  def __init__(self, N):
    super().__init__()
    self.N = N
    self.list = [0 for _ in range(self.N)]
    self.add_rand("list", [list(range(10)) for _ in range(self.N)])

    def con_list(list):
      r = True
      for i in range(self.N-1):
        r &= (list[i] != list[i+1])
      return r

    self.add_constraint(con_list)

  def __str__(self):
    r = ""
    for i in range(self.N):
      r += str(self.list[i]) + " "
    return r

ccl = CCList(5)
print(ccl)
ccl.randomize()
print(ccl)

Running the above returns 0 1 2 3 4. However, at further investigation, I've found that the value passed to con_list in the list argument is the domain for the given entry of CCList.list. As such, the constraints don't actually seem to affect the relationship between the values in the list, which I what I want.

What is the proper way to do this with cocotb-coverage?

mciepluc commented 9 months ago

HI @KasperHesse I am not sure if this construct would be supported by the constraint solver. I think you should not use iterable objects as a random variables. For doing what you expect, you could use pre/post_randomize() functions. https://cocotb-coverage.readthedocs.io/en/latest/tutorials.html#randomization-order-and-performance-issues