Search form

Main menu

My Account Menu

Ask a Question

Reinitializing randc

Full Access
1 post


I was wondering if there is a way to reinitialize a randc variable. I am trying to set several registers, but need to make sure they can be set in arbitrary order. My code looks something like this:

typedef enum bit[N:0] { REG1, REG2, REG3, REG4, ... } reg_order_e;
local randc reg_order_e reg_order;

function void set_regs();
    repeat( reg_order.num() ) begin
        case( reg_order )
            REG1: set_reg1();
            REG2: set_reg2();
            REG3: set_reg3();
            REG4: set_reg4();
        assert(randomize( reg_order ));
endfunction : set_regs

Alternatively, can a randc be declared within a function?






Forum Access
17 posts

Yes, of course.




Can you elaborate? Randc cannot be declared in a function. Is there any version of std::randomize that will guarantee a variable is randomized in a cyclic way?

Forum Moderator
1894 posts

You are actually calling std::randomize() and the rand or randc modifier is ignored. You could put reg_order inside a separate class object and randomize it.

A simpler thing to do is to create an array of indexes and shuffle the array.

[code]reg_order_e reg_order[$] = { REG1, REG2, REG3, REG4, ... } ;
for (int i=0;i




Thanks Dave. I'll look into that. Why is calling randomize from within a function calling std::randomize? I assumed it was calling this.randomize() on reg_order, keeping any modifiers and constraints, but only changing the values specified in the argument. Will all calls to randomize within a function call std::randomize?

Yes, you are correct; it is calling this.randomize(). I missed the fact that your example must have been declared inside a class that was not shown.

Your original code should work if you put the call to randomize before the case statement. But I'm not sure I understand what you mean by "Re-initializing" in the title of your post.

I should have given more example code. Here is a simplified example of what's going on:

class A;
    rand int foo; rand int bar; //etc
    local randc reg_order_e reg_order;
    task do_some_work();
        //do some work involving foo, bar
        repeat( reg_order.num ) begin
            case( reg_order )
                REG1: set_reg1();
                REG2: set_reg2();
    endtask : do_some_work
endclass : A
class B;
    rand A my_obj;
    task foo();
        my_obj = new();
        assert( my_obj.randomize() );
        //do some other stuff here, maybe change my_obj's state
        assert( my_obj.randomize() );
    endtask : foo
endclass : B

There are other random members in class A. I need to create it, randomize the other members (and randomize this order member in the process), and have it do some work, which involves setting the registers. At some point later, it gets re-randomized and then does more work, setting the registers again. It should not be the responsibility of the class B to manage the randc, and in fact B does not even know about A's reg_order enum, as it is declared as a local. Hopefully this gives a better picture of the problem, and maybe some potential solutions.

OK, that explains it much better. Basically, you do not want the my_obj.randomize() to affect the local variables in class A. Then do not declare those variables as rand or randc and use my earlier suggestion of creating a separate class object to randomize or array that you shuffle from within class A.

Ok, that's what I will do. It does seem like a deficiency in the language that I cannot reset the internal state of a randc. Thanks for the assistance.

FYI, each random variable cannot have its own internal random state, otherwise you would not be able to have constraints involving more than one random variable and get proper distribution of results. You need to look at the solution space as sets of all random numbers in the object that meet the constraints and each call to randomize picks one of those sets.