UVM基礎之---------uvm report 機制分析


uvm 中的信息報告機制相對來講比較簡單,功能上來講主要分爲兩部分:

第一經過ID對component的信息報告冗餘級別進行控制,針對每一個冗餘級別進行不一樣的行爲控制。這部分工做主要由uvm_report_hander來實現:
     主要涉及到的方法有get_report_verbosity_level(severity, id)/get_report_action(severity,id) == uvm_action'(UVM_NO_ACTION)
第二是對message進行格式化的輸出,這部分工做主要由uvm_report_server來實現
      主要涉及到的方法有message_compose

咱們經過一個`uvm_error宏的執行進行分析,
    `uvm_error(「driver」,  「the config object is null」) 
這是一個在TB中調用的uvm宏,主要接收兩個參數 ID和要打印的MSG,這個宏在 uvm_message_defines.svh中進行定義,具體定義以下:

140 `define uvm_error(ID,MSG)  \
141    begin  \
142      if (uvm_report_enabled(UVM_NONE,UVM_ERROR,ID))  \
143        uvm_report_error (ID, MSG, UVM_NONE, `uvm_file, `uvm_line);  \
144    end

首先調用的是uvm_report_enabled函數,主要目的是爲了檢查這個message是否容許輸出。這個函數有兩個版本, 假如是在一 個 component中調用uvm_error 宏的話,那麼使用的是這個 component本身的函數, 而這個函數是在uvm_report_object中定義的:
447   function int uvm_report_enabled(int verbosity,
448                           uvm_severity severity=UVM_INFO, string id="");
449     if (get_report_verbosity_level(severity, id) < verbosity ||                            //檢查對應severity,id的verbosity(冗餘級別)是否大於容許輸出的verbosity
450         get_report_action(severity,id) == uvm_action'(UVM_NO_ACTION))    //檢查對應severity,id的action是不是UVM_NO_ACTION
451       return 0;
452     else
453       return 1;
454   endfunction
假如是在一個 sequence 中或者是一個派生自 uvm_object 的類中使用這個宏的 話,調用的是全局的函數
115 function bit uvm_report_enabled (int verbosity,
116                                  uvm_severity severity=UVM_INFO, string id="");
117   uvm_root top;
118   top = uvm_root::get();
119   return top.uvm_report_enabled(verbosity,severity,id);
120  endfunction

get_report_verbosity_level 的定義以下:  m_rh 是一個 uvm_report_handler 類型的變量,它會在每一個 component 實例化的
時候被實例化,也就是說,每一個 component 對應一個 m_rh,此變量用於記錄這個 component 的一些報告信息, 如是否單獨對此 component 設置了報告冗餘度級別
(verbosity_lever) 。 get_report_verbosity_level 這個函數最終調用的是 uvm_report_handler的get_verbosity_level函數。

  81 class uvm_report_object extends uvm_object;
  82
  83   uvm_report_handler m_rh;
       …
  90   function new(string name = "");
  91     super.new(name);
  92     m_rh = new();
  93   endfunction
       …
413   function int get_report_verbosity_level(uvm_severity severity=UVM_INFO, string id="");
414     return m_rh.get_verbosity_level(severity, id);
415   endfunction
       …
539 endclas

下面簡單的分析一下在uvm_report_handler中用到的get_verbosity_level函數,咱們能夠從中學到一些對數組的控制方式:
    55 class uvm_report_handler;
       …
236   function int get_verbosity_level(uvm_severity severity=UVM_INFO, string id="" );
237
238     uvm_id_verbosities_array array;
239     if(severity_id_verbosities.exists(severity)) begin           //首先判斷severity_id_verbosities(聯合數組,索引就是severity)中是否存在與serverity對應的記錄
240       array = severity_id_verbosities[severity];                    //這個聯合數組返回的是一個uvm_id_verbosities_array,而這個array是uvm_pool的一個實例,
241       if(array.exists(id)) begin                                              //這個uvm_id_verbosities_array的索引就是對應的message_id,而內容則是這個message_id的冗餘整數
242         return array.get(id);                                                   //如今的問題是,這個severity_id_verbosities在哪裏被寫入??
243       end
244     end
245
246     if(id_verbosities.exists(id)) begin                                //id_verbosities是一個uvm_id_verbosities_array類型的變量
247       return id_verbosities.get(id);                                     //索引就是對應的message_id,而內容則是這個message_id的冗餘整數
248     end                                                                               //一樣的問題,這個id_verbosities在什麼時候被寫入??
249
250     return m_max_verbosity_level;
251
252   endfunction
       …
622 endclass : uvm_report_handle


對uvm_action和file handle的處理跟get_verbosity_level相相似,這裏就再也不進行分析,如今咱們分析在上面代碼分析中提到的兩個問題:

   1. 這個severity_id_verbosities在哪裏被寫入?咱們直接分析uvm_report_handler的code,由於前面提到了,這部分工做是有handler來實現和管理的:
  function void set_severity_id_verbosity(uvm_severity severity,
                                       string id,
                                       int verbosity);
    if(!severity_id_verbosities.exists(severity))
      severity_id_verbosities[severity] = new;
    severity_id_verbosities[severity].add(id,verbosity);
  endfunction

   2. id_verbosities在什麼時候被寫入?
  function void set_id_verbosity(input string id, input int verbosity);
    id_verbosities.add(id, verbosity);
  endfunction

分析上面的代碼能夠知道這裏面set_severity_id_verbosity 要比set_id_verbosity的優先級要高。

咱們前面說過,對message進行格式化的輸出,這部分工做主要由uvm_report_server來實現,因此uvm_report_error通過傳遞,最終會調用uvm_report_server中的report函數,這裏面須要提一下的是uvm_report_server是單實例的,在這裏重申一下uvm_report機制幾個類之間的關係, report—object和report_handler的關係是一 一對應的,固然也能夠多個report_object對應一個report_handler(set_report_handler).handler到server的關係是多對一。

243   virtual function void report(
244       uvm_severity severity,
245       string name,
246       string id,
247         string message,
248       int verbosity_level,
249       string filename,
250       int line,
251       uvm_report_object client
252       );
253     string m;
254     uvm_action a;
255     UVM_FILE f;
256     bit report_ok;
257     uvm_report_handler rh;
258
259     rh = client.get_report_handler();  // 再次拿到uvm_component的uvm_report_hander的實例指針,目的是爲了後面再次進行uvm_report_enabled檢查,以及拿到在uvm_report_handler中的file_handle
260
261     // filter based on verbosity level
262 

273     f = rh.get_file_handle(severity, id);
274
275     // The hooks can do additional filtering.  If the hook function
276     // return 1 then continue processing the report.  If the hook
277     // returns 0 then skip processing the  report.
278
279     if(a & UVM_CALL_HOOK)
280       report_ok = rh.run_hooks(client, severity, id,
281                               message, verbosity_level, filename, line);                //調用run_hooks函數再次確認是否進行打印信息,run_hooks在uvm_report_handler中進行定義,調用uvm_report_object中定義的report_info_hook/report_warning_hook/report_error_hook/report_fatal_hook函數,能夠在繼承uvm_component的時候對這些hook進行重載,今兒實現對message的控制。

282     else
283       report_ok = 1;

285     if(report_ok)
286        report_ok = uvm_report_catcher::process_all_report_catchers(             //這是一個uvm_callback類, 它的主要用處就是在真正 的打印信息以前能夠再次控制要打印的信息,每一個uvm_catcher都要實現一個catch的函數!
287                      this, client, severity, name, id, message,
288                      verbosity_level, a, filename, line);
289
290     if(report_ok) begin
291       m = compose_message(severity, name, id, message, filename, line);
292       process_report(severity, name, id, message, a, f, filename, 



這個是在uvm_catcher中的process_report_catcher函數:

  local function int process_report_catcher();
    action_e act;
    act = this.catch();
    if(act == UNKNOWN_ACTION)
      this.uvm_report_error("RPTCTHR", {"uvm_report_this.catch() in catcher instance "this.get_name(), " must return THROW or CAUGHT"}, UVM_NONE, `uvm_file`uvm_line);
    if(m_debug_flags & DO_NOT_MODIFY) begin
      m_modified_severity    = m_orig_severity;
      m_modified_id          = m_orig_id;
      m_modified_verbosity   = m_orig_verbosity;
      m_modified_action      = m_orig_action;
      m_modified_message     = m_orig_message;
    end     
    if(act == CAUGHT  && !(m_debug_flags & DO_NOT_CATCH)) begin
      return 0;
    end  
    return 1;
  endfunction  






相關文章
相關標籤/搜索