2021-03-23 UVM简单平台的构成与搭建
程序员文章站
2022-07-04 20:05:18
...
文章目录
创建一个简单UVM平台:
UVM平台的主要组件:
结构组件
- uvm_component
- uvm_test;
- uvm_env;
- uvm_scoreboard;
- uvm_agent;
- uvm_sequence;
- uvm_monitor;
- uvm_driver
组件之间的通信
-
- uvm_*_port;
- uvm_*_inmport;
- uvm_*_export;
- uvm_*_fifo_*;
- uvm_*_socket;
事务
-
- uvm_sequence_item;
- uvm_sequence;
1. 创建transaction
//从uvm_sequence_item库中创建自定义my_transaction类
class my_transaction extends uvm_sequence_item;
//为激励成员指定rand属性,随机化
rand bit [3:0] sa;
rand bit [3:0] da;
rand reg [7:0] payload[$];
//将自定义事务类在uvm中注册
`uvm_object_utils_begin(transaction)
`uvm_field_int(sa,UVM_ALL_ON);
...
`uvm_object_utils_end
//约束项,控制随机成员的随机范围
constraint Limit{
sa inside {[0:15]};
da inside {[0:15]};
payload.size() inside {[2:4]};
}
//构造函数new
function new (string name = "my_transaction");
super.new(name);
endfunction
endclass
2. 创建sequence
- 产生事务对象,并控制;
- 一般一种sequence 产生一种类型事务,产生多种类型事务很少见;
//使用参数化类扩展uvm_sequence库产生自定义my_sequence类
class my_sequence extends uvm_sequnence #(my_transaction);
//将自定义my_seuence类在uvm库中注册
`uvm_object_utils(my_sequence)
//创建构造函数new
function new(string name = "my_sequence");
super.new(name);
endfunction
//最重要的的body()函数,产生和控制事务;
virtual task body();
//raise标志开始产生事务
if (starting_phase != null )
starting_phase.raise_pbjection;
//产生事务10次,req是产生事务对象的指针
repeat(10)
//uvm库中宏uvm_do,开始产生事务
`uvm_do(req)
//drop标志事务产生结束
if (starting_phase != null )
starting_phase.drop_objection;
endtask
endclass
3. 创建sequencer
- sequence和sequence_item并不属于结构的一部分他们是组件中流动的数据流;
- sequencer的作用:
- 启动sequence;
- 将sequence产生的事务对象item发送到uvm的组件中(也就是driver);
//使用typedef在uvm_sequencer下定义需要传递my_transaction的my_sequencer;
typedef uvm_sequencer #(my_transaction) my_sequencer;
4. 创建driver
- 从sequencer中获取transaction;
- 将transaction分解为DUT可以接受的pin级信号;
- 将转化后的pin级信号按照DUT总线协议的方式驱动给DUT;
所有的平台组件都使用`uvm_component_utils进行注册,其他的使用uvm_object_utils注册
//创建自定义my_driver
class my_driver entends uvm_driver #(my_transaction);
//注册
`uvm_component_utils(my_driver)
//构造new函数,并指定父对象
function new(string name = "my_sequence",uvm_component parent);
super.new(name,parent);
endfunction
//实现driver的功能
virtual task run_phase(uvm_phase phase);
//driver是不停工作的
forever begin
//从sequencer获取transaction,req指向my_transaction
seq_item_port.get_next_item(req);
//执行一个简单的打印操作
`uvm_info("DRV_RUN_PHASE",req_sprint(),UVM_MEDIUM)
#100;
//通知sequencer事务处理完毕
seq_item_port.item_done();
end
endtask
endclass
5. 创建monitor
- 监视接口信号,捕获接口上活动的事务,并且将pin级的信号事务转化为事务级的数据包,之后将这些数据包发送的analysis组件(scoreboard,reference model等)进行分析和产生报告。
- 通过TLM-port机制与其他组件通信。
//创建自定义my_monitor
class my_monitor entends uvm_monitor;
//注册
`uvm_component_utils(my_monitor)
//构造new函数,并指定父对象
function new(string name = "",uvm_component parent);
super.new(name,parent);
endfunction
//完成monitor操作
virtual task run_phase(uvm_phase phase);
//driver是不停工作的
forever begin
//执行一个简单的打印操作
`uvm_info("MON_RUN_PHASE","MONITOR RUN!",UVM_MEDIUM)
#100;
end
endtask
endclass
6. 创建agent
- agent封装了sequenncer、driver、monitor;
- agent需要实例化封装对象并将其连接起来;
- agent有passive(只包含monitor,而没有driver 和 sequencer,没有驱动DUT的能力)和active;
//创建自定义master_agent
class master_agent entends uvm_agent;
//注册
`uvm_component_utils(master_agent)
//例化封装对象,产生句柄
my_sequencer m_seqr;
my_driver m_driv;
my_monitor m_moni
//构造new函数,并指定父对象
function new(string name = "",uvm_component parent);
super.new(name,parent);
endfunction
//完成monitor操作
virtual function void run_phase(uvm_phase phase);
//进入buildphase
super.build_phase(phase);
//当为active模式才创建sequencer和driver的对象,is_active默认为UVM_ACTIVE
if(is_active == UVM_ACTIVE) begin
//使用uvm的工厂机制创建对象,类型名::类型名的静态成员::类型名静态成员的静态函数
my_seqr = my_sequencer::type_id::create("m_seqr",this);
my_driv = my_driver :: type_id::create("m_driv",this);
end
//不管是不是active模式,monitor的对象都应该被创建
m_moni = monitor::type_id::create("m_moni",this);
//重载connect_phase
virtual function void connect_phase(uvm_phase phase);
if(is_active == UVM_ACTIVE)
//使用TLM机制,连接sequencer与driver
m_driv.seq_item_port.connect.(m_seqr.seq_item_export);
endfunction
endtask
7. 创建environment
- environment封装、例化agent、reference module、scoreboard,并将其连接;
- 监视接口信号,捕获接口上活动的事务,并且将pin级的信号事务转化为事务级的数据包,之后将这些数据包发送的analysis组件(scoreboard,reference model等)进行分析和产生报告。
- 通过TLM-port机制与其他组件通信。
//创建自定义my_env
class my_env entends uvm_environment;
//注册
`uvm_component_utils(my_env)
//实例化master_agent
master_agent my_agent;
//构造new函数,并指定父对象
function new(string name = "",uvm_component parent);
super.new(name,parent);
endfunction
//重载build_phase
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
//使用工厂机制创建agent对象
m_agent = master_agent::type_id::create("m_agent",this);
endfunction
endclass
//只例化了agent,monitor,reference module没有被例化
8. 创建testcase
- 实例化和配置env;
- 需要指定要启动的sequence;
//创建自定义my_test
class my_test entends uvm_test;
//注册
`uvm_component_utils(my_test)
//实例化my_test
my_test m_test;
//构造new函数,并指定父对象
function new(string name = "",uvm_component parent);
super.new(name,parent);
endfunction
//重载build_phase
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
//使用工厂机制创建env对象
m_env = my_env::type_id::create("m_env",this);
//为sequencer指定一个需要启动的sequence,
uvm_config_db#(uvm_object_wrapper)::set(this, "*.m_seqr.run_phase","default_sequence",my_sequence::get_type());
endfunction
//打印测试平台的组件的层次结构topology
virtual function void start_of_simulation_phase(uvm_phase phase);
super.start_of_simulation_phase(phase);
//树形结构
uvm_top.print_topology(uvm_default_tree_printer);
//表格结构
//uvm_top.print_topology(uvm_default_table_printer);
endfunction
endclass
8. 测试平台的启动
program automatic test;
import uvm_pkt.sv::*;
`include "uvm_macros.svh"
//包含以上所有创建文件
`include "..."
initial begin
run_test();
end
endmodule
上一篇: QT TextBrower设置为无边框
下一篇: CSS选择器权重比较的笔记总结