I do the objections and start my sequences from my test which extends my uvm test.
In my following code I run 2 sequences on the same sequencer from my top level test.
class class_test_ge extends class_bb_test;
`uvm_component_utils(class_test_ge)
// my sequences
seq_usb_host_ctrl c_seq_usb_host_ctrl;
seq_usb_host_bulk_in_out c_seq_usb_host_bulk_in_out;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// create the sequences
c_seq_usb_host_ctrl = new("c_seq_usb_host_ctrl");
c_seq_usb_host_bulk_in_out = new("bulk_in_out");
// get the ref to the sequencer
if (!uvm_config_db#(uvm_sequencer_base)::get(null, "", "usb_host_sqr", usb_host_sqr))
`uvm_fatal("NOVIF", {"Usb Host sequencer must be set for: ", get_full_name(), ".usb_host_sqr"});
endfunction
task main_phase(uvm_phase phase);
phase.raise_objection(this);
fork
c_seq_usb_host_ctrl.start(usb_host_sqr);
c_seq_usb_host_bulk_in_out.start(usb_host_sqr);
join_any
// run the test for 200 usec
#200_000;
phase.drop_objection(this);
endtask
endclass
The lower level agent adds the name of the sequencer to the uvm_config_db and then the top level test gets the ref to sequencer from the uvm_config_db and uses this as the ref for the sequence.start function.
I used to do the objection in the pre_body and post_body of the sequence because I saw this in one of the uvm examples. I do not believe this correct and only the top level test should raise and drop the objection. This allows the top level test to control the duration of the sim and not the sequence.