FPGA实践者
面试官问这个,是想看你是不是真的用过UVM,而不是只背了概念。我当初也被问懵过,后来自己搭环境就懂了。
简单说,phase就是UVM定好的一套“流水线”,保证环境里几十个零件能井井有条地初始化、跑起来、停下来。你不用操心谁先谁后,UVM帮你管。
最常用的就那几个:
- build_phase:盖房子。先把图纸(配置)拿来,然后从大楼(test)到房间(env)再到家具(agent, driver)一层层把对象new出来。这里记住,配置(config)是从外向里“扔”进来的,用uvm_config_db::set/get。
- connect_phase:拉电线。等所有家具都摆好了,开始接线。比如把driver的出口接到sequencer的出口,把monitor看到的信号送到scoreboard的进口。这里顺序是反的,从最里面的家具(driver)开始往外接。
- run_phase:干活。仿真时间开始走,driver开始从sequencer要数据包并驱动到接口上,monitor开始抓信号,scoreboard开始比较数据。这个phase其实是一大块,里面还分了好多小阶段(reset, main, shutdown...),你可以让不同组件在不同小阶段启动或停止,比如先复位再配置再跑主流量。
怎么插自己的代码?太常用了。你只要在你的component里写一个同名的方法就行。比如,你想在环境构建时打印个消息,就在my_env里写 `function void build_phase(uvm_phase phase); super.build_phase(phase); $display("My env is built!"); endfunction`。记住一定要先调用`super.xxx_phase(phase)`,保证父类该做的事(比如建子组件)先做完。
一个实战中的坑:在build_phase里,如果你想引用另一个组件的对象,很可能它还不存在,因为build顺序是自上而下的。这时候应该通过uvm_config_db传递句柄,而不是直接跨组件引用。
理解设计哲学:这套机制就是为了可重用性。每个组件只关心自己在每个阶段该做什么,不用管别人。这样组件就像乐高,放在任何环境里都能正确初始化和运行。
