Zero simulation time

Hello people,
I’m working on UVM project and I’m stuck with VCS simulation ending at time = 0. I don’t see any warnings or syntax errors in the log file. Can anyone tell me what are the possible reasons for this error so that I can look into those particular sections of my verification test bench.

Thank You

In reply to Ramakrishna Melgiri:

Please focus some code. There might not be any component which raises an objection in your code. Just add raise/drop objections guarding the run_phase.

// In test or any other component
task run_phase(uvm_phase phase);
phase.raise_objection(this);
//... 
// do some stuff
// work on some sequences
phase.drop_objection(this);
endtask

Refer this link for objection mechanism.

In reply to sharvil111:

Hi @sharvil111 This is a snippet from my test bench where I raise and drop objections. I’m unable to find out the bug.
class cpu_test extends uvm_test;

`uvm_component_utils(cpu_test)

 cpu_config cpu_config_0;

 cpu_env cpu_env_h;   

 function new(string name, uvm_component parent);
super.new(name, parent);
 endfunction: new

 function void build_phase(uvm_phase phase);
cpu_config_0 = new();

if(!uvm_config_db #(virtual cpu_if)::get( this, "", "cpu_vi", 
					  cpu_config_0.cpu_vi))
      `uvm_fatal("NOVIF", "No virtual interface set")

uvm_config_db #(cpu_config)::set(this, "*", "cpu_config", 
				    cpu_config_0);
cpu_env_h = cpu_env::type_id::create("cpu_env_h", this);
 endfunction: build_phase

endclass // cpu_test

class test1 extends cpu_test;
`uvm_component_utils(test1)

 function new(string name, uvm_component parent);
super.new(name, parent);
 endfunction: new

 task run_phase(uvm_phase phase);
read_modify_write seq;
seq = read_modify_write::type_id::create("seq");
phase.raise_objection(this);
seq.start(cpu_env_h.cpu_agent_h.cpu_sequencer_h);
phase.drop_objection(this);
 endtask // run_phase

endclass: test1

In reply to Ramakrishna Melgiri:

Can you confirm that you are running testcase ‘test1’ (from the log or with `uvm_info)? Time should be advancing in the drivers run_phase task. You need to confirm that the driver is actually receiving sequence item(s) (from the read_modify_write sequence). Then confirm that the driver’s run_phase is advancing time or show your sequence and driver code.

In reply to Ramakrishna Melgiri:

Does your sequence start gracefully? Also, confirm which testcase is executed.

You must call super.build_phase from test1 to create the environment and other classes.

In reply to dhserfer:

Hey, I’m adding my sequences, driver and test designs here:
Sequences:

package cpu2reg_sequences;

import uvm_pkg::*;

class cpu2reg_transaction extends uvm_sequence_item;

    `uvm_object_utils(cpu2reg_transaction)
    
    rand bit [1:0] A;
    rand bit WE;
    rand int WD;
    
    // add constraints
    
    function new (string name = "");
        super.new(name);
    endfunction: new
    
    function string convert2string;
        return $psprintf("A:\t%0b\n CPU_WE:\t%0b\n Write_Address:\t%0h", A, WE, WD);
    endfunction: convert2string
    
    // do copy, do compare
endclass: cpu2reg_transaction

class cpu2reg_rw extends uvm_sequence #(cpu2reg_transaction);

    `uvm_object_utils(cpu2reg_rw)
    
    function new (string name = "");
        super.new(name);
    endfunction: new
    
    task body;
        cpu2reg_transaction tx;
        bit [1:0] a;
        int d;
        
        tx = cpu2reg_transaction::type_id::create("tx");
        start_item(tx);
        assert( tx.randomize() );
        tx.WE = 0; // force the WE to Read
        finish_item(tx);
        
        a = tx.A;
        d = tx.WD;
        ++d; // modify the data
        
        tx = cpu2reg_transaction::type_id::create("tx");
        start_item(tx);
        assert( tx.randomize() with { tx.A == a; tx.WE == 1; tx.WD == d; } );
        finish_item(tx);
    endtask: body
    
endclass: cpu2reg_rw

class seq_of_commands extends uvm_sequence #(cpu2reg_transaction);

    `uvm_object_utils(seq_of_commands)
    `uvm_declare_p_sequencer(uvm_sequencer#(cpu2reg_rw))
    
    rand int n; // nob on UVM
    
    constraint how_many { n inside {[2:4]}; }
    
    function new (string name = "");
        super.new(name);
    endfunction: new
    
    task body;
        repeat(n)
        begin
            cpu2reg_rw seq;
            seq = cpu2reg_rw::type_id::create("seq");
            assert( seq.randomize() );
            seq.start(p_sequencer);
        end 
    endtask: body
    
endclass: seq_of_commands

endpackage: cpu2reg_sequences

Driver:

class cpu2reg_driver extends uvm_driver #(cpu2reg_transaction);

    `uvm_component_utils(cpu2reg_driver)
    
    cpu2reg_config cpu2reg_config_0;
    virtual cpu2reg_if cpu2reg_vi;
    
    function new (string name, uvm_component parent);
        super.new(name, parent);
    endfunction: new
    
    function void build_phase(uvm_phase phase);
         assert( uvm_config_db #( cpu2reg_config )::get(this, "", "cpu2reg_config", cpu2reg_config_0) );
         
        cpu2reg_vi = cpu2reg_config_0.cpu2reg_vi;
    endfunction: build_phase
    
    task run_phase(uvm_phase phase);
        forever
        begin
            cpu2reg_transaction tx;
            
            @(posedge cpu2reg_vi.Clk);

            seq_item_port.get(tx);
            
            // Wiggle pins of DUT
            cpu2reg_vi.A = tx.A;
            cpu2reg_vi.WE = tx.WE;
            cpu2reg_vi.WD = tx.WD;
            
            //seq_item_port.item_done();
        end 
    endtask: run_phase
    
endclass: cpu2reg_driver

Test:

class cpu2ocp_test extends uvm_test;

    `uvm_component_utils(cpu2ocp_test)
    
    cpu2reg_config cpu2reg_config_0;
    
    cpu2reg_env cpu2reg_env_h;
    
    function new (string name, uvm_component parent);
        super.new(name, parent);
    endfunction: new 
    
    function void build_phase(uvm_phase phase);
        cpu2reg_config_0 = new();
        
        if(!uvm_config_db #(virtual cpu2reg_if)::get( this, "", "cpu2reg_vi", cpu2reg_config_0.cpu2reg_vi))
            `uvm_fatal("NOVIF", "No virtual interface set")
        uvm_config_db #(cpu2reg_config)::set(this, "*", "cpu2reg_config", cpu2reg_config_0);
        
        cpu2reg_env_h = cpu2reg_env::type_id::create("cpu2reg_env_h", this );
    endfunction: build_phase
    
endclass: cpu2ocp_test

class test1 extends cpu2ocp_test;

    `uvm_component_utils(test1)
    
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction: new

    task run_phase(uvm_phase phase);
        cpu2reg_rw seq;
        seq = cpu2reg_rw::type_id::create("seq");
        phase.raise_objection(this);
        seq.start(cpu2reg_env_h.cpu2reg_agent_h.cpu2reg_sequencer_h);
        phase.drop_objection(this);
    endtask: run_phase
endclass: test1

class test2 extends cpu2ocp_test;

    `uvm_component_utils(test2)
    
    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction: new

    task run_phase(uvm_phase phase);
        seq_of_commands seq;
        seq = seq_of_commands::type_id::create("seq");
        assert( seq.randomize() );
        phase.raise_objection(this);
        seq.start( cpu2reg_env_h.cpu2reg_agent_h.cpu2reg_sequencer_h );
        phase.drop_objection(this);
    endtask: run_phase
 
endclass: test2

class test3 extends cpu2ocp_test;
 
    `uvm_component_utils(test3)

    function new(string name, uvm_component parent);
        super.new(name, parent);
    endfunction: new

    task run_phase(uvm_phase phase);
        seq_of_commands seq;
        seq = seq_of_commands::type_id::create("seq");
        seq.how_many.constraint_mode(0);
        assert( seq.randomize() with {seq.n > 10 && seq.n < 20;});
        phase.raise_objection(this);
        seq.start( cpu2reg_env_h.cpu2reg_agent_h.cpu2reg_sequencer_h );
        phase.drop_objection(this);
    endtask: run_phase
 
endclass: test3

I’ve modified my test block, so I’ve posted the updated one. Can you please tell me where I am going wrong in this.
Thank You.

In reply to Ramakrishna Melgiri:

If you face an issue with time not progressing this is in most cases caused by the driver.
Firstly you should check if your driver sees the posdege of the clock.
Secondly if you are performing a get_next_item/get in the driver this requires an indication to the sequencer by issuing a item_done/put.

In reply to Ramakrishna Melgiri:

Did you call “run_test()” in your top level TB?

Ting

In reply to tingqu:

Yes I called run_test() from top module

In reply to Ramakrishna Melgiri:

Your statement regarding ‘staying at time = 0’ is not precise enough. During runtime 0 the dynamic part of your testbench is built. After that the simulation starts. Because you say there are no errors and warnings I guess the testbench has been constructed. Can you please confirm?
All TLM components do not really consume time. Time consumtion is controlled by the driver and the monitor. Have a look to these components to identify the problem. My guess is your driver or monitor is not seeing a clock edge. Can you please check?

In reply to chr_sue:

Yes, I had issues with driver where I missed sequencer handle connection. Now, I am able to drive my stimulus to the DUT. I have to handle the responses now.
Thank You for the assistance.