Alok
Alok

Reputation: 31

How to randomize a variable in system verilog only if it's not having a default value

I want to have a class where I want to put all of the rand variables with some default value which should be only randomized if they are assigned non-default value from their handle

Example

typedef enum {
  NORTH = 0,
  SOUTH = 1,
  EAST  = 2,
  WEST  = 3,
  DEFAULT_DIR = 4
} direction_t;

class dir_class;
  
  rand direction_t dir;
  
 // I want something like
 // rand direction_t dir = DEFAULT_DIR;

  constraint dir_c
  { 
    if(dir == DEFAULT_DIR) 
    { 
      dir inside {NORTH,SOUTH,WEST,EAST};
    }
  }

endclass: dir_class

Now what I want is when I take handle of this class I might want to assign some non default value (which could be done with inline constraint) but I don't want to use that because I might end up having 100s of such variable.

So what I need is that initially all of the variables should be having some default enum value like DEFAULT_RAND and only be randomized if they hold this default value otherwise keep the value that is passed via handle

Upvotes: 1

Views: 483

Answers (2)

dave_59
dave_59

Reputation: 42738

A better way to write this is using a const cast, which gives you the state of a random variable before calling randomize().

typedef enum {
  NORTH = 0,
  SOUTH = 1,
  EAST  = 2,
  WEST  = 3,
  DEFAULT_DIR = 4
} direction_t;

class dir_class;
  
  rand direction_t dir = DEFAULT_DIR;

  constraint dir_c
  { 
    if(const'(dir) != DEFAULT_DIR) 
      dir == const'(dir);
    else
      dir != DEFAULT_DIR;
   }
endclass: dir_class
    
module dir_module;
  
  dir_class check;
  
  initial begin
    check = new();
    
    $display("DIR:%0s",check.dir.name);
    
    assert(check.randomize());
    
    $display("DIR:%0s",check.dir.name);
    
    check.dir = EAST;
    
    $display("DIR:%0s",check.dir.name);
    
    assert(check.randomize());
    
    $display("DIR:%0s",check.dir.name);    
  end
   
endmodule: dir_module

Not all tools support this cast in a constraint yet, but you can easily get the same effect using pre_randomize() and another state variable.

class dir_class;
  
  rand direction_t dir = DEFAULT_DIR;
  direction_t p_dir = DEFAULT_DIR;
  constraint dir_c
  { 
    if(p_dir != DEFAULT_DIR) 
      dir == p_dir;
    else
      dir != DEFAULT_DIR;
  }
  function void pre_randomize;
    p_dir = dir;
  endfunction
endclass: dir_class

Upvotes: 1

Alok
Alok

Reputation: 31

This seems to work

typedef enum {
  NORTH = 0,
  SOUTH = 1,
  EAST  = 2,
  WEST  = 3,
  DEFAULT_DIR = 4
} direction_t;

class dir_class;
  
  rand direction_t dir;

  constraint dir_c
  { 
    if(dir == DEFAULT_DIR) 
    { 
      dir inside {NORTH,SOUTH,WEST,EAST};
    }
  }

      function new();

      endfunction
     
endclass: dir_class
    
class checker_class;
  
  rand dir_class direct;
  
  function new();
    direct = new();
  endfunction
  
  function void pre_randomzie();
    if(direct.dir != DEFAULT_DIR) begin
      direct.dir_c.constraint_mode(0);
    end
  endfunction 
  
endclass
  
    
module dir_module;
  
  checker_class check;
  
  initial begin
    check = new();
    check.direct.dir = DEFAULT_DIR;
    
    $display("DIR:%0s",check.direct.dir);
    
    check.randomize();
    
    $display("DIR:%0s",check.direct.dir);
    
    check.direct.dir = EAST;
    
    $display("DIR:%0s",check.direct.dir);
    
    check.randomize();
    
    $display("DIR:%0s",check.direct.dir);    
  end
   
endmodule: dir_module

OTUPUT

CPU time: .433 seconds to compile + .398 seconds to elab + .380 seconds to link
Chronologic VCS simulator copyright 1991-2023
Contains Synopsys proprietary information.
Compiler version U-2023.03-SP2_Full64; Runtime version U-2023.03-SP2_Full64;  May  5 01:40 2024
DIR:DEFAULT_DIR
DIR:SOUTH
DIR:EAST
DIR:EAST
           V C S   S i m u l a t i o n   R e p o r t 
Time: 0 ns
CPU Time:      0.440 seconds;       Data structure size:   0.0Mb

Upvotes: -1

Related Questions