2016-09-21 47 views
1

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

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 

正如你所看到的,我不断地开始序列,以便我不会错过任何更新。我相信开始任务按顺序不会创建一个新的对象 因此对象内的值应保持恒定的开始调用之间。

假设我每次都不读取seq的regs值,测试类的regs将不会从seq获取更新。意思是regs = seq.regs;不会创建对seq.regs的实际参考。我想知道为什么是这样的,我怎样才能创建一个绝对引用该对象? (这样我就不用浪费模拟周期来阅读和更新测试类中的regs值)。另外请告诉我是否有更好的方法来做到这一点。

回答

2

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

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暂存器更新的“a”字段。

regs = seq.regs; // 

regs(在测试中)将提供到序列内regs字段的永久链接。因此,无论何时序列读取寄存器并更新寄存器字段,test_reg中的变量寄存器都会看到变化,但这意味着寄存器必须从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 
+0

哦,你是对的,正如我所说这是一个sudo代码,并且在原始代码中,我已按照您描述的方式实现了该主体。再次感谢! – maskarih

+0

:)明白了。只要确保这一切。不用谢 。 –