首页 > 代码库 > UVM基础之---------uvm report 机制分析

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  






来自为知笔记(Wiz)