UVM——callback机制应用示例
对应代码:
1、在UVM组件中主操作函数或者任务之前或者之后内嵌callback函数或任务
1 class driver extends uvm_driver #(transaction); 2 `uvm_register_cb(driver, driver_callback); //登记 3 ... 4 virtual task run_phase(uvm_phase phase)l 5 forever begin 6 seq_item_port.get_next_item(req); 7 `uvm_do_callbacks(driver, driver_callback, pre_send(this, req)); //使用宏嵌入函数或任务 8 send(req); 9 `uvm_do_callbacks(driver, driver_callback, post_send(this, req)); // 就是在哪个类中,使用哪个callback,以及这个callback的哪个方法 10 seq_item_port.item_done(); 11 end 12 13 endclass: drvier 14
2、创建一个uvm_callback 空壳类(facade class)
1 typedef class driver; 2 class driver_callback extends uvm_callback; 3 function new(string name = "driver_callback"); 4 super.new(name); 5 endfunction: new 6 7 virtual task pre_send(driver drv, transaction tr); //这是注入错误的 8 endtask 9 10 virtual task post_send(driver drv, transaction tr); //这是用来收集覆盖率的 11 endtask 12 endcalss: driver_callback
3、从callback空壳类扩展
①注入错误
1 class driver_error_callback extends driver_callback; 2 virtual task pre_send(driver drv, transaction tr); 3 drv.req.payload.delete() 4 endtask: pre_send 5 endclass: driver_error_callback
②收集覆盖率
1 class driver_cov_callback extends driver_callback; 2 covergroup drv_cov with function sample(transaction tr); 3 coverpoint tr.sa; 4 coverpoint tr.da; 5 endcovergroup 6 7 function new(); 8 drv_cov = new(); 9 endfunction: new 10 11 virtual task post_send(driver drv, transaction tr); 12 drv_cov.sample(tr); 13 endtask: pre_send 14 endclass: driver_error_callback
4、在验证环境中创建并登记UVM callback 实例
①
1 class driver_err_test extends test_base; 2 driver_error_callback drv_err_cb; // ↓ 3 virtual function void connect_phase(uvm_phase, phase); 4 super.connect_phase(phase); 5 drv_err_cb = new(); //创建 6 uvm_callbacks #(driver, driver_callback)::add(env.drv, drv_err_cb); // 登记对象 7 uvm_callbacks #(driver, driver_callback)::display(); //方便调试 8 endfunction: connect_phase 9 endcalss: driver_err_test
②
1 class driver_cov_test extends test_base; 2 ... 3 driver_cov_callback drv_err_cb; // ↓ 4 virtual function void connect_phase(uvm_phase, phase); 5 super.connect_phase(phase); 6 drv_cov_cb = new(); //创建 7 uvm_callbacks #(driver, driver_callback)::add(env.drv, drv_cov_cb); // 登记对象 8 uvm_callbacks #(driver, driver_callback)::display(); //方便调试 9 endfunction: connect_phase 10 endcalss: driver_cov_test
这个例子就到此结束了。还有一个例子。
两个例子基本一致的,就是个别宏的使用方法有点小异。
1 `include "uvm_macros.svh" 2 3 package bus_driver_pkg; 4 5 import uvm_pkg::*; 6 7 typedef class bus_driver; 8 typedef class bus_driver_cb; 9 typedef uvm_callbacks #(bus_driver,bus_driver_cb) bus_driver_cbs_t; // 这样定义好之后,使用::add的时候就不要带那么多参数了。 10 11 class bus_tr extends uvm_transaction; 12 rand int addr; 13 rand int data; 14 virtual function string convert2string(); 15 convert2string = $sformatf("addr=%0h data=%0h",addr,data); 16 endfunction 17 endclass 18 19 virtual class bus_driver_cb extends uvm_callback; // 空壳类 20 21 virtual function bit trans_received(bus_driver driver, bus_tr tr); 22 return 0; 23 endfunction 24 25 virtual task trans_executed(bus_driver driver, bus_tr tr); 26 endtask 27 28 function new(string name="bus_driver_cb_inst"); 29 super.new(name); 30 endfunction 31 32 static string type_name = "bus_driver_cb"; 33 34 virtual function string get_type_name(); 35 return type_name; 36 endfunction 37 38 endclass 39 40 class bus_driver extends uvm_component; 41 42 uvm_blocking_put_imp #(bus_tr,bus_driver) in; 43 44 `uvm_register_cb(bus_driver, bus_driver_cb) // 注册 45 46 function new (string name, uvm_component parent=null); 47 super.new(name,parent); 48 in = new("in",this); 49 endfunction 50 51 static string type_name = "bus_driver"; 52 53 virtual function string get_type_name(); 54 return type_name; 55 endfunction 56 57 virtual function bit trans_received(bus_tr tr); 58 `uvm_do_callbacks_exit_on(bus_driver,bus_driver_cb,trans_received(this,tr),1) // 这里的callback函数用在了主任务所调用的函数里,也是可以的 59 endfunction 60 61 virtual task trans_executed(bus_tr tr); 62 `uvm_do_callbacks(bus_driver,bus_driver_cb,trans_executed(this,tr)) 63 endtask 64 65 virtual task put(bus_tr t); 66 uvm_report_info("bus_tr received",t.convert2string()); 67 if (!trans_received(t)) begin 68 uvm_report_info("bus_tr dropped", 69 "user callback indicated DROPPED\n"); 70 return; 71 end 72 #100; 73 trans_executed(t); 74 uvm_report_info("bus_tr executed",{t.convert2string(),"\n"}); 75 endtask 76 77 endclass 78 79 endpackage // bus_driver_pkg 80 81 import uvm_pkg::*; 82 import bus_driver_pkg::*; 83 84 class my_bus_driver_cb extends bus_driver_cb; //第一个重载 85 86 function new(string name="bus_driver_cb_inst"); 87 super.new(name); 88 endfunction 89 90 virtual function bit trans_received(bus_driver driver, bus_tr tr); 91 static bit drop = 0; 92 driver.uvm_report_info("trans_received_cb", 93 {" bus_driver=",driver.get_full_name()," tr=",tr.convert2string()}); 94 drop = 1 - drop; 95 return drop; 96 endfunction 97 98 virtual task trans_executed(bus_driver driver, bus_tr tr); 99 driver.uvm_report_info("trans_executed_cb", 100 {" bus_driver=",driver.get_full_name()," tr=",tr.convert2string()}); 101 endtask 102 103 virtual function string get_type_name(); 104 return "my_bus_driver_cb"; 105 endfunction 106 107 endclass 108 109 class my_bus_driver_cb2 extends bus_driver_cb; //第二个 110 111 function new(string name="bus_driver_cb_inst"); 112 super.new(name); 113 endfunction 114 115 virtual task trans_executed(bus_driver driver, bus_tr tr); 116 driver.uvm_report_info("trans_executed_cb2", 117 {" bus_driver=",driver.get_full_name()," tr=",tr.convert2string()}); 118 endtask 119 120 virtual function string get_type_name(); 121 return "my_bus_driver_cb2"; 122 endfunction 123 124 endclass 125 126 module top; 127 import uvm_pkg::*; 128 import bus_driver_pkg::*; 129 130 bus_tr tr = new; 131 bus_driver driver = new("driver"); 132 my_bus_driver_cb cb1 = new("cb1"); // 由于本例结构简单,声明实例一起完成了 133 my_bus_driver_cb2 cb2 = new("cb2"); 134 135 initial begin 136 bus_driver_cbs_t::add(driver,cb1); 137 bus_driver_cbs_t::add(driver,cb2); 138 bus_driver_cbs_t::display(); 139 for (int i=1; i<=5; i++) begin 140 tr.addr = i; 141 tr.data = 6-i; 142 driver.in.put(tr); 143 end 144 begin 145 uvm_report_server svr = uvm_report_server::get_server(); 146 svr.summarize(); 147 end 148 end 149 150 endmodule