How do I set constraints for a sequence within a sequence?

I have a set of sequences and sequences of sequences, and I would like to be able to change the constraints for my lowest level sequence from the top level sequence, without modifying the lowest level sequence.

To make this a little more concrete, here is an example. A_lseq_signal contains a A_seq_stop_signal, which itself is extended from A_seq_base which extends uvm_sequence #(A_tb_txn). wait_time is a randomizable int within A_tb_txn.

My goal is to be able to constrain wait_time from A_lseq_signal. This code is the closest I’ve gotten and it’s giving me a null access error. You can also see my past attempts, which are commented out.

class A_seq_base extends uvm_sequence #(A_tb_txn);

   // Constructor
   function new (string name = "A_seq_base");
      super.new(name);
   endfunction : new
   
   `uvm_object_utils(A_seq_base)
   `uvm_declare_p_sequencer(A_tb_sequencer)
    
   // UVM Sequence Body task
   virtual task body();
      
      `uvm_create(req)
      req.randomize();
      `uvm_send(req)

   endtask : body

endclass : A_seq_base
class A_seq_stop_signal extends A_seq_base;

   // Constructor
   function new (string name = "A_seq_stop_signal");
      super.new(name);
   endfunction : new
   
   `uvm_object_utils(A_seq_stop_signal)
   
   // UVM Sequence Body task
   virtual task body();

      assert(req.randomize() with  {req.A_command == A_instructions::STOP_SIGNAL;} );
      `uvm_send(req)

     // `uvm_do_on_with(req,p_sequencer,{req.A_command == A_instructions::STOP_SIGNAL;})

   endtask : body

endclass : A_seq_stop_signal
class A_lseq_signal extends A_seq_base ;

   `uvm_object_utils(A_lseq_signal)

   A_seq_stop_signal stop_seq;

   // Constructor
   function new (string name = "A_lseq_signal");
      super.new(name);

      // Create the sub sequences
      stop_seq = A_seq_stop_signal::type_id::create("stop_seq");

   endfunction : new

virtual task body();

   assert(stop_seq.randomize() with {stop_seq.req.wait_time == 5;} );
   stop_seq.start(p_sequencer);

//   assert(stop_seq.randomize() with {stop_seq.wait_time == 5;} );
//   stop_seq.start(p_sequencer);

//   `uvm_do_with(stop_seq, {stop_seq.wait_time==5;})

endtask : body            
   
endclass : A_lseq_signal 

In reply to jms8:
You are getting a null access error because req is not constructed at the time you randomize from the top level sequence. A_seq_stop_signal does not construct req.

You should be using the UVM factory to add the constraint. The factory was specifically designed to allow you modify lower level classes from the top. I don’t have time right now to give you an example. but what you should do is extend a_tb_txn with the wait_time constraint into another class. then set the override in the body of A_lseq_signal, and then call super.body(). Hopefully this will give you an idea of what to do.

In reply to dave_59:

Hi Dave,

If the body of A_lseq_signal class is changed to the code below:-

virtual task body();

super.body();
`uvm_do_with(stop_seq, {stop_seq.req.wait_time==5;})

endtask : body

Should this have worked?