Search code examples
system-veriloguvm

Is there any method to know whether a member is declared random or not in a class in SV


// Current Class
class x;
  rand int a;
  int b; // b is nonrandom as of now

  function new();
  endfunction

  function abc;
    // if a != ref.a, where ref is reference object of class x, declared somewhere else
       a.rand_mode(0);
  endfunciton

// Future Possible Class
class x;
  rand int a;
  rand int b; // b is also a random variable now

  function new();
  endfunction

  function abc;
    // if a != ref.a, where ref is reference object of class x, declared somewhere else
       a.rand_mode(0);
    // if b != ref.b, where ref is reference object of class x, declared somewhere else
       b.rand_mode(0);
  endfunciton

So in function abc, depending upon whether a rand member value matches or doesn't match with the value of that member in reference class, that rand declared members of class x, should be active or inactive accordinly.

Purpose - I need to check if a rand variable matches with reference class value then only it should be randomized, otherwise not.

I want to generalize method abc, for all possible future variations (So I don't need to modify it, as done in the above example), and as I don't know, when a class member may become rand or nonrand member, Is there any inbuilt method to know, whether a member of a class is declared as rand or not in that class?


Solution

  • You could change your perspective on the problem slightly. Instead of trying to disable randomization for fields that are declared rand, why not say that when they get randomized, they should keep their value?

    According to this nice post, there's a new construct in SV 2012, const'(...) that would work in this case. Unfortunately I don't think many vendors support it. Your randomize() call would look like this:

    if (!rand_obj.randomize() with {
      const'(a) != ref_obj.a -> a == const'(a);
    })
      $fatal(0, "rand error");
    

    Let's dissect this code. const(a) will sample the value of a prior to doing any sort of randomization. If the value of a before randomization is not equal to the reference value, then we have the second part of the constraint that says a should keep its value. I've tried this code on two simulators but it wasn't supported by either (though it should be legal SV 2012 syntax). Maybe you're lucky enough to have a vendor that supports it.

    You can write such constraints even for state variables, as they will still hold.

    If you can't get the const syntax to work in your simulator, then the same post shows how you could work around the issue. You could store the values prior to randomization inside the object and use those in the constraint:

    class some_class;
      rand bit [2:0] a;
      bit [2:0] b;
    
      bit [2:0] pre_rand_a;
      bit [2:0] pre_rand_b;
    
      function void pre_randomize();
        pre_rand_a = a;
        pre_rand_b = b;
      endfunction
    endclass
    

    When you want to randomize, you'd add the following constraints:

    if (!rand_obj.randomize() with {
      pre_rand_a != ref_obj.a -> a == pre_rand_a;
      pre_rand_b != ref_obj.b -> b == pre_rand_b;
    })
      $fatal(0, "rand error");
    

    You can find a full example on EDAPlayground.

    You mention that your function that does randomization is defined outside of the object. Because of that, the pre_rand_* fields can't be local/protected, which isn't very nice. You should consider making the function a class member and pass the reference object to it, so that you can enforce proper encapsulation.