A randomization question between a varible and a value

Hi there,

Could anyone explain what’s the difference between the following two? Basically why a variable of max_size can’t be used instead of an absolute value of 5’h1f? The issue was the xyz in 1) could be still 5’h1f, the intention was to make the random generated data of xyz not equal to its max_size (5’h1f). Thanks!

class abc extends uvm_component;
   randc bit[4:0] xyz;

  rand bit [4:0] max_size = 5'h1F;
endclass: abc

class m_seqeunce extends my_base_sequence;

 int max_size = 5'h1F; 

 abc   m_abc;

 virtual task body();
// why can't the "max_size" being used here ,instead it has to put an  absolute value of 5'h1F here?
  (m_abc.randomize() with {m_abc.xyz != max_size;}   
 endtask

endclass: m_sequence

class abc extends uvm_component;
   randc bit[4:0] xyz;

  rand bit [4:0] max_size = 5'h1F;
endclass: abc

class m_seqeunce extends my_base_sequence;

 int max_size = 5'h1F; 

 abc               m_abc;

 virtual task body();
   (m_abc.randomize() with {m_abc.xyz != 5'h1F;}
 endtask

endclass: m_sequence



The with clause to randomize() is defined to search for variable identifiers in the scope of the object being randomized first, followed by the scope containing the call to randomize(). What you want to write is:

if (!m_abc.randomize() with {xyz != local::max_size}) $error(...);

Even better would be to not use the same variable name in two different objects.

In reply to dave_59:

Thanks Dave.

Does the code of “if (!m_abc.randomize() with {xyz != local::max_size}) $error(…);” imply that I could still get a value of max_size for xyz but with an error message reported? My intention is not to let the randomization generated that value for xyz.

Alternatively, do you think the following code will work? I tried to put the following constraints in the class abc, and only do randomize() (i.e. not randomize() with) in the task body() . Thanks much!

class abc extends uvm_component;
randc bit[4:0] xyz;

rand bit [4:0] max_size = 5’h1F;

rand bit specific_mode = 1;

constraint xyz_c {
{specific_mode == 1’b1} → (xyz != max_size );

   }

endclass: abc

And then:class m_seqeunce extends my_base_sequence;

// int max_size = 5’h1F;

abc m_abc;

virtual task body();
m_abc.specifi_mode.rand_mode(0);
(m_abc.randomize();
endtask

In reply to nickbayshore:

The if (!randomize) $error; is a good habit to get into even if you don’t expect the randomization to ever fail. The LRM does not make a randomization failure an error, although some tools do allow you to change the severity.

I actually prefer to put the constraints inside the class instead using the with clause. It makes it easier to use inheritance to override the constraints.

In reply to dave_59:

Thanks Dave for your advice!

In reply to nickbayshore:

Hi Dave,

That code actually doesn’t really work, I got solver failure. Do you know why the xyz is still generated as 5’h1f? Looks like the constraint didn’t apply to the randc xyz … Thanks again!

Solver failed when solving following set of constraints
bit[4:0] xyz = 5’h1f;
rand bit[4:0] xyz_start = 5’h0; // rand_mode = OFF
rand bit[4:0] xyz_offset = 5’h1f; // rand_mode = OFF
rand bit[0:0] specific_mode = 1’h1; // rand_mode = OFF
constraint xyz_c // (from this) (constraint_mode = ON)
{
(specific_mode == 1’h1) → ((xyz >= xyz_start) && (xyz < (xyz_start + xyz_offset)));
}


class abc extends uvm_component;
randc bit[4:0] xyz;

rand bit specific_mode = 1;

rand bit [4:0] xyz_start = 5’h0;
rand bit [4:0] xyz_offset = 5’h1f;

constraint xyz_c {
{specific_mode == 1’b1} → ((xyz >= xyz_start) && (xyz <(xyz_start + xyz_offset)));

}
endclass: abc

And then:class m_seqeunce extends my_base_sequence;

// int max_size = 5’h1F;

abc m_abc;

virtual task body();
m_abc.specifi_mode.rand_mode(0);
m_abc.start_xyz.rand_mode(0);
m_abc.offset_xyz.rand_mode(0);
m_abc.randomize();
endtask

In reply to nickbayshore:

How about wrapping your code into a small self-contained testcase?

In reply to dave_59:

Hi Dave,

I can reproduce the issue in a small test case easily now. I suspect the randc xyz is actually generated already before the constraint applied. I tried to use a “solve specific_mode before xyz”, but it throws Error due to it is a type of randc, can’t be used in an expression of solve-before … Any insights? Thanks!

In reply to nickbayshore:

How about wrapping your code into a small self-contained testcase and posting it here?

In reply to dave_59:

I printed some debug messages and it’s approved that errors happens when the xyz is generated as 7 . So question is why the constraints doesn’t apply to the randc xyz ? Is it supposed to be like so for randc?

See also below:

data[ 0]: 0
data[ 1]: 5
data[ 2]: 4
data[ 3]: 1

=======================================================

Solver failed when solving following set of constraints

bit[2:0] xyz = 3’h7;
rand bit[2:0] xyz_start= 3’h0; // rand_mode = OFF
rand bit[2:0] xyz_offset = 3’h7; // rand_mode = OFF
rand bit[0:0] specific_mode = 1’h1; // rand_mode = OFF

constraint xyz_c // (from this) (constraint_mode = ON)
{
(specific_mode == 1’h1) → (xyz > xyz_start) && (xyz <(xyz_start + xyz_offset)));
}

In reply to nickbayshore:

Sorry, I don’t know how to extract it to a self-contained test case. But the corresponding code has been pretty much as above already … on top of that, just randomize this sequence and start the sequencer …

m_sequence.randomize()
m_sequence.start(sequencer)

Thanks!

In reply to nickbayshore:

I did more experiments. The only case works is #1 . i.e. put an absolute value in the constraint, it’s not even working in #2


#1:
class abc extends uvm_component;
randc bit[2:0] xyz;

rand bit specific_mode = 1;

rand bit [2:0] xyz_start = 3’h0;
rand bit [2:0] xyz_offset = 3’h7;

constraint xyz_c {
{specific_mode == 1’b1} → (xyz != 7); //only works using an absolute value here

}
endclass: abc

#2:
class abc extends uvm_component;
randc bit[2:0] xyz;

rand bit specific_mode = 1;

rand bit [2:0] xyz_start = 3’h0;
rand bit [2:0] xyz_offset = 3’h7;

constraint xyz_c {
{specific_mode == 1’b1} → (xyz != xyz_offset); //not working using varible

}
endclass: abc

The error message for #2 is as following:

Solver failed when solving following set of constraints

bit[2:0] xyz = 3’h7;
rand bit[2:0] xyz_offset = 3’h7; // rand_mode = OFF

constraint xyz_c // (from this) (constraint_mode = ON) ( … )
{
(xyz != xyz_offset);
}

=======================================================

This randomization behavior doesn’t seem to be expected. Sounds a bug to me. Can anyone have an explanation for this behavior? Much appreciated!

In reply to nickbayshore:

Another thing, from the test case extracted by the tool itself, somehow the xyz is not an randc anymore instead it’s static. I also printed the rand_mode() for xyz before each randomize, and shows rand_mode() returns 1 for xyz. I don’t know why it shows static. Isn’t this a UVM bug? Anyone could explain something here?! Thanks!

class c_8_2;
bit[2:0] xyz = 3’h7; //??? it’s changed to static, not randc
rand bit[2:0] xyz_offset = 3’h7; // rand_mode = OFF

constraint xyz_c_this    // (constraint_mode = ON) (blahblah.sv:line number)
{
   (xyz != xyz_offset);
}

endclass

program p_8_2;
c_8_2 obj;
string randState;

initial
    begin
        obj = new;
        randState = "0xzx000x1xxz1010x01zz01x0xz0x10zxzzzzzxxzzxxzzxxzzxxxzxzzxxzzxzz";
        obj.set_randstate(randState);
        obj.xyz_offset.rand_mode(0);
        obj.randomize();
    end

endprogram

In reply to nickbayshore:

The code in the box is a self-contained test case and works fine for me.

module self_contained_module;
class abc;
   
   randc bit[2:0] xyz;
   
   rand bit specific_mode = 1;
   
   rand bit [2:0] xyz_start = 3'h0;
   rand bit [2:0] xyz_offset = 3'h7;

   constraint xyz_c {
      {specific_mode == 1'b1} -> (xyz != xyz_offset); //not working using variable
      
   }
  endclass: abc
   abc h;
   initial repeat(20) begin
      h = new;
      assert(h.randomize());
      $display(h.specific_mode,,h.xyz,,h.xyz_offset);
   end
endmodule // self_contained_module

I don’t understand the error message you are getting. Why is xyz shown declared without the rand keyword? Why does is show RAND_MODE off for the variable xyz_offset. Maybe it’s because YOU ARE NOT SHOWING USE THE ACTUAL CODE YOU ARE RUNNING.

In reply to dave_59:

I think you need to take this up with your tool vendor directly where you can share your complete code. I doubt this has anything to do with the UVM, but no one could say for sure without seeing all your code.

In reply to dave_59:

Hi Dave,

To answer your questions,

  1. I don’t understand why xyz shown declared without randc keyword either, that’s my question in my last post
  2. as for why the xyz_offset shows rnad_off, as I posted my code in the early post, it’s because I have the following before calling the randomize(), you may add those to your code to have a try too. Thanks!

:class m_seqeunce extends my_base_sequence;

// int max_size = 5’h1F;

abc m_abc;

virtual task body();
m_abc.specifi_mode.rand_mode(0);
m_abc.start_xyz.rand_mode(0);
m_abc.offset_xyz.rand_mode(0);
m_abc.randomize();
endtask

BTW, which UVM version are you using? maybe there is a bug in my version (1.1)

In reply to nickbayshore:

Hi Dave, How to run your module? I would like to try out your code in my env … Thanks!

In reply to nickbayshore:

Hello Nick,

you can run Dave’s code directly using the below command.

In questasim

qverilog self_contained_module.sv

In cadence NC:

irun self_contained_module.sv

Minor update
instead of this display $display(h.specific_mode,h.xyz,h.xyz_offset);
you can print all the fields of transaction using below debug message

$display(“transaction is %p”,h);

Also using constraints would be advisable.

Thanks

In reply to Bharath_Verif:

Thanks Bharath and Dave.

I am actually using VCS, and I have reproduced the exact same issue using Dave’s self-contained module with a slight additional changes that are the same as my real test case. Here is the updated module and the reproduced problem:

module randc_test_module;
class abc;

randc bit[2:0] xyz;

rand bit specific_mode = 1;

rand bit [2:0] xyz_start = 3’h0;
rand bit [2:0] xyz_offset = 3’h7;

constraint xyz_c {
{specific_mode == 1’b1} → (xyz != xyz_offset); //not working using variable

}
endclass: abc
abc h;
initial repeat(20) begin
h = new;
h.specific_mode.rand_mode(0);
h.xyz_start.rand_mode(0);
h.xyz_offset.rand_mode(0);
assert(h.randomize());
// $display(h.specific_mode,h.xyz,h.xyz_offset);
$display(“transaction is %p”,h);
end
endmodule // randc_test_module

Error message which is the exact same problem as my real test case, where the xyz has become a static variable but a randc, and also the constraint doesn’t work anymore:
transaction is '{xyz:'h1, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h4, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h3, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h3, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h0, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}

=======================================================

Solver failed when solving following set of constraints

bit[2:0] xyz = 3’h7;
rand bit[2:0] xyz_offset = 3’h7; // rand_mode = OFF rand bit[0:0] specific_mode = 1’h1; // rand_mode = OFF

constraint xyz_c // (from this) (constraint_mode = ON) (randc_test_module.sv:11)
{
(specific_mode == 1’h1) → (xyz != xyz_offset); }

=======================================================

“randc_test_module.sv”, 22: randc_test_module.unnamed$$_2.unnamed$$_1: started at 0s failed at 0s
Offending ‘h.randomize()’

transaction is '{xyz:'h0, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h5, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h1, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h2, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h4, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h5, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h5, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h4, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h2, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h1, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h6, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h2, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h2, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h0, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}
transaction is '{xyz:'h3, specific_mode:'h1, xyz_start:'h0, xyz_offset:'h7}

In reply to nickbayshore:

If xyz is the only random variable, then it should be able to take on any value other than 'h7. This works fine in Questa, Looks a tool bug to me - you will have to contact Synopsys.