2016-09-21 64 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

:)明白了。只要確保這一切。不用謝 。 –