Quantcast
Channel: Cadence Functional Verification Forum
Viewing all articles
Browse latest Browse all 1069

How to use uvm_agent for sequencing

$
0
0

Hi all,

based on the discussion in https://community.cadence.com/cadence_technology_forums/f/functional-verification/38665/run_phase-doesn-t-update-sv-interface-signals I have extended the testbench  with uvm_agent, but sequencing cannot be bound properly.

DUT interface, DUT and testbench are in the thread above. I am trying to test a very simple counter to learn UVM environment.

My UVM package looks like as follows.

I get the compilation error at Incisive 15.22.

ncvlog: *E,NOTCLM (tb_pkg.sv,120|52): seq_item_port is not a class item.
seq.start (m_env.m_seqr);

The problem is the "run_phase" function in uvm_test which complains that the object cannot be found. Where should I move the seq_item_port? To the agent or to the sequencer? And how?

Sorry this might be stupid question but I couldnt figure out how to do it, because on web most examples are simple so that there is no need to use uvm_agent.

Any help appreciated.


`include "uvm_macros.svh"

// www.youtube.com/watch
package my_pkg;

import uvm_pkg::*;

// Transaction (for constrain random value generation)

class my_transaction extends uvm_sequence_item;

`uvm_object_utils (my_transaction)

rand logic [7:0] load_val;
constraint c_load_val { load_val > 10 ; load_val < 20; }

function new(string name = "");
super.new(name);
endfunction

function void do_copy (uvm_object rhs);
my_transaction tx;
$cast(tx, rhs);
load_val = tx.load_val;
endfunction

endclass : my_transaction

// Sequencer (to create sequences, to be called by the driver)

typedef uvm_sequencer #(my_transaction) my_sequencer;

class my_sequence extends uvm_sequence #(my_transaction);

`uvm_object_utils(my_sequence)

function new (string name = "");
super.new(name);
endfunction

task body;
if (starting_phase != null)
starting_phase.raise_objection(this);

repeat (8)
begin
req = my_transaction::type_id::create("req");
start_item(req);
if (!req.randomize()) `uvm_error ("", "randomize failed");
finish_item (req);
end

if (starting_phase != null)
starting_phase.drop_objection(this);
endtask : body

endclass: my_sequence

// Driver

class my_driver extends uvm_driver #(my_transaction);
`uvm_component_utils (my_driver)

// this is the DUT interface, mostly instantiated in the driver
virtual dut_if dut_vi;

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

function void build_phase(uvm_phase phase);
if (! uvm_config_db #(virtual dut_if)::get(this, "", "dut_if", dut_vi))
`uvm_error ("", "uvm_config_db::get failed");

endfunction

task run_phase(uvm_phase phase);
forever
begin
seq_item_port.get_next_item(req);
@(posedge dut_vi.i_clk);
$display ("run_phase!!");
dut_vi.i_load_en <= '1;
// dut_vi.i_load_val <= $urandom;
dut_vi.i_load_val = req.load_val;
seq_item_port.item_done();
end
endtask

endclass: my_driver


// Agent

class my_agent extends uvm_agent;

my_sequencer m_seqr;
my_driver m_driv;

`uvm_component_utils(my_agent)

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

// build phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);

if (get_is_active() == UVM_ACTIVE) begin
m_driv = my_driver::type_id::create("m_driv", this);
m_seqr = my_sequencer::type_id::create("m_seqr", this);
end
endfunction : build_phase

function void connect_phase(uvm_phase phase);
if (get_is_active() == UVM_ACTIVE) begin
m_driv.seq_item_port.connect(m_seqr.seq_item_port);
end
endfunction : connect_phase

endclass : my_agent


// Environment

class my_env extends uvm_env;
`uvm_component_utils (my_env)

// my_sequencer m_seqr;
// my_driver m_driv;
my_agent m_agt;


// Constructor - informs parent this class
function new (string name, uvm_component parent);
super.new(name, parent);
endfunction : new

function void build_phase(uvm_phase phase);
// m_seqr = my_sequencer::type_id::create("m_seqr", this);
// m_driv = my_driver::type_id::create("m_driv", this);
m_agt = my_agent::type_id::create("m_agt", this);
endfunction : build_phase

// if connect_phase is empty, then no need to instantiate it :-)

// function void connect_phase(uvm_phase phase);
// m_driv.seq_item_port.connect(m_seqr.seq_item_export);
// endfunction : connect_phase

endclass


// driver is instantiated in the test
class my_test extends uvm_test;

`uvm_component_utils (my_test)

// decl member
my_env m_env;

// standard code for all components
// must it be a virtual function?
function new (string name, uvm_component parent);
super.new (name, parent);
endfunction

// Factory method call "create" in UVM is used
// we extend the functionality of m_env
function void build_phase(uvm_phase phase);
m_env = my_env::type_id::create("m_env", this);
endfunction

// only task phase (contains sim time)
task run_phase(uvm_phase phase);
/* // from now on the test is busy
phase.raise_objection(this);
// we consume some time
#200;
// one of 4 macros, others: `uvm_warning, `uvm_error, `uvm_fatal
// UVM_MEDIUM - verbosity level: UVM_INFO,
`uvm_info("", "Hello world", UVM_MEDIUM);
// I'm finished, test is over
phase.drop_objection(this); */
my_sequence seq;
seq = my_sequence::type_id::create("seq");
if(!seq.randomize() ) `uvm_error ("", "run_phase::seq.randomize failed");
seq.starting_phase = phase;
seq.start (m_env.m_seqr);
endtask

endclass: my_test

endpackage : my_pkg


Viewing all articles
Browse latest Browse all 1069

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>