在我的Testbench中,我有一个需要驱动的界面。该接口可以以2种不同的模式驱动,每种模式都有自己的驱动协议和事务类型。
到目前为止,我已经分别设计了两个uvm_agents。现在,我需要一种方法来交换一个或另一个,这取决于我正在运行的测试用例。我也希望以最适合UVM理念的方式做到这一点。
我能提出的最佳方法是:在我的uvm_env中,从“ModeA”或“ModeB”的测试中获取uvm_db_config参数,并根据该参数,将代理的is_active设置为“UVM_ACTIVE”适当地使用“UVM_PASSIVE”。
我想对这种方法有所了解。
向我建议的方法是保留一个公共的uvm_agent,并根据配置实例化uvm_driver / uvm_sequencer。对这种方法不太确定,因为它看起来很乱。
答案 0 :(得分:3)
我也建议,像都铎一样,只使用一个代理人。但后来我会使用继承,声明一个base_driver和一个base_sequencer(它可能具有ModeA或ModeB驱动程序和/或顺控程序的共同功能),而ModeA和ModeB单元将扩展那些基本功能。然后,在代理中,并使用每个测试中设置的uvm_config_db中的标志,您可以选择实例化一个或另一个:
基本驱动程序:
class my_proj_base_driver extends uvm_driver#(my_proj_tr);
[...]
ModeA驱动程序:
class my_proj_ModeA_driver extends my_proj_base_driver;
[...]
ModeB驱动程序:
class my_proj_ModeB_driver extends my_proj_base_driver;
[...]
在代理商中:
[...]
my_proj_base_driver driver;
bit modeAorB // 0 for A, 1 for B
[...]
if (!uvm_config_db#(bit)::get(this,"","modeAorB", modeAorB))
`uvm_fatal("NOMODE","No mode set for this agent")
if(!modeAorB)
driver = my_proj_ModeA_driver::type_id::create(.name("driver"), .parent(this));
else
driver = my_proj_ModeB_driver::type_id::create(.name("driver"), .parent(this));
对于音序器也一样。
答案 1 :(得分:2)
我更希望每个模式都有一个公共代理类和一个具体的classe,然后根据我正在运行的测试进行类型覆盖。通过这种方式可以清楚地看到,只有一个代理处理该接口(而不是2,其中一个在根本不使用时被设置为被动)。一个代理类实例化一组驱动程序/顺控程序,另一个代理程序类实例化其他代理程序类。这样,您只需设置一个类型覆盖(在代理上)而不是2(在驱动程序和顺控程序上)。
如果在两种模式下都使用相同的监视器,那么最好选择一种代理方法,因为您只需将记分板连接到一台监视器,而不是连接代理A或其他监视器中的任何一种。代理B取决于模式。
你的方法也很有效,在这种情况下我不认为有一种标准的UVM方式。我有一位同事为GPIO界面做了类似的事情,但它运行良好。