Correct way to kill sequences

I am a bit confused on how to correctly kill a sequence. Here is what the UVM Cookbook ( from Mentor) say s about killing sequences.


Stopping a Sequence
Once started, sequences should not be stopped.
There are two methods available in the sequence and sequencer API that allow sequences to be killed. However,
neither method checks that the driver is not currently processing any sequence_items and the result is that any
item_done() or put() method called from the driver will either never reach the controlling sequence or will cause an
UVM fatal error to occur because the sequences return pointer queue has been flushed.
The methods are:
• .kill()
• .stop_sequences()
Do not use these methods unless you have some way of ensuring that the driver is inactive before making the call.


Now, based on past experiences, this is what I have done for killing sequences. This code is used for things like phase jumping when sequences need to be killed ban in the middle of the main_phase. Basically, we are stopping the sequences and then sending an event to the driver to stop it.

class agent_c extends uvm_agent;
 `uvm_component_utils(agent_c)
 sqr_c sqr;
 drv_c drv;
 ...
 virtual task pre_reset_phase(uvm_phase phase);
   if(sqr && drv) begin
     sqr.stop_sequences();
     ->drv.reset_driver;
   end
 endtask : pre_reset_phase
endclass : agent_c

Here is the corresponding code from the driver that kills the driver ( and presumably the item_done inside)


class drv_c extends uvm_driver;
 `uvm_component_utils(drv_c)
 event reset_driver;
 ...
 virtual task run_phase(uvm_phase phase);
   forever begin
   @(posedge my_vi.rst_n);
     fork
       driver();
     join_none
     @(reset_driver);
     disable fork;
     cleanup();
   end
 endtask : run_phase
 
virtual task driver();
 forever begin
 ...
 end
 endtask : driver
endclass : drv_c

The stop_sequences call does the following : (From the comments section for this function from uvm_sequencer.h)
// Tells the sequencer to kill all sequences and child sequences currently
// operating on the sequencer, and remove all requests, locks and responses
// that are currently queued. This essentially resets the sequencer to an
// idle state.

The question I have is if you have reset the sequencer to an idle state before you stop the driver, how does one ensure that the driver will not call an item_done on a transaction after the stop_sequences call and before the reset_driver call ? I have used the above code before and it has worked. What I am wondering is how this works ?

If the above is not the right way to kill sequences, what is the recommended way ?

In reply to DVJoe:

I do not see in your code any reason to use the sub_phases of the run_phase. I believe you are doing simple things complicated. Stopping/killing sequences might be useful during the development steps but it is dangerous and high risk to do this when verifying your DUT.
If you are dealing with different sequences like reset sequence, config sequence and operational sequences you can reach the same objective as you doing running the sub_phases. The difference is it is mor easy and avoids critical situations.

@chr_sue,

The sequence stopping is being done for active reset testing where we yank the reset randomly somewhere in the main_phase to see if the DUT can handle a reset while traffic is running. This is routinely done for blocks that need this kind of verification.

If you are familiar with phase jumping and active reset testing, I beleive one has to stop_sequences at some point to achieve this. If you think that is not the case, can you shed light on how you have done it with some example code.

For example, this is one paper that talks about active reset testing and phase jumping. This one also uses the stop_sequences to do active reset testing.

http://www.sunburst-design.com/papers/HunterSNUGSV_UVM_Resets_paper.pdf

In reply to DVJoe:

The scenario you are describing can be implemented using run_phase only. You do not need any phase jumping.
You can run your main traffic and start a reset sequence by grabbing the main traffic sequence. Executing the reset and afterwards continuewith the main traffic. This is a very easy implementation.
For a code example see the code examples in the Verification Academy.
Wrt to the paper you are mentioning. This is another way of doing this. I my eyes it is not really easier than what I was proposing.

In reply to chr_sue:

Could you tell us which code example in the Verification Academy show the easy implementation?
I found many examples in the link,but don’t know which one.
Thanks.

In reply to ZhaoHengzheng:

Please look here:
Sequencer Grab Lock
or any of the interrupt code examples.