uvm通信-uvc通信方式二之analysis_port/export/imp
1.analysis端口(ap与imp)
(1) analysis_port和analysis_export其实与put和get系列端口类似,都用于传递transaction;
(2) 一个analysis_port/analysis_export可以和多个IMP相连进行通信,但是IMP的类型必须是uvm_analysis_imp;
(3) 在analysis_imp所在的component,必须定义一个write函数.调用analysis_port.write()函数时,会依次获取与之相连的analysis_imp,并调用analysis_imp.write()函数;在analysis_imp.write()函数内,会调用analysis_imp所在uvm_component的write()函数;
注1:需要注意的是,如果analysis_imp采用的是`uvm_analysis_imp_decl(*),就不需要uvm_analysis_imp_*所在的uvm_component中有write函数,而是要有write_*函数;
注2:参考src/tlm1/uvm_analysis_port.svh & uvm-1.2/macros/uvm_tlm_defines.svh;
2.analysis端口与put/get系列端口的异同
(1) 默认情况下, 一个analysis_port (analysis_export)可以连接多个IMP(见下文示例), 也就是说, analysis_port (analysis_export)与IMP之间的通信是一对多的通信,而put和get系列端口与相应IMP的通信是一对一的通信(除非在实例化时,指定可以连接的数量).
(2) put与get系列端口都有阻塞和非阻塞的区分. 但是对于analysis_port和analysis_export来说,没有阻塞和非阻塞的概念. 因为它本身就是广播, 不用等待与其相连的其他端口的响应,所以不存在阻塞和非阻塞.
(3) 对于put系列端口, 有put、try_put、can_put等操作,对于get系列端口,有get、try_get和can_get等操作. 对于analysis_port和analysis_export来说,只有一种操作: write.
(4) 与put系列端口的PORT和EXPORT直接相连会出错的情况一样,analysis_port如果和一个analysis_export直接相连也会出错;只有在analysis_export后面再连接一级uvm_analysis_imp,才不会出错;
3.跨层次的ap,imp连接
比如o_agt的monitor与scoreboard之间的通信;
3.1连接方式一: 直接在env中跨层次引用monitor中的ap;
3.2连接方式二: 在agent中声明一个ap,并实例化它,在connect_phase将其与monitor的ap相连,并可以在env中把agent的ap直接连接到scoreboard的imp;
3.3连接方式三: 在agent中声明一个ap,但是不实例化它,让其指向monitor中的ap. 在env中可以直接连接agent的ap到scoreboard的imp;
注1:下图中有一处笔误,ap=mon.ap应当放在connect_phase或者放在build_phase中的monitor例化语句之后;
3.4 三种连接方法的对比
三种跨层次ap,imp连接方法的比较:第一种简单但层次关系不好; 第二种稍显麻烦; 第三种既具有明显的层次关系,同时较易实现.
4.一个component内多个IMP
4.1 多个IMP需要有多个write函数与之对应, 宏uvm_analysis_imp_decl可以解决一个component内多个IMP的问题.
注1:需要补充说明的是,对于blocking/nonblocking_put/get/transport/..._imp存在类似的宏,如下图所示;
4.2示例:
(1)通过宏uvm_analysis_imp_decl声明两个后缀_monitor和_model; UVM会根据这两个后缀定义两个新的IMP类-uvm_analysis_imp_monitor和uvm_analysis_imp_model;
(2)在my_scoreboard中声明并实例化uvm_analysis_imp_monitor与uvm_analysis_imp_model, 句柄分别为monitor_imp和model_imp;
(3)当与monitor_imp相连接的analysis_port执行write函数时,会自动调用write_monitor函数; 而与model_imp相连接的analysis_port执行write函数时,会自动调用write_model函数.
注1:这种情况下,uvm_analysis_imp与write函数应该还是可以使用的;
1 //示例 2 //注意:该实例中,多个imp共用同一个write函数; 3 `ifndef WB_CONMAX_SCOREBOARD__SV 4 `define WB_CONMAX_SCOREBOARD__SV 5 6 `uvm_analysis_imp_decl(_master) 7 `uvm_analysis_imp_decl(_slave) 8 9 typedef class wb_transaction; 10 class wb_conmax_scoreboard extends uvm_scoreboard; 11 12 `include "wb_conmax_env_defines.svh" 13 uvm_analysis_imp_master #(wb_transaction,wb_conmax_scoreboard) master_export[8]; 14 uvm_analysis_imp_slave #(wb_transaction,wb_conmax_scoreboard) slave_export[16]; 15 16 uvm_tlm_analysis_fifo #(wb_transaction) master_fifo[8]; 17 18 uvm_in_order_class_comparator #(wb_transaction) comparator[16]; 19 20 // Built in UVM comparator will not be used. User has to define the compare logic 21 22 `uvm_component_utils(wb_conmax_scoreboard); 23 extern function new(string name = "wb_conmax_scoreboard", 24 uvm_component parent = null); 25 extern virtual function void build_phase (uvm_phase phase); 26 extern virtual function void connect_phase (uvm_phase phase); 27 extern virtual function void end_of_elaboration_phase (uvm_phase phase); 28 extern virtual task main_phase(uvm_phase phase); 29 extern virtual function void report_phase(uvm_phase phase); 30 extern function void write_master(wb_transaction tr); 31 extern function void write_slave(wb_transaction tr); 32 extern function void report(); 33 extern function int get_addr(ref wb_transaction tr); 34 extern function bit report_info_hook(input id, string message, int verbosity, string filename, int line) ; 35 36 endclass: wb_conmax_scoreboard 37 38 function bit wb_conmax_scoreboard::report_info_hook(input id, string message, int verbosity, string filename, int line) ; 39 $display("called report hook, %d",$time); 40 return 1; 41 endfunction: report_info_hook 42 43 function wb_conmax_scoreboard::new(string name = "wb_conmax_scoreboard", 44 uvm_component parent); 45 super.new(name,parent); 46 endfunction: new 47 48 function void wb_conmax_scoreboard::build_phase(uvm_phase phase); 49 super.build_phase(phase); 50 for(int i = 0; i < 8; i = i+1) begin 51 master_export[i] = new($sformatf("master_export%d",i) , this); 52 end 53 for(int i = 0; i < 16; i = i+1) begin 54 slave_export[i] = new($sformatf("slave_export%d",i) , this); 55 comparator[i] = new($sformatf("comparator%d",i), this); 56 end 57 58 endfunction:build_phase 59 60 task wb_conmax_scoreboard::main_phase(uvm_phase phase); 61 super.main_phase(phase); 62 phase.raise_objection(this,"scbd.."); 63 phase.drop_objection(this); 64 endtask: main_phase 65 66 function void wb_conmax_scoreboard::report_phase(uvm_phase phase); 67 super.report_phase(phase); 68 endfunction:report_phase 69 70 // Master ingress functions 71 72 function void wb_conmax_scoreboard::write_master(wb_transaction tr); 73 integer master_id; 74 master_id = get_addr(tr); 75 `uvm_info("SCOREBOARD_MASTER",tr.sprint(),UVM_HIGH) 76 comparator[get_addr(tr)].before_export.write(tr); 77 endfunction 78 79 function void wb_conmax_scoreboard::write_slave(wb_transaction tr); 80 `uvm_info("SCOREBOARD_SLAVE",tr.sprint(),UVM_HIGH) 81 comparator[get_addr(tr)].after_export.write(tr); 82 endfunction 83 84 function void wb_conmax_scoreboard::report(); 85 86 foreach (comparator[i]) begin 87 `uvm_info("Scoreboard Report", 88 $sformatf("Comparator[%0d] Matches = %0d, Mismatches = %0d", 89 i, comparator[i].m_matches, comparator[i].m_mismatches), UVM_MEDIUM); 90 end 91 endfunction 92 93 function void wb_conmax_scoreboard::end_of_elaboration_phase(uvm_phase phase); 94 set_report_severity_action(UVM_INFO, UVM_DISPLAY|UVM_CALL_HOOK); 95 endfunction 96 97 function int wb_conmax_scoreboard::get_addr(ref wb_transaction tr); 98 bit [31:0] addr; 99 case(addr) inside 100 [`SLAVE0_MIN :`SLAVE0_MAX] : get_addr = 0; 101 [`SLAVE1_MIN :`SLAVE1_MAX] : get_addr = 1; 102 ... 103 [`SLAVE14_MIN :`SLAVE14_MAX] : get_addr = 14; 104 [`SLAVE15_MIN :`SLAVE15_MAX] : get_addr = 15; 105 endcase 106 107 endfunction 108 109 `endif // WB_CONMAX_SCOREBOARD__SV