Vous êtes sur la page 1sur 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


Simplify test writer API
u1

Sequences define
transaction streams

May start on any sequencer

Sequences can call children


Sequences & transactions customizable
via the factory

u1
s1

s5

s3
s2
s4

2013 Mentor Graphics Corporation, all rights reserved.

Review: Sequence Basics


class my_seq extends uvm_sequence #(req_t);
`uvm_object_utils(uvm_seq)
req_t req;
int num = 10;

Transaction type
Default name in
constructor

function new(string name = my_seq);


super.new(name);
endfunction
task body();
uvm_config_db#(int)::get(this, , num, num);
Create request
req = req_t::type_id::create(req);
for_int i = 0; i < num; i++) begin
Initiate Driver Handshake
start_item(req);
Late Randomization
if(!req.randomize()) begin
Note: begin-end around
`uvm_error(body, rand failure)
`uvm_<msg>
end
finish_item(req);
Send transaction
end
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;
Dont need to declare a
new sequencer type

2013 Mentor Graphics Corporation, all rights reserved.

Review: Sequence/Driver Handshake


my_seq1
start_item(req);

driver
get_next_item(req);

finish_item(req);
item_done();

task body();
task run_phase(uvm_phase phase);
req = req_t::type_id::create(req);
forever begin
for_int i = 0; i < num; i++) begin
seq_item_port.get_next_item(req);
start_item(req);
drive_item2bus(req);
if(!req.randomize()) begin
seq_item_port.item_done();
`uvm_error(body, rand failure)
end
end
endtask
finish_item(req);
`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
start_item(req);

driver
get_next_item(req);

finish_item(req);
item_done();
get_response(rsp);
task body();
req = req_t::type_id::create(req);
for_int i = 0; i < num; i++) begin
start_item(req);
if(!req.randomize()) begin
`uvm_error(body, rand failure)
end
finish_item(req);
get_response(rsp);
end
endtask

put_response(rsp);
task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req);
drive_item2bus(req,rsp);
seq_item_port.item_done();
rsp.set_id_info(req);
seq_item_port.put_response(rsp);
end
If driver provides separate
endtask
response object
2013 Mentor Graphics Corporation, all rights reserved.

Arbitration and Responses in the Sequencer


class myseq;
virtual task body();

finish_item(req)
get_response(rsp);
get_response(rsp,id);
endtask
s1
endclass

Both
sequences
now waiting
for responses

Sequence-specific
Sequencer
class req;
seq_id = 1;
2;
trans_id = 1;

arbitrate
requests

Driver
1,1
2,1

s2

Sequencer uses
sequence_id to route
response to
originating sequence

Unique within sequence

route
responses
rsp

rsp
1,1 = 1;
seq_id
trans_id = 1;

seq_idset_id_info()
= 1;
copies id
trans_idfields
= 1; from req to rsp

class driver;
task run();

rsp.set_id_info(req);
seq_item_port.put_response(rsp);
endtask
endclass
2013 Mentor Graphics Corporation, all rights reserved.

Arbitration and Responses in the Sequencer


class myseq;
virtual task body();
use_response_handler(1);
finish_item(req)
get_response(rsp,id);
endtask

Customize the response handler as necessary

virtual function void response_handler(uvm_sequence_item response);

endfunction
endclass

SEQ_ARB_FIFO
SEQ_ARB_WEIGHTED
SEQ_ARB_RANDOM
SEQ_ARB_STRICT_FIFO
SEQ_ARB_STRICT_RANDOM
SEQ_ARB_USER

sequencer.set_arbitration(SEQ_ARB_USER);
class my_sequencer extends uvm_sequencer(REQ);
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)
my_agent my_agent_h;
...

Factory enables test to


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;
...
task run_phase(uvm_phase phase);
iseq = init_seq::type_id::create(iseq);
eseq = exec_seq::type_id::create(eseq);
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 );

phase.drop_objection(this);
endtask
endclass

init_seq

exec_seq

start() is blocking

2013 Mentor Graphics Corporation, all rights reserved.

Parallel Sequences
class my_test extends uvm_test;

init_seq iseq;
exec_seq
exec_seq eseq;
...
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
Dont use fork-join_none

phase.drop_objection(this);
endtask
endclass

init_seq

2013 Mentor Graphics Corporation, all rights reserved.

Parallel Sequences
class my_test extends uvm_test;

init_seq iseq;
exec_seq
exec_seq eseq;
...
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

init_seq

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;
exec_seq eseq;

test_seq

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;
exec_seq eseq;

test_seq

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;
exec_seq eseq;

test_seq

init_seq

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

endtask
endclass

Run on test_seqs
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;
exec_seq eseq;

test_seq

init_seq

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

endtask
endclass

Optional parent
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;
exec_seq eseq;
task body();
iseq = init_seq::type_id::create(iseq);
eseq = exec_seq::type_id::create(eseq);
iseq.start( m_sequencer, this );

test_seq

init_seq

exec_seq

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;
exec_seq eseq;

test_seq

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

endtask
endclass

init_seq

exec_seq

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

Vous aimerez peut-être aussi