Overriding constraints

Hi,
I’m trying to override a constraint . I’ve tried various ways, but nothing seems to work. This is what I intend to do:

In an object class, I have these three random variables and their weights. In the test class, I want to set all the three to the same value.

class abc_object extends uvm_oject;
  rand bit a1;
  rand bit a2;
  rand bit a3;

 constraint set_weigths_a {
   a1 dist {
    1'b0 :/1,
    1'b1 :/999
  };
   a2 dist {
    1'b0 :/1,
    1'b1 :/999
  };
   a3 dist {
    1'b0 :/1,
    1'b1 :/999
  };
}
The abc_env creates the object for abc_object;

class abc_test extends uvm_test;
  abc_env a_env;
  
  constraint change_constraint_for_a {
    a_env.a_obj.a2 == a_env.a_obj.a1;
    a_env.a_obj.a2 == a_env.a_obj.a1;
  }

endclass

The above doesnt work. As in, no compilation error , just that the test still generates a different vale for a1,a2 and a3.
I tried setting the rand mode to 0 to these three variables from test class, and creating a new random variable and assigning the value of this new random variable to a1,a2 and a3 from test class: This also doesnt work.

I tried solve_before for a1 before assigning a2 and a3 in the constraint in test class, that also doesnt work.

I tried adding a post_randomize function in test class and including this assignment in post_randomize, the post_randomize does not even get called.

Can you please help me at the earliest.

Thanks
Ramya

In reply to Ramyas:
You didn’t show your abc_env class or how it gets randomized, but I’ll assume it is

class abc_env extends uvm_env;

  abc_object a_obj;

  function void build_phase(uvm_phase phase);
    a_obj = abc_object::type_id::create();
    if (!a_obj.randomize()) `uvm_error(<some_error_message>)
    ...
  endfunction
endclass


Adding a constraint to your test class has no effect because that’s not the class object being randomized. It could work if declared everything as
rand
and called randomize on the test_object.

What you probably want to do is extend the abc_object with the new constraint and use the factory and have the test override the creation of the abc_object with the extended class.

class abc_extended extends abc_object;
  constraint change_constraint_for_a {
    a1 == a2; a2 == a3;
  }
endclass

class abc_test extends uvm_test;
  abc_env a_env;
 
  function void build_phase(uvm_phase phase);
     abc_object::type_id::set_type_override(abc_extended::get_type());
     a_env = abc_env::type_id::create("a_env",this);
  endfunciton 
endclass

Hi Dave

Why do we need to extend base class ?

Does in line constraint is not enough ?

abc_object.randomize () with {a1 == a2,a2 == a3;};

In reply to RonakShah:
Unless the call to
randomize()
is in the top level test, you need to extend some class and override the method that calls
randomize()
in order to add the in-line constraint…

I do not like using in-line constraints because it is not OOP friendly. To add a set of in-line constraints, you have to modify the procedural flow of code, which usually means duplicating a lot of procedural code. It’s much better to keep the constraints separate for the procedural flow and keep the constraints as part of the object being randomized.

In reply to dave_59:

Another way to overreide a constraint is to define in your extended class another constraint which has to have the same name of the constarint you want to override.

In reply to dave_59:

In reply to RonakShah:
Unless the call to
randomize()
is in the top level test, you need to extend some class and override the method that calls
randomize()
in order to add the in-line constraint…
I do not like using in-line constraints because it is not OOP friendly. To add a set of in-line constraints, you have to modify the procedural flow of code, which usually means duplicating a lot of procedural code. It’s much better to keep the constraints separate for the procedural flow and keep the constraints as part of the object being randomized.

Hi dave,

Yes … Nice concept…

But one more thing, We can also achieve the solution in the following way:

if i decalare all the variable in base class (here abc_object ) as static rand , What i think is, all the instance of that class have the same value, once got randomized by calling function “a_obj.randomize())” say inside env class i.e., “abc_env”.
so that when the top class have another istance or access the variable with some other instance have the same value for the “static” variable of the base class(abc_object).

sample code ::

class abc_object extends uvm_oject;
static rand bit a1; // Here variable are static in nature so any inatsnce of the
// above class have same value. And it can be use in another
// class like base_test.
static rand bit a2;
static rand bit a3;



endclass

The abc_env creates the object for abc_object;

class abc_test extends uvm_test;
abc_env a_env;

constraint change_constraint_for_a {
a_env.a_obj.a2 == a_env.a_obj.a1;
a_env.a_obj.a2 == a_env.a_obj.a1;
}

endclass

p.s : Please Dave correct me if i am wrong.

Thanks
Anubhaw

In reply to anu.anu:
Why don’t you try it and see if it works for you?

In reply to anu.anu:
It doesn’t work.