UVM糖果爱好者教程 - 4.代理
2018-03-19 16:00
841 查看
上一篇文章集中讨论了 jelly-bean系统的transaction和sequence。本文将深入解释验证环境中的验证组件。
interface
在这一部分,将提供接口(jelly_bean_if)的一般解释及其绑定验证组件和jelly-bean(DUT)的作用。
下图显示了jelly_bean_if的内容。实质上,jelly_bean_if已包含从jelly_bean_transaction中的属性转换而来的信号。interface jelly_bean_if(input bit clk);
logic [2:0] flavor;
logic [1:0] color;
logic sugar_free;
logic sour;
logic [1:0] taste;
clocking master_cb @ (posedge clk);
default input #1step output #1ns;
output flavor, color, sugar_free, sour;
input taste;
endclocking: master_cb
clocking slave_cb @ (posedge clk);
default input #1step output #1ns;
input flavor, color, sugar_free, sour;
output taste;
endclocking: slave_cb
modport master_mp(input clk, taste, output flavor, color, sugar_free, sour);
modport slave_mp(input clk, flavor, color, sugar_free, sour, output taste);
modport master_sync_mp(clocking master_cb);
modport slave_sync_mp(clocking slave_cb);
endinterface: jelly_bean_if各个信号的时序由时钟块定义。 master_cb从总线master的角度定义时序,而slave_cb从总线slave的角度定义时序。
该接口还有modport列表,它定义了接口内信号的方向。我们定义了四个modport列表:
DUT使用异步modport列表(master_mp和slave_mp),而testbench使用同步modport列表(master_sync_mp和slave_sync_mp)。
更新(2014年4月2日):我们注意到有些仿真器不支持#1步骤(第9和15行)。如果是这种情况,您可以将其更改为#1ns。
import jelly_bean_pkg::*;
always @ ( posedge jb_slave_if.clk ) begin
if ( jb_slave_if.flavor == jelly_bean_transaction::CHOCOLATE &&
jb_slave_if.sour ) begin
jb_slave_if.taste <= jelly_bean_transaction::YUCKY;
end else begin
jb_slave_if.taste <= jelly_bean_transaction::YUMMY;
end
end
endmodule: jelly_bean_taster或者,您可以在模块实例的端口连接中指定modport列表。module jelly_bean_taster( jelly_bean_if jb_slave_if ); // no modport specified
// ...
endmodule
module top;
reg clk;
jelly_bean_if jb_slave_if( clk );
jelly_bean_taster jb_taster( jb_slave_if.slave_mp ); // modport specified
// ...
endmodule您可以在模块声明和模块实例中指定modport列表,但如果您这样做,它们必须相同。如果完全没有指定modport列表,则接口中的信号被假定为无法访问。
更新(2014年4月2日):在本教程中,我们使用uvm_resource_db来检索jelly_bean_if(第12和13行)。 UVM建议使用uvm_config_db而不是uvm_resource_db,因为前者更健壮。您可以用下列内容替换第12行和第13行:assert( uvm_config_db#( virtual jelly_bean_if )::
get( .cntxt( this ), .inst_name( "" ), .field_name( "jelly_bean_if" ), .value( jb_vi ) ) );
更新(2014年4月2日):我们使用uvm_resource_db来检索jelly_bean_if(第14行和第15行)。有关如何使用uvm_config_db而不是uvm_resource_db,请参阅上一节。
class jelly_bean_monitor extends uvm_monitor;
`uvm_component_utils(jelly_bean_monitor)
uvm_analysis_port#(jelly_bean_transaction) jb_ap;
virtual jelly_bean_if jb_vi;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_resource_db#(virtual jelly_bean_if)::read_by_name
(.scope("ifs"), .name("jelly_bean_if"), .val(jb_vi)));
jb_ap = new(.name("jb_ap"), .parent(this));
en
4000
dfunction: build_phase
task run_phase(uvm_phase phase);
forever begin
jelly_bean_transaction jb_tx;
@jb_vi.slave_cb;
if (jb_vi.slave_cb.flavor != jelly_bean_transaction::NO_FLAVOR) begin
jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
jb_tx.flavor = jelly_bean_transaction::flavor_e'(jb_vi.slave_cb.flavor);
jb_tx.color = jelly_bean_transaction::color_e'(jb_vi.slave_cb.color);
jb_tx.sugar_free = jb_vi.slave_cb.sugar_free;
jb_tx.sour = jb_vi.slave_cb.sour;
@jb_vi.master_cb;
jb_tx.taste = jelly_bean_transaction::taste_e'(jb_vi.master_cb.taste);
jb_ap.write(jb_tx);
end
end
endtask: run_phase
endclass: jelly_bean_monitor
class jelly_bean_agent extends uvm_agent;
`uvm_component_utils(jelly_bean_agent)
uvm_analysis_port#(jelly_bean_transaction) jb_ap;
jelly_bean_sequencer jb_seqr;
jelly_bean_driver jb_drvr;
jelly_bean_monitor jb_mon;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
jb_ap = new(.name("jb_ap"), .parent(this));
jb_seqr = jelly_bean_sequencer::type_id::create(.name("jb_seqr"), .parent(this));
jb_drvr = jelly_bean_driver::type_id::create(.name("jb_drvr"), .parent(this));
jb_mon = jelly_bean_monitor::type_id::create(.name("jb_mon"), .parent(this));
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
jb_drvr.seq_item_port.connect(jb_seqr.seq_item_export);
jb_mon.jb_ap.connect(jb_ap);
endfunction: connect_phase
endclass: jelly_bean_agent虽然这篇文章到这里就结束,但下一篇将继续介绍其他验证组件。
interface
在这一部分,将提供接口(jelly_bean_if)的一般解释及其绑定验证组件和jelly-bean(DUT)的作用。下图显示了jelly_bean_if的内容。实质上,jelly_bean_if已包含从jelly_bean_transaction中的属性转换而来的信号。interface jelly_bean_if(input bit clk);
logic [2:0] flavor;
logic [1:0] color;
logic sugar_free;
logic sour;
logic [1:0] taste;
clocking master_cb @ (posedge clk);
default input #1step output #1ns;
output flavor, color, sugar_free, sour;
input taste;
endclocking: master_cb
clocking slave_cb @ (posedge clk);
default input #1step output #1ns;
input flavor, color, sugar_free, sour;
output taste;
endclocking: slave_cb
modport master_mp(input clk, taste, output flavor, color, sugar_free, sour);
modport slave_mp(input clk, flavor, color, sugar_free, sour, output taste);
modport master_sync_mp(clocking master_cb);
modport slave_sync_mp(clocking slave_cb);
endinterface: jelly_bean_if各个信号的时序由时钟块定义。 master_cb从总线master的角度定义时序,而slave_cb从总线slave的角度定义时序。
该接口还有modport列表,它定义了接口内信号的方向。我们定义了四个modport列表:
DUT使用异步modport列表(master_mp和slave_mp),而testbench使用同步modport列表(master_sync_mp和slave_sync_mp)。
更新(2014年4月2日):我们注意到有些仿真器不支持#1步骤(第9和15行)。如果是这种情况,您可以将其更改为#1ns。
DUT
下面的代码显示了jelly_bean_taster的一个简单结构。第1行指定了我们刚刚定义的jelly_bean_if,以及slave_mp为接口信号选择适当的方向信息。品尝师只会对酸味巧克力口味产生负面影响(即有酸味的巧克力)!module jelly_bean_taster( jelly_bean_if.slave_mp jb_slave_if );import jelly_bean_pkg::*;
always @ ( posedge jb_slave_if.clk ) begin
if ( jb_slave_if.flavor == jelly_bean_transaction::CHOCOLATE &&
jb_slave_if.sour ) begin
jb_slave_if.taste <= jelly_bean_transaction::YUCKY;
end else begin
jb_slave_if.taste <= jelly_bean_transaction::YUMMY;
end
end
endmodule: jelly_bean_taster或者,您可以在模块实例的端口连接中指定modport列表。module jelly_bean_taster( jelly_bean_if jb_slave_if ); // no modport specified
// ...
endmodule
module top;
reg clk;
jelly_bean_if jb_slave_if( clk );
jelly_bean_taster jb_taster( jb_slave_if.slave_mp ); // modport specified
// ...
endmodule您可以在模块声明和模块实例中指定modport列表,但如果您这样做,它们必须相同。如果完全没有指定modport列表,则接口中的信号被假定为无法访问。
Sequencer
jelly-bean sequence由sequencer处理。 uvm_sequencer按原样使用,因为 jelly-bean sequencer不涉及任何类型的扩展功能。typedef uvm_sequencer#(jelly_bean_transaction) jelly_bean_sequencer;Driver
driver通过22行中的seq_item_port接收jelly_bean_transaction,然后驱动interface上的信号。driver使用driver和DUT之间的interface来驱动信号。该interface存储在uvm_resource_db(第12行)中。更新(2014年4月2日):在本教程中,我们使用uvm_resource_db来检索jelly_bean_if(第12和13行)。 UVM建议使用uvm_config_db而不是uvm_resource_db,因为前者更健壮。您可以用下列内容替换第12行和第13行:assert( uvm_config_db#( virtual jelly_bean_if )::
get( .cntxt( this ), .inst_name( "" ), .field_name( "jelly_bean_if" ), .value( jb_vi ) ) );
class jelly_bean_driver extends uvm_driver#(jelly_bean_transaction); `uvm_component_utils(jelly_bean_driver) virtual jelly_bean_if jb_vi; function new(string name, uvm_component parent); super.new(name, parent); endfunction: new function void build_phase(uvm_phase phase); super.build_phase(phase); void'(uvm_resource_db#(virtual jelly_bean_if)::read_by_name (.scope("ifs"), .name("jelly_bean_if"), .val(jb_vi))); endfunction: build_phase task run_phase(uvm_phase phase); jelly_bean_transaction jb_tx; forever begin @jb_vi.master_cb; jb_vi.master_cb.flavor <= jelly_bean_transaction::NO_FLAVOR; seq_item_port.get_next_item(jb_tx); @jb_vi.master_cb; jb_vi.master_cb.flavor <= jb_tx.flavor; jb_vi.master_cb.color <= jb_tx.color; jb_vi.master_cb.sugar_free <= jb_tx.sugar_free; jb_vi.master_cb.sour <= jb_tx.sour; seq_item_port.item_done(); end endtask: run_phase endclass: jelly_bean_driver第20和23是所谓的时钟块事件。它们相当于@(posedge jb_vi.clk)
Monitor
monitor中的数据流向与driver中相反,但与驱动程序类似。 DUT的interface(jelly_bean_if)位于uvm_resource_db(第14行)。monitor密切监视jelly_bean_if,并获取信号的值。我们的monitor监视一个非NO_FLAVOR果冻豆(第23行)并创建一个jelly_bean_transaction(第24行)。创建的transaction通过analysis port发送给31行的用户。更新(2014年4月2日):我们使用uvm_resource_db来检索jelly_bean_if(第14行和第15行)。有关如何使用uvm_config_db而不是uvm_resource_db,请参阅上一节。
class jelly_bean_monitor extends uvm_monitor;
`uvm_component_utils(jelly_bean_monitor)
uvm_analysis_port#(jelly_bean_transaction) jb_ap;
virtual jelly_bean_if jb_vi;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
void'(uvm_resource_db#(virtual jelly_bean_if)::read_by_name
(.scope("ifs"), .name("jelly_bean_if"), .val(jb_vi)));
jb_ap = new(.name("jb_ap"), .parent(this));
en
4000
dfunction: build_phase
task run_phase(uvm_phase phase);
forever begin
jelly_bean_transaction jb_tx;
@jb_vi.slave_cb;
if (jb_vi.slave_cb.flavor != jelly_bean_transaction::NO_FLAVOR) begin
jb_tx = jelly_bean_transaction::type_id::create(.name("jb_tx"), .contxt(get_full_name()));
jb_tx.flavor = jelly_bean_transaction::flavor_e'(jb_vi.slave_cb.flavor);
jb_tx.color = jelly_bean_transaction::color_e'(jb_vi.slave_cb.color);
jb_tx.sugar_free = jb_vi.slave_cb.sugar_free;
jb_tx.sour = jb_vi.slave_cb.sour;
@jb_vi.master_cb;
jb_tx.taste = jelly_bean_transaction::taste_e'(jb_vi.master_cb.taste);
jb_ap.write(jb_tx);
end
end
endtask: run_phase
endclass: jelly_bean_monitor
Agent
sequencer,driver,monitor - 全部例化在在agent中。这些组件在build_phase中创建,创建的组件在connect_phase中连接。由于subscriber没有例化在agent,但是monitor要向subscriber发送trans,所以创建analysis port以与subscriber进行通信。agent和monitor中的analysis port在26行相互连接。然后,agent中的analysis port又和subscriber中的analysis imp在env中连接。class jelly_bean_agent extends uvm_agent;
`uvm_component_utils(jelly_bean_agent)
uvm_analysis_port#(jelly_bean_transaction) jb_ap;
jelly_bean_sequencer jb_seqr;
jelly_bean_driver jb_drvr;
jelly_bean_monitor jb_mon;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction: new
function void build_phase(uvm_phase phase);
super.build_phase(phase);
jb_ap = new(.name("jb_ap"), .parent(this));
jb_seqr = jelly_bean_sequencer::type_id::create(.name("jb_seqr"), .parent(this));
jb_drvr = jelly_bean_driver::type_id::create(.name("jb_drvr"), .parent(this));
jb_mon = jelly_bean_monitor::type_id::create(.name("jb_mon"), .parent(this));
endfunction: build_phase
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
jb_drvr.seq_item_port.connect(jb_seqr.seq_item_export);
jb_mon.jb_ap.connect(jb_ap);
endfunction: connect_phase
endclass: jelly_bean_agent虽然这篇文章到这里就结束,但下一篇将继续介绍其他验证组件。
相关文章推荐
- UVM糖果爱好者教程 - 7.虚拟序列
- UVM糖果爱好者教程 - 3.传输和序列
- UVM糖果爱好者教程 - 5.环境
- UVM糖果爱好者教程 - 1.概述
- UVM糖果爱好者教程 - 6.品尝
- UVM糖果爱好者教程 - 2.食谱
- 在IIS7中应用Application Request Routing配置反向代理的图文教程
- 利用nginx+lua+redis实现反向代理方法教程
- 安卓手机通过 Fiddler代理上网教程,抓包
- 主机运行代理软件, 虚拟机中下载android源码的教程
- 为MySQL安装配置代理工具Kingshard的基本教程
- iOS开发之OC与swift开发混编教程,代理的相互调用,block的实现。OC调用Swift中的代理, OC调用Swift中的Block 闭包,swift 3.0
- Java动态代理之InvocationHandler最简单的入门教程
- nginx教程第八篇:用HTTP proxy module配置一个反向代理服务器
- qq代理服务器设置教程
- 静态代理模式-马士兵设计模式教程
- 亚马逊aws代理教程
- sap ui5教程(7)配置代理服务、使用mock server模拟oData提供者
- 『CMP你我它』之php篇:php代码列表代理在CMP里的使用教程
- Python-Scrapy 个人兴趣教程(二):没错,从代理IP开始