This is an example of code similar to my case just to simplify the issue:
the following is the main virtual sequence implementing a normal behavior:
class seq1_vseq extends uvm_sequence;
uvm_reg_seq seq1;
vip_seq seq2;
`uvm_object_utils(seq1_vseq )
function new(string name="seq1_vseq ");
super.new(name);
endfunction : new
virtual task body();
uvm_status_e status;
uvm_reg_data_t value;
int k_idx;
seq1 = uvm_reg_seq ::type_id::create("seq1 ");
seq2 = vip1_seq ::type_id::create("seq2");
fork
forever
seq2.start(p_sequencer.vip1_seqr, this);
seq1.start(p_sequencer.ahb_seqr, this);
join_any
endtask : body
endclass: seq1_vseq
the following one is a special sequence that will call for the above sequence to implement a special behavior which is the normal behavior of above virtual sequence that will be interrupted by a special event:
class seq1_with_abort_event_vseq extends uvm_sequence;
seq1_vseq vseq1;
`uvm_object_utils(seq1_with_abort_event_vseq )
function new(string name="seq1_with_abort_event_vseq ");
super.new(name);
endfunction : new
virtual task body();
vseq1 = seq1_vseq::type_id::create("vseq1");
fork
vseq1.start(p_sequencer, this;
begin
wait (abort == 1);
vseq1.kill();
//some code to handle the abort event
//we restart the vseq1 again after treating the abort event
vseq1.start(p_sequencer, this));
end
join
endtask: body
endclass: seq1_with_abort_event_vseq
the uvm_error issued by seq1 (called in seq1_vseq) sequencer.
To answer chr_sue about why I did not use a break statement when the abort event occurred inside the sequence (seq1_vseq)) that I will stop or kill, in fact the two processes are separated I wanted to do something clean and reusable since seq1_vseq just one example I have many like it in my case, so I implemented all normal behaviors in each sequence then for the abort event I called a sequence each time with the abort event in a new sequence (seq1_with_abort_event_vseq ), it may not be the perfect approach but I found it more clean and simple to understand and debug.