The Proper Care and Feeding of UVM Sequences PDF

Download as pdf or txt
Download as pdf or txt
You are on page 1of 27

Advanced UVM

The Proper Care and Feeding of Sequences

Tom Fitzpatrick
Verification Evangelist

[email protected] | www.verificationacademy.com
Separating Stimulus from the Testbench
• A key to reusability is to separate Behavior from Structure

Configuration & Factory

Behavior
Structure
Testbench VIP

DUT

© 2013 Mentor Graphics Corporation, all rights reserved.


Review: Sequences
• Decouple stimulus specification from
structural hierarchy
• Add/remove/modify stimulus scenarios independent of testbench u1
• Simplify test writer API
u1
• Sequences define s1

transaction streams
• May start on any sequencer
s3 s5
• Sequences can call children s2

• Sequences & transactions customizable


via the factory s4

© 2013 Mentor Graphics Corporation, all rights reserved.


Review: Sequence Basics
class my_seq extends uvm_sequence #(req_t); Transaction type
`uvm_object_utils(uvm_seq)
req_t req; Default name in
int num = 10; constructor

function new(string name = “my_seq”);


super.new(name);
endfunction

task body();
uvm_config_db#(int)::get(this, “”, “num”, num);
req = req_t::type_id::create(“req”); Create request
for_int i = 0; i < num; i++) begin Initiate Driver Handshake
start_item(req);
Late Randomization
if(!req.randomize()) begin
`uvm_error(“body”, “rand failure”) Note: begin-end around
end `uvm_<msg>
finish_item(req);
end Send transaction
endtask
endclass
© 2013 Mentor Graphics Corporation, all rights reserved.
Review: Sequence/r/Driver Parameterization
class my_seq extends uvm_sequence #(type REQ=req_t, RSP=rsp_t);
`uvm_object_utils(my_seq)
… By default, RSP=REQ
endclass

class my_driver extends uvm_driver #(type REQ=req_t, RSP=rsp_t);


`uvm_component_utils(my_driver)
Parameterization must

match sequence
endclass

typedef uvm_sequencer #(type REQ=req_t, RSP=rsp_t) my_sequencer;

Don’t need to declare a


new sequencer type

© 2013 Mentor Graphics Corporation, all rights reserved.


Review: Sequence/Driver Handshake
my_seq1 driver
start_item(req); get_next_item(req);

finish_item(req);
item_done();

task body();
req = req_t::type_id::create(“req”); task run_phase(uvm_phase phase);
for_int i = 0; i < num; i++) begin forever begin
start_item(req); seq_item_port.get_next_item(req);
if(!req.randomize()) begin drive_item2bus(req);
`uvm_error(“body”, “rand failure”) seq_item_port.item_done();
end end
finish_item(req); endtask
`uvm_info(“my_seq1”,req.convert2string()); If driver updates req with
end response information
endtask
© 2013 Mentor Graphics Corporation, all rights reserved.
Review: Sequence/Driver Handshake
my_seq1 driver
start_item(req); get_next_item(req);

finish_item(req);
item_done();

get_response(rsp);
put_response(rsp);

task body();
req = req_t::type_id::create(“req”); task run_phase(uvm_phase phase);
for_int i = 0; i < num; i++) begin forever begin
start_item(req); seq_item_port.get_next_item(req);
if(!req.randomize()) begin drive_item2bus(req,rsp);
`uvm_error(“body”, “rand failure”) seq_item_port.item_done();
end rsp.set_id_info(req);
finish_item(req); seq_item_port.put_response(rsp);
get_response(rsp); end
If driver provides separate
end endtask
response object
endtask
© 2013 Mentor Graphics Corporation, all rights reserved.
Arbitration and Responses in the Sequencer
class myseq…; Sequence-specific
virtual task body();
Sequencer Unique within sequence

finish_item(req)
class req;
get_response(rsp);
get_response(rsp,id);
seq_id = 1;
2;
endtask s1
trans_id = 1;
endclass
arbitrate Driver
requests 1,1

Both 2,1
sequences s2

now waiting rsp


route seq_id
1,1 = 1; class driver…;
for responses task run();
responses trans_id = 1;

Sequencer uses rsp.set_id_info(req);
rsp
sequence_id to route seq_item_port.put_response(rsp);
seq_idset_id_info()
= 1; copies id endtask
response to trans_idfields
= 1; from req to rsp
originating sequence endclass
© 2013 Mentor Graphics Corporation, all rights reserved.
Arbitration and Responses in the Sequencer
class myseq…;
virtual task body();
use_response_handler(1); Customize the response handler as necessary
finish_item(req)
get_response(rsp,id);
endtask

virtual function void response_handler(uvm_sequence_item response);


… SEQ_ARB_FIFO
endfunction
SEQ_ARB_WEIGHTED
endclass
SEQ_ARB_RANDOM
SEQ_ARB_STRICT_FIFO
sequencer.set_arbitration(SEQ_ARB_USER); SEQ_ARB_STRICT_RANDOM
class my_sequencer extends uvm_sequencer(REQ); SEQ_ARB_USER
‘uvm_component_utils(my_sequencer)
virtual function integer user_priority_arbitration(integer avail_sequences[$]);

endfunction
endclass
© 2013 Mentor Graphics Corporation, all rights reserved.
Review: Starting a Sequence

class test1 extends uvm_test;

`uvm_component_utils(test1)

my_env my_env_h;
...

task run_phase(uvm_phase phase);


read_modify_write seq;
seq = read_modify_write::type_id::create(“seq”);

Create sequence
via factory

© 2013 Mentor Graphics Corporation, all rights reserved.


Review: Starting a Sequence

class test1 extends uvm_test;

`uvm_component_utils(test1)

my_env my_env_h;
...

task run_phase(uvm_phase phase);


read_modify_write seq;
seq = read_modify_write::type_id::create(“seq”);
phase.raise_objection(this);
seq.start( my_env_h.my_agent_h.my_sequencer_h );

Always use start() to


execute a sequence

© 2013 Mentor Graphics Corporation, all rights reserved.


Review: Starting a Sequence

class test1 extends uvm_test;

`uvm_component_utils(test1)

my_env my_env_h;
...

task run_phase(uvm_phase phase);


read_modify_write seq;
seq = read_modify_write::type_id::create(“seq”);
phase.raise_objection(this);
seq.start( my_env_h.my_agent_h.my_sequencer_h );

Path to sequencer

© 2013 Mentor Graphics Corporation, all rights reserved.


Can Start Sequence from Environment too

class my_env extends uvm_env;

`uvm_component_utils(my_env)
Factory enables test to
my_agent my_agent_h;
choose what default
...
sequence to run
task run_phase(uvm_phase phase);
read_modify_write seq;
seq = read_modify_write::type_id::create(“seq”);
phase.raise_objection(this);
seq.start( my_agent_h.my_sequencer_h );

phase.drop_objection(this);
endtask Path to sequencer

© 2013 Mentor Graphics Corporation, all rights reserved.


Sequential Sequences

class my_test extends uvm_test;



init_seq iseq;
exec_seq eseq; init_seq
...
task run_phase(uvm_phase phase);
iseq = init_seq::type_id::create(“iseq”);
eseq = exec_seq::type_id::create(“eseq”); exec_seq
phase.raise_objection(this);
iseq.start( my_env_h.my_agent_h.my_sequencer_h );
eseq.start( my_env_h.my_agent_h.my_sequencer_h );
… start() is blocking
phase.drop_objection(this);
endtask
endclass

© 2013 Mentor Graphics Corporation, all rights reserved.


Parallel Sequences

class my_test extends uvm_test;



init_seq iseq;
exec_seq eseq; exec_seq init_seq
...
task run_phase(uvm_phase phase);
iseq = init_seq::type_id::create(“iseq”);
eseq = exec_seq::type_id::create(“eseq”);
phase.raise_objection(this);
fork
iseq.start( my_env_h.my_agent_h.my_sequencer_h );
eseq.start( my_env.h.my_agent_h.my_sequencer_h );
join
… Don’t use fork-join_none
phase.drop_objection(this);
endtask
endclass

© 2013 Mentor Graphics Corporation, all rights reserved.


Parallel Sequences

class my_test extends uvm_test;



init_seq iseq;
exec_seq eseq; exec_seq init_seq
...
task run_phase(uvm_phase phase);
iseq = init_seq::type_id::create(“iseq”);
eseq = exec_seq::type_id::create(“eseq”);
phase.raise_objection(this);
fork
iseq.start( my_agent_h.my_sequencer_h, this, HIGH );
eseq.start( my_agent_h.my_sequencer_h, this, LOW );
join

phase.drop_objection(this);
endtask
Optional
endclass
priority

© 2013 Mentor Graphics Corporation, all rights reserved.


Hierarchical Sequences

test_seq
init_seq

exec_seq

© 2013 Mentor Graphics Corporation, all rights reserved.


Hierarchical Sequences

class test_seq extends uvm_sequence #(req,rsp);


`uvm_object_utils(test_seq)
init_seq iseq; test_seq
exec_seq eseq; init_seq

task body();
iseq = init_seq::type_id::create(“iseq”);


endtask
endclass

© 2013 Mentor Graphics Corporation, all rights reserved.


Hierarchical Sequences

class test_seq extends uvm_sequence #(req,rsp);


`uvm_object_utils(test_seq)
init_seq iseq; test_seq
exec_seq eseq; init_seq

task body();
iseq = init_seq::type_id::create(“iseq”);

iseq.start( m_sequencer, this );


endtask
endclass

© 2013 Mentor Graphics Corporation, all rights reserved.


Hierarchical Sequences

class test_seq extends uvm_sequence #(req,rsp);


`uvm_object_utils(test_seq)
init_seq iseq; test_seq
exec_seq eseq; init_seq

task body();
iseq = init_seq::type_id::create(“iseq”);

iseq.start( m_sequencer, this );


endtask Run on test_seq’s
endclass sequencer

© 2013 Mentor Graphics Corporation, all rights reserved.


Hierarchical Sequences

class test_seq extends uvm_sequence #(req,rsp);


`uvm_object_utils(test_seq)
init_seq iseq; test_seq
exec_seq eseq; init_seq

task body();
iseq = init_seq::type_id::create(“iseq”);

iseq.start( m_sequencer, this );


endtask Optional parent
endclass sequence specifier

© 2013 Mentor Graphics Corporation, all rights reserved.


Hierarchical Sequences

class test_seq extends uvm_sequence #(req,rsp);


`uvm_object_utils(test_seq)
init_seq iseq; test_seq
exec_seq eseq; init_seq

task body();
iseq = init_seq::type_id::create(“iseq”);
exec_seq
eseq = exec_seq::type_id::create(“eseq”);
iseq.start( m_sequencer, this );


endtask
endclass

© 2013 Mentor Graphics Corporation, all rights reserved.


Hierarchical Sequences

class test_seq extends uvm_sequence #(req,rsp);


`uvm_object_utils(test_seq)
init_seq iseq; test_seq
exec_seq eseq; init_seq

task body();
iseq = init_seq::type_id::create(“iseq”);
exec_seq
eseq = exec_seq::type_id::create(“eseq”);
iseq.start( m_sequencer, this );
eseq.start( m_sequencer, this );

endtask
endclass

“top.env.agent.sequencer.test_seq.eseq”

© 2013 Mentor Graphics Corporation, all rights reserved.


Pipelined Driver
class mbus_pipelined_driver extends uvm_driver #(mbus_seq_item);
`uvm_component_utils(mbus_pipelined_driver)

virtual mbus_if MBUS;

function new(string name = "mbus_pipelined_driver", uvm_component parent = null);


super.new(name, parent);
endfunction

task run_phase(uvm_phase phase);


@(posedge MBUS.MRESETN);
@(posedge MBUS.MCLK);
fork
do_pipelined_transfer;
do_pipelined_transfer;
join
endtask
task do_pipelined_transfer;
endtask
endclass
© 2013 Mentor Graphics Corporation, all rights reserved.
Pipelined Driver
class mbus_pipelined_driver extends uvm_driver #(mbus_seq_item);
`uvm_component_utils(mbus_pipelined_driver)

virtual mbus_if MBUS;

task do_pipelined_transfer;
mbus_seq_item req,rsp;

forever begin
pipeline_lock.get();
seq_item_port.get(req);
do_command_phase(req);
pipeline_lock.put();
do_data_phase(req,rsp);
seq_item_port.put(rsp);
end
endtask
endclass
© 2013 Mentor Graphics Corporation, all rights reserved.
Summary: General Rules
• Make sure to parameterize sequence/sequencer/driver with
the same request and response types
• Start sequences using seq.start(sequencer)
• Use seq_item_port.get_next_item/item_done in the driver
• Use try_next_item/item_done if driver must perform idle cycles
• Use get/put for pipelined drivers
• Use uvm_config_db#()::get() to configure sequences
• Sequence and Driver must agree on response path, if any

© 2013 Mentor Graphics Corporation, all rights reserved.


Advanced UVM
The Proper Care and Feeding of Sequences

Tom Fitzpatrick
Verification Evangelist

[email protected] | www.verificationacademy.com

You might also like