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