Item_done is called and returned but execute_item in sequencer is still blocked and not doing forward to send next item

Hi,

I have a task in virtual sequencer which actually randomizes the sequence item and then uses execute_item to send the randomized sequence item to the driver.

The driver receives an item using get_next_item. Upon receiving, it drives the item and calls item_done.
Using debug message after item_done, I can clearly see that item_done is called and returned but execute_item in sequencer is still blocked and not going forward to send next item (it implements a loop).

Can anyone help me with possible reasons why execute_item would not return even when driver has called item_done and come out of item_done.

Below is the code of task in sequencer:
assert(item.randomize());
dc_seqr.execute_item(item);

Below is the code in driver:

forever begin
seq_item_port.get_next_item(item);
$cast(m_transfer,item);
void’(this.begin_tr(m_transfer));
drive_data(m_transfer);
this.end_tr(m_transfer);
seq_item_port.item_done(m_transfer);
end

PS:
execute_item has finish_item() and kept display statements below and above of it and i can find that its hanging at finish_item.
The task is called multiple times and the issue is coming for only recent call and is there are no more calls are happening because its hanging at finish_item.

Thanks in advance!
Avinash.

In reply to vgadupu:

Your problem is in the virtual sequence. I virtual sequence is a sequence which does not generate sequence items. What you have to do after randomizing the sequence you want to execute is starting this sequence.
See the body method below:

task example_top_default_seq::body();
super.body();

apb_seq = apb_default_seq::type_id::create(“apb_seq”);
spi_seq = spi_default_seq::type_id::create(“spi_seq”);

`uvm_info(get_type_name(),“default sequence starting”, UVM_MEDIUM)

repeat(10) begin
`uvm_info(get_type_name(),“apb sequence starting”, UVM_MEDIUM)

void’(apb_seq.randomize());
apb_seq.start(apb_sequencer_i);
`uvm_info(get_type_name(),“spi sequence starting”, UVM_MEDIUM)

void’(spi_seq.randomize());
spi_seq.start(spi_sequencer_i);
end

// alternatively use macros to start sequences
// fork
// uvm_do_on(apb_seq, apb_sequencer_i) // uvm_do_on(spi_seq, spi_sequencer_i)
// join
`uvm_info(get_type_name(),“default sequence completed”,UVM_MEDIUM)
endtask : body

My UVM testbench has 2 agents, one for apb and another one for spi.
In the virtual sequence I’m starting both sequences.

In reply to chr_sue:

Hi,

I am using execute_item in virtual_sequencer but not in virtual_sequence.

Regards,
Avinash.

In reply to vgadupu:

Could you please elaborate a little bit more in detail?
You can only start a sequence on a sequencer.

In reply to chr_sue:

In my virtual sequencers i will have sequencers handles of all the different sequencers. For example if my environment has I2C, AHB, APB then my virtual sequencer will have sequencers of I2C, AHB and APB. So, in UVM sequencer base there will be execute_item method which actually has a object of uvm_sequence_base and this execute_item accepts item of type uvm_sequence_item and it will have the following code snippet.

task uvm_sequencer_base::execute_item(uvm_sequence_item item);
uvm_sequence_base seq;

seq = new();
item.set_sequencer(this);
item.set_parent_sequence(seq);
seq.set_sequencer(this);
uvm_info(get_full_name(),$psprintf("Calling START_ITEM: %s",item.sprint()),UVM_LOW) seq.start_item(item); uvm_info(get_full_name(),$psprintf(“Calling FINISH_ITEM: %s”,item.sprint()),UVM_LOW)
seq.finish_item(item);
`uvm_info(get_full_name(),$psprintf(“Exiting execute_item: %s”,item.sprint()),UVM_LOW)
endtask

From the above code it is implying that you can send item to driver of a particular environment without sequence. For example i will call i2c_seqr.execute_item(item); This way i can send items from my virtual sequencer.

Please let me know if this helps.

In reply to vgadupu:

There are 2 different ways to deal with virtual sequences, either you have the refences of your agent sequencers in the virtual sequence or you have it in the virtual sequencer. If you have it in the virtual sequence you do not need a virtual sequencer. This is how I work with.
My virtual bse sequence looks like this:
//-----------------------------------------------------------------------------
class example_top_base_seq extends uvm_sequence #(uvm_sequence_item);
//-----------------------------------------------------------------------------

`uvm_object_utils(example_top_base_seq)

example_top_config cfg;
apb_sequencer apb_sequencer_i;
spi_sequencer spi_sequencer_i;

extern function new(string name = “example_top_base_seq”);

extern task body();
//---------------------------------------------------------------------------
// constraints
//---------------------------------------------------------------------------

endclass : example_top_base_seq

//-----------------------------------------------------------------------------
// example_top_base_seq implementation
//-----------------------------------------------------------------------------

function example_top_base_seq::new(string name = “example_top_base_seq”);
super.new(name);
endfunction : new
task example_top_base_seq::body();
if (!uvm_config_db #(apb_sequencer)::get(null, get_full_name(), “apb_sequencer”, apb_sequencer_i))
uvm_error(get_type_name(), "Config Error uvm_config_db #(apb_sequencer)::get cannot find sequencer") if (!uvm_config_db #(spi_sequencer)::get(null, get_full_name(), "spi_sequencer", spi_sequencer_i)) uvm_error(get_type_name(), “Config Error uvm_config_db #(spi_sequencer)::get cannot find sequencer”)
endtask: body

This are the refernces to the agent sequencers.
The real sequence is here:
class example_top_default_seq extends example_top_base_seq;

`uvm_object_utils(example_top_default_seq)

// UVC sequences
apb_default_seq apb_seq;
spi_default_seq spi_seq;

extern function new(string name = “example_top_default_seq”);
extern task body();

endclass : example_top_default_seq

//-----------------------------------------------------------------------------
// example_top_default_seq implementation
//-----------------------------------------------------------------------------

function example_top_default_seq::new(string name = “example_top_default_seq”);
super.new(name);
endfunction : new

task example_top_default_seq::body();
super.body();

apb_seq = apb_default_seq::type_id::create(“apb_seq”);
spi_seq = spi_default_seq::type_id::create(“spi_seq”);

`uvm_info(get_type_name(),“default sequence starting”, UVM_MEDIUM)

repeat(10) begin
`uvm_info(get_type_name(),“apb sequence starting”, UVM_MEDIUM)

void’(apb_seq.randomize());
apb_seq.start(apb_sequencer_i);
`uvm_info(get_type_name(),“spi sequence starting”, UVM_MEDIUM)

void’(spi_seq.randomize());
spi_seq.start(spi_sequencer_i);
end

// alternatively use macros to start sequences
// fork
// uvm_do_on(apb_seq, apb_sequencer_i) // uvm_do_on(spi_seq, spi_sequencer_i)
// join
`uvm_info(get_type_name(),“default sequence completed”,UVM_MEDIUM)
endtask : body
And the body task of the agent sequence looks like this:

task spi_default_seq::body();
uvm_info(get_type_name(),"default sequence starting", UVM_MEDIUM) super.body(); item = spi_seq_item::type_id::create("item"); begin start_item(item); item.data = data; item.no_bits = no_bits; item.RX_NEG = RX_NEG; finish_item(item); end uvm_info(get_type_name(),“default sequence completed”, UVM_MEDIUM)

// Alternatively use macros
// `uvm_do_with(item, {
// item.data == data;
// item.no_bits == no_bits;
// item.RX_NEG == RX_NEG;
// })

endtask : body

Does this help for your understanding?