- uvm_config_db
对于这个知识点,印象最深刻的就是,少使用它,并且使用的时候应该精准;
这个项目中,做vip(ahb_agent和apb_agent)的时候,为了方便调用vip,不需要了解vip的具体使用方法,我们有这样的定义方法:
- 首先,在top_tb使用set来传递interface到agent这一层
uvm_config_db#(virtual apb_if)::set(null,"uvm_test_top.env_i.apb_slv_agt_i","vif",apb_if_i);
uvm_config_db#(virtual ahbl_if)::set(null,"uvm_test_top.env_i.ahbl_mst_agt_i","vif",ahbl_if_i);
- 然后,在agent层次get到对应的interface,并且通过set再传递给agent下层的monitor和driver,
//apb_slv_agt
if(!uvm_config_db#(virtual apb_if)::get(this,"","vif",vif))
`uvm_fatal("No vif","Vif is not set!")
uvm_config_db#(virtual apb_if)::set(this,"mon_i","vif",vif);
if(is_active == UVM_ACTIVE)begin
sqr_i = apb_slv_sqr::type_id::create("sqr_i",this);
drv_i = apb_slv_drv::type_id::create("drv_i",this);
uvm_config_db#(virtual apb_if)::set(this,"drv_i","vif",vif);
end
//ahbl_mst_agt
if(!uvm_config_db#(virtual ahbl_if)::get(this,"","vif",vif))
`uvm_fatal("No vif","Vif is not set!")
uvm_config_db#(virtual ahbl_if)::set(this,"mon_i","vif",vif);
if(is_active == UVM_ACTIVE)begin
sqr_i = ahbl_mst_sqr::type_id::create("sqr_i",this);
drv_i = ahbl_mst_drv::type_id::create("drv_i",this);
uvm_config_db#(virtual ahbl_if)::set(this,"drv_i","vif",vif);
end
- 最后,在对应的monitor和driver中get到interface
//apb monitor或driver
if(!uvm_config_db#(virtual apb_if)::get(this,"","vif",vif))begin
`uvm_fatal("No vif","Vif not found");
end
//ahb monitor或driver
if(!uvm_config_db#(virtual ahbl_if)::get(this,"","vif",vif))begin
`uvm_fatal("No vif","Vif is not set")
end
以上三个步骤,是为了vip重用,以后搭建环境的人,不需要关心底层的interface,只需要在uvm_top_tb中将需要的interface通过set传递到agent一层就可以了,至于内部怎么传递,那是vip里面的事情!
- is-active什么时候用?
集成的时候,已经是全芯片的时候,是电路中真正的master(别的模块)来驱动!
这个时候就不需要driver、sequencer,我们就可以调用开关,关掉它们,agent中的monitor都活着也不影响! - AHB-APB
左右连个协议,AHB比APB复杂,多了burst传输,但是在ahb到apb传输时,因为apb没有burst传输,所有在ahb这一侧没有加入burst,也没有必要使用burst,直接single即可。这样,一个周期就是一个package,直接传入scoreboard即可直接比较产生结果!
即便是在ahb_mst_monitor中使用了burst,在scoreboard中还要解包才能与apb进行比较,这就有些复杂!