如何访问UVM Sequence中的变量?通过UVM_config_db修改序列变量方法
n_times变量 刚好我之前也遇到过类似的困惑,核心要先搞清楚:Sequence是uvm_object而非uvm_component,它本身没有固定的层级结构,只有当它被启动在某个Sequencer上时,才会依附于该Sequencer的层级之下。这是确定配置路径的关键。下面给你两种实用的解决方法:
方法一:直接给Sequence实例赋值(最简单直接)
如果你的测试顶层是直接创建并启动Sequence实例的,那完全可以跳过uvm_config_db,直接在启动前给变量赋值:
class my_test extends uvm_test; env my_env; base_sequence base_seq; virtual task run_phase(uvm_phase phase); phase.raise_objection(this); // 创建Sequence实例 base_seq = base_sequence::type_id::create("base_seq"); // 直接修改n_times变量 base_seq.n_times = 50; // 启动Sequence base_seq.start(my_env.my_agent.my_sequencer); phase.drop_objection(this); endtask endclass
这种方式代码简洁,适合不需要动态配置的简单场景。
方法二:用UVM_config_db传递变量(更灵活,适配复杂场景)
如果需要通过配置数据库来传递参数(比如支持不同测试用例的动态配置),关键是找对Sequence的层级路径,或者利用它依附的Sequencer来传递配置。
步骤1:在测试顶层设置UVM_config_db
因为Sequence启动后会挂靠在Sequencer的层级下,你可以把配置设置到Sequencer的路径下,用通配符*匹配所有在该Sequencer上启动的Sequence:
class my_test extends uvm_test; env my_env; virtual function void build_phase(uvm_phase phase); super.build_phase(phase); my_env = env::type_id::create("my_env", this); // 将n_times设置到sequencer路径下,匹配所有该sequencer上的sequence uvm_config_db#(int unsigned)::set(this, "my_env.my_agent.my_sequencer.*", "n_times", 100); endfunction endclass
如果你只想给特定的Sequence实例传递配置,可以指定Sequence的实例名(比如启动时创建的base_seq):
uvm_config_db#(int unsigned)::set(this, "my_env.my_agent.my_sequencer.base_seq", "n_times", 100);
步骤2:在Sequence中获取配置值
在base_sequence的body()任务(或者pre_body())中,通过uvm_config_db获取值,这里有两种稳妥的方式:
方式A:利用Sequence自身的完整路径
你可以通过get_full_name()打印出Sequence的完整层级路径,然后用它来获取配置:
virtual task body(); // 尝试从config_db获取n_times,没拿到就用默认值 if(!uvm_config_db#(int unsigned)::get(null, get_full_name(), "n_times", n_times)) begin n_times = 10; // 设置默认值 `uvm_warning("CFG_GET", "n_times not found in config_db, using default value 10") end // 原有的repeat逻辑 repeat (n_times) begin start_item (data_obj); assert (data_obj.randomize ()); finish_item (data_obj); end endtask
如果不确定路径,可以先加一句打印:uvm_info("SEQ_PATH", $sformatf("My full path is %s", get_full_name()), UVM_MEDIUM);,仿真时就能看到完整路径,方便调整配置。
方式B:利用依附的Sequencer
因为Sequence和Sequencer是绑定的,你可以通过get_sequencer()拿到Sequencer的句柄,用它作为上下文来获取配置,这种方式不需要关心Sequence的实例名:
virtual task body(); uvm_sequencer #(my_data) sqr; sqr = get_sequencer(); // 从sequencer的上下文获取配置 if(!uvm_config_db#(int unsigned)::get(sqr, "", "n_times", n_times)) begin n_times = 10; `uvm_warning("CFG_GET", "n_times not found in config_db, using default value 10") end // 原有的repeat逻辑 endtask
内容的提问来源于stack exchange,提问作者Yong Chen

