1

我正在创建一个框架,我的验证团队和我可以轻松地编写 uvm 测试用例。基本思想是我的基本(uvm_)序列在其主体任务中仅包含一行:

regs.update(status);

从我的个人 (uvm_) 测试中,我可以使用方便的辅助函数设置寄存器值。例如,我的测试将包含:

class base_test extends uvm_test;
    ........
    ........
    virtual function void set_registerA(....);
        regs.registerA1.set(....);
        regs.registerA2.set(....);
        regs.registerA3.set(....);
    endfunction

    virtual function void set_registerB(....);
        regs.registerB1.set(....);
        regs.registerB2.set(....);
        regs.registerB3.set(....);
    endfunction
endclass

class test1 extends base_test;
    virtual function void end_of_elaboration_phase(uvm_phase phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

class test2 extends base_test;
    virtual function void end_of_elaboration_phase(uvm_phase phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

现在我意识到 end_of_elaboration 阶段可能不是设置寄存器的最佳位置。我的编译器给了我警告,上面写着“警告:在任务“end_of_elaboration”中调用任务“set_registerA”。所以我将其更改为在我的run_phase中执行:

class test1 extends base_test;
    virtual task run_phase(uvm_phase phase);
        super.run_phase(phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

class test2 extends base_test;
    virtual task run_phase(uvm_phase phase);
        super.run_phase(phase);
        set_registerA(....);
        set_registerB(....);
    endfunction
endclass

我不确定这是否是我想要做的正确方法?调用 super.run_phase 会导致问题吗?我没有看到其他地方这样做过。

4

3 回答 3

1

我个人不喜欢调用 super.run_phase(...) 因为如果你想实现在祖父类中定义的东西,它会产生问题。如果您不期望从测试继承的测试继承测试,那么您应该没有任何问题。主要思想是 run_phase 几乎总是会被覆盖,但 end_of_elaboration/start_of_simulation 更少,这就是为什么它会成为更通用事物的更好候选者。

对于您的编译问题,请检查您是否没有为 set_register* 函数创建任务而不是函数。您的编译器可能更宽松,并允许您在函数内启动任务(end_of_elaboration 是一个函数),很可能通过执行相当于 fork...join_none

于 2014-06-16T19:25:21.247 回答
1

想到 2 种可能的解决方案: 1. 您可以放弃基本序列的想法,创建不同的序列并在 中设置寄存器,body()然后调用update(). 或者,如果您真的想使用基本序列,您可以在pre_bodythen in bodycall中设置寄存器,super.body这将执行update. 从方法论的角度来看,我认为为寄存器设置值(通过更新真正转换为 reg.write())属于序列而不是测试。2.你可以把setregs留在测试如果你在测试main_phase开始序列,在做seq.start(seqr)之前,所有的寄存器都可以设置

为了仅使用 1 个具有交替序列的测试,请在测试文件中添加:

function void build_phase(uvm_phase phase);
      string seq_name;
      uvm_sequence_base seq;
      uvm_factory factory= uvm_factory::get();

      super.build_phase(phase);

      $value$plusargs("SEQ_NAME=%s", seq_name); 
      .......    

 if(! $cast(seq, factory.create_object_by_name(seq_name)))
     `uvm_fatal("", "Failed to create sequence")
  if(seq == null)
     `uvm_fatal("", "no sequence created seq=null!!")

  uvm_config_db #(uvm_sequence_base)::set(this, "master.sequencer.main_phase" ,"default_sequence", seq);

然后在命令行添加:+SEQ_NAME=rand_seq

于 2014-06-17T11:53:43.217 回答
1

您已经发现它是正确的 uvm_end_of_elaboration_phase 主要用于微调我们的测试平台,因此它不是设置寄存器的好地方。

我建议运行时阶段是设置寄存器的更好地方,但不要使用通用阶段,即虚拟任务 run_phase(uvm_phase phase);

我们可以将其拆分为 UVM 预定义的运行时阶段,它们是

UVM 运行时间阶段

其中我们可以选择“uvm_configure_phase”和“uvm_main_phase”,所以建议的伪代码编辑如下,

  class base_test extends uvm_test;
    ........
    ........
    virtual function void set_registerA(....);
        regs.registerA1.set(....);
        regs.registerA2.set(....);
        regs.registerA3.set(....);
    endfunction

    virtual function void set_registerB(....);
        regs.registerB1.set(....);
        regs.registerB2.set(....);
        regs.registerB3.set(....);
    endfunction

   task main_phase (uvm_phase phase)
   // Copy your run_phase code over here
   endtask : main_phase

 endclass

class test1 extends base_test;
    virtual task configure_phase(uvm_phase phase);
        set_registerA(....);
        set_registerB(....);
    endtask

    virtual task main_phase(uvm_phase phase);
        super.main_phase(phase);
    endtask : main_phase
endclass

class test2 extends base_test;
    virtual task configure_phase(uvm_phase phase);
        set_registerA(....);
        set_registerB(....);
    endtask : configure_phase

    virtual task main_phase(uvm_phase phase);
        super.main_phase(phase);
    endtask : main_phase
endclass

希望这能解决你的问题!!!

于 2016-02-20T08:36:42.447 回答