UVM Sequence总结
作者:互联网
一个sequence生成一系列的sequence_item,并通过sequencer发送给驱动程序,Sequence是通过扩展uvm_sequence来编写的。
uvm_sequence 派生自 uvm_sequence_item
sequence用 sequence_item 的类型参数化,这定义了和 driver 之间 发送/接收的 sequence_item 的类型。
sequence base class
virtual class uvm_sequence #( type REQ = uvm_sequence_item, type RSP = REQ ) extends uvm_sequence_base
example:
class write_sequence extends uvm_sequence #(mem_seq_item);
....
....
endclass
该writ_sequence具有 mem_seq_item 的句柄 req 和 rsp。
request/req:
提供信息来启动特定操作的事务。
response/rsp:
提供有关特定操作的完成信息或状态信息的事务。
Sequence执行
sequence最重要的属性是:
- body method
- m_sequencer handle
body Method:
body 方法定义了这个sequence做什么事情。
m_sequencer Handle:
m_sequencer 句柄包含对运行 sequence 的 sequencer 的引用。
该 sequence 将在从 test 中调用 sequence 的 start 时开始执行。
sequence_name.start(sequencer_name);
sequencer_name 指定 sequence 必须在哪个 sequencer 上运行。
有与 uvm_sequence 相关的 Methods, macros and pre-defined callbacks(方法、宏和预定义的回调)。
用户可以将方法(任务或函数)定义为预定义的回调。这些方法将在调用序列 start 时自动执行。
这些方法不应由用户直接调用。
下面的框图显示了调用sequence start时调用方法的顺序。
注意:* mid_do 和 post_do 是函数,其他都是任务
Starting The Sequence:
生成和发送 sequence_item 的逻辑将写入sequence的 body() 方法中。
发送 sequence_item 的sequence、sequencer和driver之间的握手如下所示。
sequence和driver之间的通信涉及以下步骤,
1.create_item() / create req.
2.wait_for_grant().
3.randomize the req.
4.send the req.
5.wait for item done.
6.get response.
* 步骤 5 和 6 是可选的。
Method Call | Description |
---|---|
create_item() req = **_seq_item::type_id::create(“req”); |
创建和初始化*一个 sequence_item 或sequence *initialize - 初始化以与指定的sequencer通信 |
wait_for_grant() |
这个方法调用是阻塞的,执行会一直阻塞,直到方法返回。 1.此方法向当前 sequencer 发出请求 2.sequencer 授予从 driver 获取的 get_next_item() request |
req.randomize() | 这个方法是随机化sequence_item |
send_request(req,re-randomize) re-randomize = 0 or re-randomize = 1; |
将request item 发送到sequencer,sequencer会将其转发给driver。如果设置了重新随机化位,则item将在发送给driver之前被随机化。 |
wait_for_item_done() | 此调用是可选的。此任务将阻塞,直到 driver 调用 item_done 或 put。 |
get_current_item() | 返回当前由 sequencer 执行的请求项。 如果sequencer当前未执行项目,则此方法将返回 null。 |
get_response(rsp) | 收到 driver 的回复。 |
编写 UVM sequence
class mem_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(mem_sequence)
//Constructor
function new(string name = "mem_sequence");
super.new(name);
endfunction
virtual task body();
req = mem_seq_item::type_id::create("req"); //create the req (seq item)
wait_for_grant(); //wait for grant
assert(req.randomize()); //randomize the req
send_request(req); //send req to driver
wait_for_item_done(); //wait for item done from driver
get_response(rsp); //get response from driver
endtask
endclass
UVM Sequence 宏
这些宏用于在默认sequencer,m_sequencer 上start sequence和sequence item。
Macro | Description |
---|---|
`uvm_do(Item/Seq) | 此宏将 seq_item 或sequence作为参数。 在调用 `uvm_do() 时,将执行上面定义的 6 个步骤。 |
`uvm_create(Item/Seq) | 此宏创建 item or sequence. |
`uvm_send(Item/Seq) | create() 和 randomize() 被跳过,其余所有步骤都被执行。 |
`uvm_rand_send(Item/Seq) | 只有 create() 被跳过,其余所有步骤都被执行。 |
`uvm_do_with(Item/Seq,Constraints) | 该宏执行上述 6 个步骤以及第二个参数中定义的约束。 |
`uvm_rand_send_with(Item/Seq,Constraints) | create() 被跳过,其余所有步骤与第二个参数中定义的约束一起执行。 |
`uvm_do_pri(Item/Seq,Priority ) | 以提到的优先级执行`uvm_do()。 |
`uvm_do_pri_with(Item/Seq,Constraints,Priority) | 执行 `uvm_do() 以及定义的约束和提到的优先级。 |
`uvm_send_pri(Item/Seq,Priority) | create() 和 randomize() 被跳过,其余所有其他步骤都以提到的优先级执行。 |
`uvm_rand_send_pri(Item/Seq,Priority) | 只有 create() 被跳过,其余所有其他步骤都以提到的优先级执行。 |
`uvm_rand_send_pri_with(Item/Seq,Priority, Constraints) | 只有 create() 被跳过,其余所有其他步骤与 create() 一起被跳过,其余所有其他步骤与定义的优先级约束一起执行。 |
`uvm_declare_p_sequencer(SEQUENCER) | 该宏用于声明一个变量 p_sequencer,其类型由 SEQUENCER 指定。通过使用 p_sequencer 句柄,可以访问 sequencer 的属性。 |
使用宏编写sequence
`UVM_DO()
class mem_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(mem_sequence)
//Constructor
function new(string name = "mem_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_do(req)
endtask
endclass
`UVM_CREATE() AND `UVM_SEND()
class mem_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(mem_sequence)
//Constructor
function new(string name = "mem_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_create(req)
assert(req.randomize());
`uvm_send(req);
endtask
endclass
`UVM_RAND_SEND()
class mem_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(mem_sequence)
//Constructor
function new(string name = "mem_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_create(req)
`uvm_rand_send(req)
endtask
endclass
`UVM_DO_WITH()
class write_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(write_sequence)
//Constructor
function new(string name = "write_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_do_with(req,{req.wr_en == 1;})
endtask
endclass
`UVM_RAND_SEND_WITH()
class read_sequence extends uvm_sequence#(mem_seq_item);
`uvm_object_utils(read_sequence)
//Constructor
function new(string name = "read_sequence");
super.new(name);
endfunction
virtual task body();
`uvm_create(req)
`uvm_rand_send_with(req,{req.rd_en == 1;})
endtask
CALLING SEQUENCE’S INSIDE THE SEQUENCE
class wr_rd_seq extends uvm_sequence#(mem_seq_item);
write_sequence wr_seq;
read_sequence rd_seq;
`uvm_object_utils(wr_rd_seq)
//Constructor
function new(string name = "wr_rd_seq");
super.new(name);
endfunction
virtual task body();
`uvm_do(wr_seq)
`uvm_do(rd_seq)
endtask
endclass
m_sequencer 和 p_sequencer 的区别:
m_sequencer,
m_sequencer 句柄包含对运行sequence 的sequencer(默认sequencer)的引用。
这是由,
start 方法中提供的sequencer句柄
parent sequence 使用的sequencer
使用 set_sequencer 方法设置的sequencer
p_sequencer,
p_sequencer 是一个变量,用作访问 sequencer 属性的句柄。
p_sequencer 是使用宏定义的 : `uvm_declare_p_sequencer(SEQUENCER_NAME)
标签:总结,req,sequence,mem,Sequence,item,uvm,sequencer,UVM 来源: https://www.cnblogs.com/fuqiangblog/p/16683750.html