Sie sind auf Seite 1von 27

Advanced UVM

The Proper Care and Feeding of Sequences

Tom Fitzpatrick
Verification Evangelist

info@verificationacademy.com | 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

info@verificationacademy.com | www.verificationacademy.com

Das könnte Ihnen auch gefallen