文章目录
- 前言
- 一、什么是UVM中的代理(Agent)
- 二、如何理解Agent
- 三、如何使用Agent
- 1、创建Agent类
- 2、实例化组件
- 3、配置Agent
- 4、连接组件
- 四、示例代码分析
前言
从Agent的概念入手,这个应该比较容易解释,就是把Driver、Monitor和Sequencer封装在一起,这样能让验证环境更清晰。
然后,我得考虑怎么解释Agent的使用步骤。这个需要我好好梳理一下,从创建Agent类开始,到实例化组件,再到配置Agent,最后是连接组件,这些步骤得一步一步地讲清楚。
UVM(Universal Verification Methodology)中的代理(Agent)是一个关键组件,用于封装与特定协议相关的驱动程序(Driver)、监视器(Monitor)和序列发生器(Sequencer)。以下是对UVM中代理的详细解释、使用方法以及示例代码的分析:
一、什么是UVM中的代理(Agent)
定义:
- Agent是UVM中的一个组件,用于封装与特定协议相关的驱动程序、监视器和序列发生器。
- 它继承自uvm_component,并且可以是主动的(UVM_ACTIVE)或被动的(UVM_PASSIVE)。
作用: - 封装性:将与特定协议相关的组件封装在一起,提高代码的可重用性和可维护性。
- 协议处理:处理特定协议的数据发送、驱动和采样。
- 灵活配置:可以根据测试需求灵活配置Agent的行为,例如设置为active或passive模式。
二、如何理解Agent
- 组件封装:Agent将Driver、Monitor和Sequencer封装在一起,形成一个独立的模块。
- 主动与被动模式:
- 主动模式(UVM_ACTIVE):Agent会实例化Driver和Sequencer,用于生成激励并驱动到DUT(Device Under Test)。
- 被动模式(UVM_PASSIVE):Agent只实例化Monitor,用于监视DUT的输出。
层次结构:在复杂的验证环境中,不同的接口协议可以分成不同的Agent,便于环境的管理和规范化。
三、如何使用Agent
使用Agent通常需要以下步骤:
- 创建Agent类:继承自uvm_agent,并定义内部组件(Driver、Monitor、Sequencer)。
- 实例化组件:在build_phase中实例化Driver、Monitor和Sequencer。
- 配置Agent:设置Agent的模式(active或passive),并通过uvm_config_db进行参数配置。
- 连接组件:在connect_phase中连接Driver和Sequencer的端口。
1、创建Agent类
- 继承uvm_agent:创建一个继承自uvm_agent的类,并定义内部组件(Driver、Monitor、Sequencer)。
- 注册类:使用uvm_component_utils宏进行类的注册,以便UVM工厂可以实例化它。
- 定义组件:在类中声明Driver、Monitor和Sequencer的实例。
示例代码
class my_agent extends uvm_agent;my_driver drv; // 驱动程序my_monitor mon; // 监视器my_sequencer sqr; // 序列发生器`uvm_component_utils(my_agent) // 注册类function new(string name = "my_agent", uvm_component parent = null);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);// 实例化监视器mon = my_monitor::type_id::create("mon", this);// 根据配置决定是否实例化驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv = my_driver::type_id::create("drv", this);sqr = my_sequencer::type_id::create("sqr", this);endendfunctionvirtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);// 如果是主动模式,连接驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv.seq_item_port.connect(sqr.seq_item_export);endendfunction
endclass
2、实例化组件
在build_phase中,根据Agent的模式(active或passive)实例化组件:
- 被动模式(passive):只实例化Monitor。
- 主动模式(active):实例化Driver、Monitor和Sequencer。
示例代码
virtual function void build_phase(uvm_phase phase);super.build_phase(phase);// 实例化监视器mon = my_monitor::type_id::create("mon", this);// 根据配置决定是否实例化驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv = my_driver::type_id::create("drv", this);sqr = my_sequencer::type_id::create("sqr", this);end
endfunction
3、配置Agent
- 设置Agent模式:通过is_active属性设置Agent为UVM_ACTIVE或UVM_PASSIVE。
- 配置参数:通过uvm_config_db设置Agent的其他参数,例如接口句柄、配置对象等。
示例代码
在测试环境中配置Agent:
class my_test extends uvm_test;my_agent agt;`uvm_component_utils(my_test)function new(string name = "my_test", uvm_component parent = null);super.new(name, parent);endfunctionvirtual function void build_phase(uvm_phase phase);super.build_phase(phase);// 实例化Agentagt = my_agent::type_id::create("agt", this);// 配置Agent为active模式agt.is_active = UVM_ACTIVE;// 通过uvm_config_db设置接口句柄(假设接口名为vif)uvm_config_db#(my_interface)::set(this, "agt", "vif", vif);endfunction
endclass
4、连接组件
在connect_phase中,连接Driver和Sequencer的端口,以便它们可以通信。
示例代码
virtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);// 如果是主动模式,连接驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv.seq_item_port.connect(sqr.seq_item_export);end
endfunction
以下是使用Agent的完整步骤:
- 创建Agent类:
- 实例化组件:
- 在build_phase中,根据is_active属性实例化组件。
- 配置Agent:
- 设置is_active属性。
- 通过uvm_config_db设置其他参数。
- 连接组件:
- 在connect_phase中,连接Driver和Sequencer的端口。
通过以上步骤,你可以构建一个完整的Agent,并将其集成到验证环境中。
四、示例代码分析
以下是一个简单的Agent示例代码及其分析:
示例代码
class my_agent extends uvm_agent;// 1. 定义内部组件my_driver drv; // 驱动程序my_monitor mon; // 监视器my_sequencer sqr; // 序列发生器// 2. 注册类`uvm_component_utils(my_agent)// 3. 构造函数function new(string name = "my_agent", uvm_component parent = null);super.new(name, parent);endfunction// 4. build_phasevirtual function void build_phase(uvm_phase phase);super.build_phase(phase);// 实例化监视器mon = my_monitor::type_id::create("mon", this);// 根据配置决定是否实例化驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv = my_driver::type_id::create("drv", this);sqr = my_sequencer::type_id::create("sqr", this);endendfunction// 5. connect_phasevirtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);// 如果是主动模式,连接驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv.seq_item_port.connect(sqr.seq_item_export);endendfunction
endclass
这段代码定义了一个 UVM 代理(uvm_agent)类 my_agent,它是 UVM 验证平台中的一个关键组件。以下是代码的详细解析和功能说明:
- 类定义和继承
class my_agent extends uvm_agent;
uvm_agent:这是 UVM 提供的基类,用于实现验证平台中的代理组件。代理组件通常包含驱动器(Driver)、监视器(Monitor)和序列发生器(Sequencer)。
my_agent:这是用户定义的代理类,继承自 uvm_agent。
- 定义内部组件
my_driver drv; // 驱动程序
my_monitor mon; // 监视器
my_sequencer sqr; // 序列发生器
my_driver:驱动程序,负责将事务转换为具体的信号并驱动到 DUT。
my_monitor:监视器,负责监视 DUT 的信号并生成事务。
my_sequencer:序列发生器,负责生成事务并将其传递给驱动程序。
- 注册类
`uvm_component_utils(my_agent)
uvm_component_utils:这是 UVM 提供的一个宏,用于将组件注册到 UVM 工厂中。注册后,可以通过名字创建和配置该组件。
my_agent:将 my_agent 类注册到 UVM 工厂中,方便后续实例化和使用。
- 构造函数
function new(string name = "my_agent", uvm_component parent = null);super.new(name, parent);
endfunction
new:这是类的构造函数,用于初始化 my_agent 实例。
super.new:调用父类 uvm_agent 的构造函数,完成初始化。
- build_phase
virtual function void build_phase(uvm_phase phase);super.build_phase(phase);// 实例化监视器mon = my_monitor::type_id::create("mon", this);// 根据配置决定是否实例化驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv = my_driver::type_id::create("drv", this);sqr = my_sequencer::type_id::create("sqr", this);end
endfunction
build_phase:这是 UVM 的一个阶段,用于组件的构建和初始化。
super.build_phase:调用父类的 build_phase 方法,完成父类的初始化。
- 实例化监视器:
mon = my_monitor::type_id::create("mon", this);
a.使用 type_id::create 方法实例化监视器 mon。
b.this 表示当前组件的父组件。
- 根据配置决定是否实例化驱动程序和序列发生器:
if (is_active == UVM_ACTIVE) begindrv = my_driver::type_id::create("drv", this);sqr = my_sequencer::type_id::create("sqr", this);
end
a.is_active:这是一个 UVM 提供的属性,用于决定代理是主动模式(UVM_ACTIVE)还是被动模式(UVM_PASSIVE)。
b.UVM_ACTIVE:如果代理是主动模式,实例化驱动程序 drv 和序列发生器 sqr。
c.UVM_PASSIVE:如果代理是被动模式,不实例化驱动程序和序列发生器,只实例化监视器。
- connect_phase
virtual function void connect_phase(uvm_phase phase);super.connect_phase(phase);// 如果是主动模式,连接驱动程序和序列发生器if (is_active == UVM_ACTIVE) begindrv.seq_item_port.connect(sqr.seq_item_export);end
endfunction
connect_phase:这是 UVM 的一个阶段,用于组件之间的连接。
super.connect_phase:调用父类的 connect_phase 方法,完成父类的连接。
- 连接驱动程序和序列发生器:
if (is_active == UVM_ACTIVE) begindrv.seq_item_port.connect(sqr.seq_item_export);
end
a.drv.seq_item_port:驱动程序的 TLM 端口,用于接收事务。
b.sqr.seq_item_export:序列发生器的 TLM 导出,用于发送事务。
c.connect:将驱动程序的 TLM 端口连接到序列发生器的 TLM 导出,确保事务可以从序列发生器传递到驱动程序。
这段代码实现了一个 UVM 代理 my_agent,它可以根据配置决定是否实例化驱动程序和序列发生器,并将它们连接起来。代理是 UVM 验证平台中的关键组件,负责管理驱动程序、监视器和序列发生器之间的交互。通过灵活的配置和连接,代理可以适应不同的验证需求,提高验证平台的可重用性和可维护性。
功能总结
- 组件实例化:实例化监视器 mon,用于监视 DUT 的信号并生成事务。根据配置决定是否实例化驱动程序 drv 和序列发生器 sqr。
- 组件连接:如果代理是主动模式,将驱动程序的 TLM 端口连接到序列发生器的 TLM 导出,确保事务可以从序列发生器传递到驱动程序。
- 灵活性:通过 is_active 属性,代理可以配置为主动模式或被动模式,灵活适应不同的验证需求。
- UVM 工厂注册:使用 uvm_component_utils 宏将 my_agent 类注册到 UVM 工厂,方便后续实例化和使用。