从 Python 视角理解 SystemVerilog 中的 UVM 语法
·
🧪 UVM 语法详解(OOP 视角 · Python 类比版)
目标:理解 UVM 中每个组件“是什么”,而不是“怎么跑测试”。
假设你熟悉 Python 的class、__init__、继承、方法调用。
🧱 1. 类定义与继承
✅ UVM
// 定义一个组件类,继承自 uvm_component
class my_driver extends uvm_component;
// 类体
endclass
🧠 Python 类比
class MyDriver:
pass
🔍 说明:
- 所有 UVM 组件必须继承自
uvm_component(或其子类如uvm_driver,uvm_monitor); - 所有事务类(数据包)必须继承自
uvm_object或uvm_sequence_item。
🔧 2. 构造函数:new() vs __init__()
✅ UVM
class my_driver extends uvm_component;
// 构造函数:必须接受 name 和 parent
function new(string name, uvm_component parent);
super.new(name, parent); // 调用父类构造器
endfunction
endclass
🧠 Python 类比
class MyDriver:
def __init__(self, name, parent):
self.name = name
self.parent = parent
# 父类初始化(Python 中通常自动处理)
⚠️ 注意:UVM 的
new()不是“创建对象”,而是“初始化已分配的对象”。实际创建由工厂完成(见下文)。
🏷️ 3. 类注册:宏 `uvm_component_utils
✅ UVM
class my_driver extends uvm_component;
`uvm_component_utils(my_driver) // ← 关键宏!
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
🧠 Python 类比(模拟注册机制)
# 模拟 UVM 工厂注册表
UVM_FACTORY = {}
def register_class(cls_name, cls):
UVM_FACTORY[cls_name] = cls
class MyDriver:
def __init__(self, name, parent):
self.name = name
self.parent = parent
# 注册
register_class("MyDriver", MyDriver)
🔍 为什么需要注册?
UVM 使用 工厂模式 动态创建对象。如果不注册,type_id::create()会失败。
🏭 4. 对象创建:工厂模式 type_id::create()
✅ UVM
// 在 test 或 env 中创建 driver
my_driver drv = my_driver::type_id::create("drv", this);
🧠 Python 类比
# 通过工厂创建(而非直接 MyDriver())
drv = UVM_FACTORY["MyDriver"]("drv", parent=this)
✅ 优势:支持运行时替换类(override),实现测试复用。
📦 5. 事务类(数据包):uvm_sequence_item
✅ UVM
class my_item extends uvm_sequence_item;
`uvm_object_utils(my_item) // 注意:这里是 object_utils!
rand bit [7:0] data; // 随机变量
rand int delay;
constraint c_valid {
data > 8'h10;
delay inside {[1:10]};
}
function new(string name = "my_item");
super.new(name);
endfunction
endclass
🧠 Python 类比
import random
class Transaction:
def __init__(self, name="Transaction"):
self.name = name
# 手动实现约束随机
self.data = random.randint(0x11, 0xEF)
self.delay = random.randint(1, 10)
🔍 关键差异:
- UVM:
rand+constraint→ 编译器/仿真器自动保证合法性; - Python:需手动编码,无法表达复杂约束(如
solve before、dist)。
🔄 6. 组件通信:TLM 端口(Port / Export)
✅ UVM(Driver 从 Sequencer 获取事务)
class my_driver extends uvm_driver #(my_item);
// 内置端口:seq_item_port(类型为 uvm_seq_item_pull_port)
// 无需声明,基类已提供
virtual task run_phase(uvm_phase phase);
forever begin
seq_item_port.get_next_item(req); // 阻塞等待
// 驱动 req 到 DUT
seq_item_port.item_done(); // 通知完成
end
endtask
endclass
🧠 Python 类比(简化队列通信)
from queue import Queue
class Sequencer:
def __init__(self):
self.queue = Queue()
def put(self, item):
self.queue.put(item)
def get(self):
return self.queue.get() # 阻塞
class Driver:
def __init__(self, sequencer):
self.sequencer = sequencer
def run(self):
while True:
item = self.sequencer.get()
self.drive(item)
🔍 UVM 优势:
- 标准化接口(所有 driver 都用
seq_item_port); - 类型安全(只能传
my_item); - 支持多 producer / single consumer 模型。
📡 7. 发布-订阅:uvm_analysis_port
✅ UVM(Monitor 发布事务)
class my_monitor extends uvm_monitor;
// 声明分析端口
uvm_analysis_port #(my_item) ap;
function new(string name, uvm_component parent);
super.new(name, parent);
ap = new("ap", this); // 创建端口实例
endfunction
virtual task run_phase(uvm_phase phase);
forever begin
my_item item = collect_from_dut();
ap.write(item); // 发送给所有订阅者
end
endtask
endclass
🧠 Python 类比(回调列表)
class Monitor:
def __init__(self):
self.subscribers = []
def subscribe(self, callback):
self.subscribers.append(callback)
def run(self):
while True:
item = self.collect()
for cb in self.subscribers:
cb(item) # 通知所有监听者
✅ UVM 的
write()是标准方法,Scoreboard 只需实现write()即可接收数据。
🧩 8. 组件组装:build_phase 与 connect_phase
✅ UVM
class my_env extends uvm_env;
my_agent agent;
my_scoreboard sb;
virtual function void build_phase(uvm_phase phase);
// 创建子组件
agent = my_agent::type_id::create("agent", this);
sb = my_scoreboard::type_id::create("sb", this);
endfunction
virtual function void connect_phase(uvm_phase phase);
// 连接通信端口
agent.monitor.ap.connect(sb.analysis_imp);
endfunction
endclass
🧠 Python 类比
class Env:
def __init__(self):
self.agent = Agent()
self.scoreboard = Scoreboard()
# 连接:monitor 的输出 → scoreboard 的输入
self.agent.monitor.subscribe(self.scoreboard.write)
🔍 UVM 特色:
build_phase:只负责“创建”,不涉及连接;connect_phase:只负责“连线”,此时所有组件已存在;- 两个 phase 由系统自动调用,顺序严格。
✅ 总结:UVM OOP 核心要素对照表
| 概念 | UVM 语法 | Python 类比 | 说明 |
|---|---|---|---|
| 类定义 | class X extends Y; |
class X(Y): |
必须继承 UVM 基类 |
| 构造函数 | function new(...) |
def __init__(...) |
必须调用 super.new() |
| 类注册 | `uvm_component_utils(X) |
factory.register(X) |
工厂创建的前提 |
| 对象创建 | X::type_id::create(...) |
Factory.create("X") |
支持 override |
| 随机数据 | rand + constraint |
random + while |
UVM 更强大安全 |
| 组件通信 | port.connect(export) |
obj1.callback = obj2.method |
UVM 标准化、类型安全 |
| 组件组装 | build_phase / connect_phase |
__init__ + 手动连线 |
UVM 自动调度 |
更多推荐


所有评论(0)