【问题标题】:Reference to UVM Sequence参考 UVM 序列
【发布时间】:2016-09-21 15:58:33
【问题描述】:

我需要监控寄存器的状态。我创建了一个 UVM 序列来读取寄存器并将它们存储在本地。现在在我的测试代码中,我需要访问这些 寄存器。这是一个 sudo 代码:

typedef struct {
    int a;
} my_regs;

class my_seq extends uvm_sequence;
     // register to uvm db 
    reg_map       map;
    my_regs       regs;
    uvm_status_e  status;

    task build_phase(uvm_phase phase);
    endtask 

    task run_phase(uvm_phase phase);
        map.CORE.reg_a.read(status, regs.a, UVM_BACKDOOR)
    endtask
endclass

class test_reg extends uvm_test;
     // register to uvm db 
     my_seq  seq;
     my_regs regs;

     task build_phase(uvm_phase phase);
         seq  = my_seq::type_id::create("reg_seq", this);
         regs = seq.regs;
     endtask 

     task run_phase(uvm_phase phase);
         reg_seq.start(null);
         // read reg values from seq??????
         if(rqgs.a>1)
            //do some thing

     endtask
endclass

如您所见,我不断启动序列,以免错过任何更新。我相信 start 任务顺序不会创建新对象 所以对象内部的值应该在开始调用之间保持不变。

假设我不是每次都从 seq 读取 regs 值,那么测试类的 regs 不会从 seq 获取更新。这意味着 regs = seq.regs; 不会创建对 seq.regs 的实际引用。我想知道为什么会这样以及如何创建对该对象的绝对引用? (这样我就不会浪费模拟周期来读取和更新测试类中的 regs 值)。如果有更好的方法,请告诉我。

【问题讨论】:

    标签: system-verilog uvm


    【解决方案1】:

    首先是一个小修复。序列没有构建或运行阶段。与其他 uvm_components 不同,它们不会自动启动[使用相位系统]。 序列有一个主体任务,它被覆盖以实现功能(在这种情况下是读取寄存器)。所以需要将 run_phase 中的代码移到 body 函数中。

    class my_seq extends uvm_sequence;
         // register to uvm db 
        reg_map       map;
        my_regs       regs;
        uvm_status_e  status;
    function  new(string name="my_seq");
        super.new(name);
      endfunction
    
      task body ();
            map.CORE.reg_a.read(status, regs.a, UVM_BACKDOOR);
        endtask
    endclass
    

    一旦调用序列,它将从 RTL 寄存器中读取值并更新 my_seq 类中 regs 中的“a”字段。

     regs = seq.regs; // 
    

    regs (在测试中)将提供到序列中 regs 字段的永久链接。因此,每当序列读取寄存器并更新 regs 字段时,test_reg 中的变量 regs 都会看到变化,但这意味着必须从 RTL 中读取寄存器。 test_reg 需要实现一个循环来定期读取寄存器(通过调用序列 my_seq)。这是因为变量 regs 或寄存器字段 map.CORE.reg_a 不是 RTL 中寄存器的直接链接。

    您将需要花费模拟周期来读取 RTL 寄存器,因为 uvm_register 只是一个镜像/副本,只有在发出读取时才会更新。

    问题是固件如何访问寄存器?如果寄存器是通过轮询机制访问的,最好在测试用例中模仿。

    task run_phase(uvm_phase phase);
         task_done = 0;
         while ( !task_done ) 
          begin
             // wait for some delay as backdoor access takes 0 simulation time
             reg_seq.start(null);   // regs is updates 
             // read reg values from seq - done
             if(regs.a>1)    // check for bit to be set 
             begin
                task_done = 1;
                //do some thing
             end
             // else continue to poll register 
           end
    end task
    

    或者,我们可以等待 RTL 信号改变,然后发出读取(这种方法是不可取的,因为我们正在从测试台访问 RTL 信号。)

    task run_phase(uvm_phase phase);
                 wait ( RTL.module.reg.CORE.reg_a == 1 ) ;
                 reg_seq.start(null);   // regs file is updates 
                 // read reg values from seq - done
                 if(regs.a>1)    // check for bit to be set 
                    //do some thing
        endtask
    

    【讨论】:

    • 哦,你是对的,正如我所说,这是一个 sudo 代码,在原始代码中,我按照你描述的方式实现了主体。再次感谢!
    • :) 知道了。只要确保仅此而已。不客气。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    相关资源
    最近更新 更多