UVM test finishes immediately

I am trying to run a simple uvm testbench and i can get it to compile and “run”, but it seems to stop immediately into the simulation at the first rising edge of the clock…

I put some silly print statements into the various tasks/function and it looks like the sequence body() task is running, the run_phase() of the test is running, but the run_phase() task of the driver is not running.

I reviewed the connect_phase code in my agent and as far as I can tell the sequencer and driver are connected correctly.

So what I am trying to understand is why does my driver code never execute?
Or at least it seems to never execute because my print statement in there never executes…

It is also confusing to me since it was my understanding was that the driver pulls sequence_items from the sequence via the sequencer and the sequence body task generates the sequence_items. If this is correct then i dont understand why my sequence body task executes but my run_phase() task in my driver never runs… since in my understanding the drive run_phase() task should “call” or at least initiate the sequence_items body task.

Any ideas what i am doing wrong?

Below is the output from my console with the print statement i am using.

UVM_INFO @ 0: uvm_test_top.m_env.uvm_csv_agent.drv [uvm_test_top.m_env.uvm_csv_agent.drv] get_full_name()

uvm_test_0.run_phase : phase.raise_objection:

uvm_csv_packet_sequence.body :

uvm_test_top.m_env.uvm_csv_agent.sqr.m_seq.uvm_csv_packet_item_inst

data = 'hc 'd12

valid = 'h1 'd1

** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0

Time: 10 ns Iteration: 1 Instance: /top_tb/depack/depacketizer_buffer_inst/data_shifter_inst

** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0

Time: 10 ns Iteration: 1 Instance: /top_tb/depack/depacketizer_buffer_inst/data_shifter_inst

UVM_INFO verilog_src/uvm-1.1d/src/base/uvm_objection.svh(1268) @ 10000: reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase

Below is the code for the “relavent” parts of my testbench.

If there are other parts of code in here that i should add to clarify things let me know.

test.sv

task  uvm_test_0::run_phase (uvm_phase phase);
	phase.raise_objection(this);
	$display("uvm_test_0.run_phase : phase.raise_objection: ");
	m_seq.start(m_env.uvm_csv_agent_inst.uvm_csv_sequencer_inst);
	phase.drop_objection(this);
endtask : run_phase

sequence.sv

  
task uvm_csv_packet_sequence ::body();
  uvm_csv_packet_item_inst = uvm_csv_packet_item::type_id::create("uvm_csv_packet_item_inst");
  $display("uvm_csv_packet_sequence.body :  ");
  start_item(uvm_csv_packet_item_inst); 
  finish_item(uvm_csv_packet_item_inst); 
endtask : body

agent.sv

  
function void uvm_csv_agent::build_phase(uvm_phase phase);  
  uvm_csv_sequencer_inst =uvm_csv_sequencer::type_id::create("sqr",this);
  uvm_csv_driver_inst    =uvm_csv_driver::type_id::create("drv",this);
endfunction : build_phase

function void uvm_csv_agent::connect_phase(uvm_phase phase);
   uvm_csv_driver_inst.seq_item_port.connect(uvm_csv_sequencer_inst.seq_item_export);
endfunction : connect_phase

driver.sv

task uvm_csv_driver::run_phase(uvm_phase phase);
    forever
    begin
        $display("uvm_csv_driver::run_phase ");
      seq_item_port.get_next_item(req);
      do_drive();
      seq_item_port.item_done();
    end
  endtask : run_phase

  task uvm_csv_driver::do_drive();
  	@(posedge virtual_interface.clk);
    virtual_interface.data = req.data;
    virtual_interface.data_valid = req.valid;
  endtask : do_drive

In reply to mreister:

  1. Is your agent passive when building the environment?
  2. Can you add a display statement after the start_item and also may be after finish_item to keep track of the driver -sequencer hand shake
  3. Here I see that you added a display before the start_item so that doesn’t give too much info on the hand shake
  4. you can do the same in the driver, adding displays after get_next_item and before item_done and also in the actual driver task

My view is that the handshake hasn’t started here based on the code I could see, guessing if the agent is also passive and not active which can cause the issue you are observing

In reply to hsam:

Did you check your clock signal?
BTW where does

uvm_test_top.m_env.uvm_csv_agent.sqr.m_seq.uvm_csv_packet_item_inst

data = 'hc 'd12

valid = 'h1 'd1

Come from?

In reply to hsam:

As far as whether my driver is active or passive i believe its active…
because i have the following in my agent class:

uvm_active_passive_enum is_active = UVM_ACTIVE;

updated console output
Ok. Interesting…

It seems as though when i put in the print statements you suggested things start to make a little more sense…

It now seems as though the run_phase task of the driver is executing and that its executing before the sequence.body.

it then seems to go through one “cycle” of the the get_next_item/item_done in the driver… but then when the driver run_phase() start agian that when the party stops…

See updated code and console output below:

uvm_test_0.run_phase : phase.raise_objection:

uvm_csv_driver::run_phase

uvm_csv_packet_sequence.body :

After Start Items

After get_next_item

** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0

Time: 10 ns Iteration: 1 Instance: /top_tb/depack/depacketizer_buffer_inst/data_shifter_inst

** Warning: NUMERIC_STD.TO_INTEGER: metavalue detected, returning 0

Time: 10 ns Iteration: 1 Instance: /top_tb/depack/depacketizer_buffer_inst/data_shifter_inst

After item_done

uvm_csv_driver::run_phase

After Finish Items

UVM_INFO verilog_src/uvm-1.1d/src/base/uvm_objection.svh(1268) @ 10000: reporter [TEST_DONE] ‘run’ phase is ready to proceed to the ‘extract’ phase

updated sequencer.sv

  task uvm_csv_packet_sequence ::body();    
    uvm_csv_packet_item_inst = uvm_csv_packet_item::type_id::create("uvm_csv_packet_item_inst");
    $display("uvm_csv_packet_sequence.body :  ");
    uvm_csv_packet_item_inst.data = p3_packet_data[0];
    uvm_csv_packet_item_inst.valid = 1;
    start_item(uvm_csv_packet_item_inst); driver?
    $display("After Start Items" );
    finish_item(uvm_csv_packet_item_inst); driver?
    $display("After Finish Items" );
  endtask : body

updated driver.sv

task uvm_csv_driver::run_phase(uvm_phase phase);
    forever
    begin    	
      $display("uvm_csv_driver::run_phase ");
      seq_item_port.get_next_item(req);
      $display("After get_next_item ");        
      do_drive();      
      seq_item_port.item_done();
      $display("After item_done ");        
    end
  endtask : run_phase

In reply to chr_sue:

that output came from me printing my transaction… and my poor attempt at implementing the convert2string() function in my sequence item.

As far as the clock here is my code for it along with my top_level test bench with my DUT:

import uvm_pkg::*;
import uvm_csv_test_pkg::*;

module top_tb;
  timeunit      100ns;
  timeprecision 1ps;
initial begin
  input_i.clk = 0;
  forever #10ns input_i.clk = ~input_i.clk;
end

 uvm_csv_depack_in input_i ();
 uvm_csv_depack_in output_o ();

  /* depacketizer */
  depacketizer depack (
    // input
    .data_i(input_i.data),
  .data_valid_i(input_i.data_valid),
  .x_res_i(13'h0000),
  .y_res_i(12'h000),
  .clk_i(input_i.clk),
  .rst_i(1'b0),
  // output 
  .data_o(output_o.data),
  .data_valid_o(output_o.data_valid)
);

  initial
  begin
    uvm_config_db #(virtual uvm_csv_depack_in)::set(null,"uvm_test_top.*", "input_i", input_i); // assign the interface
    uvm_config_db #(virtual uvm_csv_depack_in)::set(null,"uvm_test_top.*", "output_o", output_o);
    run_test(); // run the test
  end
endmodule

I can see my clock signal go high in my waveform viewer but it is at that very instance of time when my simulation ends…

In reply to mreister:

Could you please put your testbench example to EDAPlayground? This would help to debug your code.
And put in more diagnostic messages - please using `uvm_info instead of $display.
This helps you to improve your debug knowledge.

In reply to chr_sue:

ok. that is a good idea. I have uploaded the design here UVM test finishes immediately - EDA Playground
I am still trying to figure out how to get it to compile correctly on there.

In reply to mreister:

Do we need the csv_parser for the testbench? The corresponding file is missing.
And what is ‘csv_record’. There is no definition.

In reply to mreister:

Your environment is acting exactly as it should:

  • Your test raises an objection and starts one sequence
  • Your sequence body creates one sequence_item and calls start_item()/finish_item() to send it to the agent sequencer
  • The agent driver gets the one sequence_item from the sequencer
  • The driver calls do_drive(), which has only one timing construct: @(posedge virtual_interface.clk);
  • Once this timing construct detects the posedge of the clock, it will complete the data/valid assignments
  • The sequence_item is now finished
  • The sequence is now finished
  • The test drops the objection and the simulation exits

This is why you see the test finish immediately on the first posedge of the clock. If you add a drain_time(), you can run longer.

In reply to cgales:

Thanks! That explains things… I was under the incorrect assumption that the body() of the sequence would be called every time get_next_item(req) in the driver was called…

I believe I thought this because the sequencer examples I was looking at only used one sequence item… probably for simple demonstration purposes.

After this comment and reviewing better examples for sequence from the mentor uvm code examples I was able to figure this out.

I now have my simulation running!

I appreciate everyone’s help on this.