日常记录(62)域、phase、TLM
域的自动化
copy
copy 方法的结果如下代码:
首先是注册,注意copy方法的调用者是被赋值的对象,参数是来源的对象。
do_copy是在copy后自动执行的方法,是一个回调函数。
点击查看代码
module taa (); import uvm_pkg::*; `include "uvm_macros.svh" class box extends uvm_object; // data or class properties int length=10; typedef enum bit[3:0] { BLACK, WHITE, RED, BLUE } color_t; color_t color=BLUE; int width=5; string name="box_base"; `uvm_object_utils_begin(box) `uvm_field_int(length, UVM_ALL_ON) `uvm_field_int(width, UVM_ALL_ON) `uvm_field_enum(color_t, color, UVM_ALL_ON) `uvm_object_utils_end function void do_copy(uvm_object rhs); length = 100; endfunction: do_copy // initialization function new(); endfunction : new endclass : box initial begin box box1 = new(); box box2 = new(); box1.length = 5; box1.width = 3; box2.copy(box1); box1.print(); box2.print(); end endmodule
点击查看代码
-------------------------------- Name Type Size Value -------------------------------- <unnamed> box - @455 length integral 32 'h5 width integral 32 'h3 color color_t 4 BLUE -------------------------------- -------------------------------- Name Type Size Value -------------------------------- <unnamed> box - @456 length integral 32 'h64 width integral 32 'h3 color color_t 4 BLUE --------------------------------
compare
基本原理同copy,但是以下代码自定义了uvm_comparer,然后在compare的过程中将其传入,可修改显示的不匹配个数控制。
点击查看代码
module taa (); import uvm_pkg::*; `include "uvm_macros.svh" class box extends uvm_object; // data or class properties int length=10; typedef enum bit[3:0] { BLACK, WHITE, RED, BLUE } color_t; color_t color=BLUE; int width=5; string name="box_base"; `uvm_object_utils_begin(box) `uvm_field_int(length, UVM_ALL_ON) `uvm_field_int(width, UVM_ALL_ON) `uvm_field_enum(color_t, color, UVM_ALL_ON) `uvm_object_utils_end endclass : box initial begin box box1 = new(); box box2 = new(); uvm_comparer cmpr = new(); cmpr.show_max = 2; box1.length = 'h5; box1.width = 'h3; box2.length = 'h51; box2.width = 'h11; if(box2.compare(box1, cmpr)) begin $info("same"); end else begin $info("not same"); end end endmodule
点击查看代码
UVM_INFO @ 0: reporter [MISCMP] Miscompare for <object>.length: lhs = 'h51 : rhs = 'h5 UVM_INFO @ 0: reporter [MISCMP] Miscompare for <object>.width: lhs = 'h11 : rhs = 'h3 UVM_INFO @ 0: reporter [MISCMP] 2 Miscompare(s) for object @455 vs. @456 Info: "taa.sv", 36: taa: at time 0 not same
在调用print的过程中,使用uvm_default_printer,默认为table的形式,可以将其它的printer赋值到uvm_default_printer,实现打印格式控制。
uvm_default_printer uvm_default_line_printer uvm_default_tree_printer
此外,同uvm_comparer一样,可以定义uvm_table_printer等,修改其中的knobs.full_name,调用print时候传入,完成打印过程控制。
phase概念
内部概念
schedule是包括phase的关联数组
domain内置一个schedule
schedule所属类uvm_schedule和domain所属类uvm_domain都是继承于uvm_phase
编写规范
由于未来可能对run_phase中的reset、configure、main、shutdown的废除,建议使用run_phase,并使用fork-join语句块实现同步。
OVM的历史遗留变量传递
传递方法
不同于uvm的set_config_db,ovm使用set_config_int、set_config_string、get_config_int、get_config_string等方法
隐式get
可能不用get函数也可获得set过的数据。
但是依赖于具体的field_automation、然后需要调用suoer.build_phase,即可匹配同名,自动获取值。
实例代码
以下代码实现了ovm的数值传递。
- string类型的数据没有注册到automation,是手动set和get的
- int的val1类型是注册到automation,然后通过调用父类自动get的,因此前后都是100
- int的val3类型是注册到automation,但是值和字符串的域不一样,无法赋值,只能通过手动方式获取值
另外,如果get_config_int改成了get_config_string,类型不一致不会报错,但是无法获得值。
点击查看代码
module set_config_variable; import uvm_pkg::*; `include "uvm_macros.svh" class comp1 extends uvm_component; int val1 = 1; string str1 = "null"; int val2 = 123; `uvm_component_utils_begin(comp1) `uvm_field_int(val1, UVM_ALL_ON) `uvm_field_int(val2, UVM_ALL_ON) `uvm_component_utils_end function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); `uvm_info("SETVAL", $sformatf("val1 is %d before get", val1), UVM_LOW) `uvm_info("SETVAL", $sformatf("val2 is %d before get", val2), UVM_LOW) `uvm_info("SETVAL", $sformatf("str1 is %s before get", str1), UVM_LOW) get_config_string("str1", str1); /* get_config_int("val3", val2); */ `uvm_info("SETVAL", $sformatf("val1 is %d after get", val1), UVM_LOW) `uvm_info("SETVAL", $sformatf("val2 is %d after get", val2), UVM_LOW) `uvm_info("SETVAL", $sformatf("str1 is %s after get", str1), UVM_LOW) endfunction endclass class test1 extends uvm_test; `uvm_component_utils(test1) comp1 c1; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); uvm_component::print_config_matches = 1; set_config_int("c1", "val1", 100); set_config_string("c1", "str1", "comp1"); set_config_int("c1", "val3", 11); c1 = comp1::type_id::create("c1", this); endfunction endclass initial begin run_test("test1"); end endmodule
信息打印
信息打印控制
以下代码实现了打印信息的控制过程。
对于写入文件,建立好文件,然后调用set_report_default_file。
然后通过控制函数,实现对打印信息的控制过程。控制函数会有很多很多。
点击查看代码
module object_report; import uvm_pkg::*; `include "uvm_macros.svh" class test1 extends uvm_test; integer f; `uvm_component_utils(test1) function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); f = $fopen("logfile", "w"); set_report_default_file(f); set_report_severity_action(UVM_INFO, UVM_DISPLAY | UVM_LOG); set_report_severity_action(UVM_WARNING, UVM_DISPLAY | UVM_LOG); set_report_severity_action(UVM_ERROR, UVM_DISPLAY | UVM_LOG | UVM_COUNT); set_report_severity_action(UVM_FATAL, UVM_DISPLAY | UVM_LOG | UVM_STOP); set_report_verbosity_level(UVM_LOW); endfunction task run_phase(uvm_phase phase); uvm_report_info("RUN", "info1", UVM_MEDIUM); uvm_report_info("RUN", "info2", UVM_LOW); uvm_report_warning("RUN", "warning1", UVM_LOW); uvm_report_error("RUN", "error1", UVM_LOW); uvm_report_error("RUN", "error2", UVM_HIGH); uvm_report_error("RUN", "error3", UVM_LOW); endtask function void report_phase(uvm_phase phase); $fclose(f); endfunction endclass initial begin run_test("test1"); end endmodule
打印前控制的HOOK
如下:
默认UVM_LOW以下打印,然后是UVM_CALL_HOOK使能。、
点击查看代码
module report_hook; import uvm_pkg::*; `include "uvm_macros.svh" class test1 extends uvm_test; integer f; `uvm_component_utils(test1) function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); set_report_severity_action(UVM_ERROR, UVM_DISPLAY | UVM_CALL_HOOK); set_report_verbosity_level(UVM_LOW); endfunction task run_phase(uvm_phase phase); uvm_report_info("RUN", "info1", UVM_MEDIUM); uvm_report_info("RUN", "info2", UVM_LOW); uvm_report_warning("RUN", "warning1", UVM_LOW); uvm_report_error("RUN", "error1", UVM_LOW); uvm_report_error("RUN", "error2", UVM_HIGH); uvm_report_error("RUN", "error3", UVM_LOW); endtask function bit report_hook(string id, string message, int verbosity, string filename, int line); uvm_report_info("RPTHOOK", $sformatf("%s : %s", id, message), UVM_LOW); return 1; endfunction function bit report_error_hook(string id, string message, int verbosity, string filename, int line); uvm_report_info("ERRHOOK", $sformatf("%s : %s", id, message), UVM_LOW); return 1; endfunction endclass initial begin run_test("test1"); end endmodule
uvm组件
driver的seq
uvm_seq_item_pull_port seq_item_port
uvm_algorithm_comparator
更高端的通用比较类,需要实现compare、conver2string、transform函数。
双向通信
点击查看代码
module tlm_transport; import uvm_pkg::*; `include "uvm_macros.svh" class itrans extends uvm_transaction; int id; int data; function new(string name, uvm_component parent); super.new(name, parent); endfunction endclass class otrans extends uvm_transaction; int id; int data; function new(string name, uvm_component parent); super.new(name, parent); endfunction endclass class comp1 extends uvm_component; uvm_blocking_transport_port #(itrans, otrans) bt_port; `uvm_component_utils(comp1) function new(string name, uvm_component parent); super.new(name, parent); bt_port = new("bt_port", this); endfunction task run_phase(uvm_phase phase); itrans itr; otrans otr; int trans_num = 6; for(int i=0; i<trans_num; i++) begin itr = new("itr", this); itr.id = i; itr.data = 'h10 + i ; this.bt_port.transport(itr, otr); `uvm_info("TRSPT", $sformatf("put itrans id: 'h%0x , data: 'h%0x | get otrans id: 'h%0x , data: 'h%0x ", itr.id, itr.data, otr.id, otr.data), UVM_LOW) end endtask endclass class comp2 extends uvm_component; uvm_blocking_transport_imp #(itrans, otrans, comp2) bt_imp; `uvm_component_utils(comp2) function new(string name, uvm_component parent); super.new(name, parent); bt_imp = new("bt_imp", this); endfunction task transport(itrans req, output otrans rsp); rsp = new("rsp", this); rsp.id = req.id; rsp.data = req.data << 8; endtask endclass class env1 extends uvm_env; comp1 c1; comp2 c2; `uvm_component_utils(env1) function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); c1 = comp1::type_id::create("c1", this); c2 = comp2::type_id::create("c2", this); endfunction: build_phase function void connect_phase(uvm_phase phase); super.connect_phase(phase); c1.bt_port.connect(c2.bt_imp); endfunction: connect_phase endclass class test1 extends uvm_test; `uvm_component_utils(test1) env1 env; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); env = env1::type_id::create("env", this); endfunction endclass initial begin run_test("test1"); end endmodule // UVM_INFO @ 0: reporter [RNTST] Running test test1... // UVM_INFO @ 0: uvm_test_top.env.c1 [TRSPT] put itrans id: 'h0 , data: 'h10 | get otrans id: 'h0 , data: 'h1000 // UVM_INFO @ 0: uvm_test_top.env.c1 [TRSPT] put itrans id: 'h1 , data: 'h11 | get otrans id: 'h1 , data: 'h1100 // UVM_INFO @ 0: uvm_test_top.env.c1 [TRSPT] put itrans id: 'h2 , data: 'h12 | get otrans id: 'h2 , data: 'h1200 // UVM_INFO @ 0: uvm_test_top.env.c1 [TRSPT] put itrans id: 'h3 , data: 'h13 | get otrans id: 'h3 , data: 'h1300 // UVM_INFO @ 0: uvm_test_top.env.c1 [TRSPT] put itrans id: 'h4 , data: 'h14 | get otrans id: 'h4 , data: 'h1400 // UVM_INFO @ 0: uvm_test_top.env.c1 [TRSPT] put itrans id: 'h5 , data: 'h15 | get otrans id: 'h5 , data: 'h1500
TLM2.0
特点
双向通信,支持blocking和nonblocking两种方式。
blocking方式需要在一次传输过程中request和response,实现方法为:b_transport,对应任务:
task b_transport(trans, delay)
nonblocking方式将request和response分为两个独立的单向传输,两个传输整体视为一个传输过程。
实现方法为:nb_transport_fw, nb_transport_bw。
对应函数:
function uvm_tlm_sync_e nb_transport_fw(trans, p, delay); function uvm_tlm_sync_e nb_transport_bw(trans, p, delay);
trans:uvm_tlm_generic_payload类,唯一的trans
p为:做状态同步的部分
fw:request发送通道
bw: response发送通道
delay: uvm_til_time类,标定延迟时间
端口
端口是继承于uvm_port_base的,
blocking方式的代码
点击查看代码
module tlm2_socket; import uvm_pkg::*; `include "uvm_macros.svh" class comp1 extends uvm_component; uvm_tlm_b_initiator_socket b_ini_skt; `uvm_component_utils(comp1) function new(string name, uvm_component parent); super.new(name, parent); b_ini_skt = new("b_ini_skt", this); endfunction task run_phase(uvm_phase phase); byte unsigned data[] = {1, 2, 3, 4, 5, 6, 7, 8}; uvm_tlm_generic_payload pl = new("pl"); uvm_tlm_time delay = new("delay"); pl.set_address('h0000F000); pl.set_data_length(8); pl.set_data(data); pl.set_byte_enable_length(8); pl.set_write(); delay.incr(0.3ns, 1ps); `uvm_info("INITRSP", $sformatf("initiated a trans at %0d ps", $realtime()), UVM_LOW) b_ini_skt.b_transport(pl, delay); endtask endclass class comp2 extends uvm_component; uvm_tlm_b_target_socket #(comp2) b_tgt_skt; `uvm_component_utils(comp2) function new(string name, uvm_component parent); super.new(name, parent); b_tgt_skt = new("b_tgt_skt", this); endfunction task b_transport(uvm_tlm_generic_payload pl, uvm_tlm_time delay); `uvm_info("TGTTRSP", $sformatf("received a trans at %0d ps", $realtime()), UVM_LOW) pl.print(); #(delay.get_realtime(1ps)); pl.set_response_status(UVM_TLM_OK_RESPONSE); `uvm_info("TGTTRSP", $sformatf("completed a trans at %0d ps", $realtime()), UVM_LOW) pl.print(); endtask endclass class env1 extends uvm_env; comp1 c1; comp2 c2; `uvm_component_utils(env1) function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); c1 = comp1::type_id::create("c1", this); c2 = comp2::type_id::create("c2", this); endfunction: build_phase function void connect_phase(uvm_phase phase); super.connect_phase(phase); c1.b_ini_skt.connect(c2.b_tgt_skt); endfunction: connect_phase endclass class test1 extends uvm_test; `uvm_component_utils(test1) env1 env; function new(string name, uvm_component parent); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); env = env1::type_id::create("env", this); endfunction task run_phase(uvm_phase phase); super.run_phase(phase); phase.raise_objection(this); #1us; phase.drop_objection(this); endtask endclass initial begin run_test("test1"); end endmodule
运行命令
vcs -sverilog -R -ntb_opts uvm-1.1 -timescale="1ps/1ps" taa.sv
运行结果:
点击查看代码
UVM_INFO @ 0: reporter [RNTST] Running test test1... UVM_INFO taa.sv(22) @ 0: uvm_test_top.env.c1 [INITRSP] initiated a trans at 0 ps UVM_INFO taa.sv(35) @ 0: uvm_test_top.env.c2 [TGTTRSP] received a trans at 0 ps ------------------------------------------------------------------------------- Name Type Size Value ------------------------------------------------------------------------------- pl uvm_tlm_generic_payload - @505 address integral 64 'hf000 command uvm_tlm_command_e 32 UVM_TLM_WRITE_COMMAND response_status uvm_tlm_response_status_e 32 UVM_TLM_INCOMPLETE_RESPONSE streaming_width integral 32 'h0 data darray(byte) 8 - [0] byte 8 'h01 x [1] byte 8 'h02 x [2] byte 8 'h03 x [3] byte 8 'h04 x [4] byte 8 'h05 x [5] byte 8 'h06 x [6] byte 8 'h07 x [7] byte 8 'h08 x extensions aa(obj,obj) 0 - ------------------------------------------------------------------------------- UVM_INFO taa.sv(39) @ 300: uvm_test_top.env.c2 [TGTTRSP] completed a trans at 300 ps ------------------------------------------------------------------------- Name Type Size Value ------------------------------------------------------------------------- pl uvm_tlm_generic_payload - @505 address integral 64 'hf000 command uvm_tlm_command_e 32 UVM_TLM_WRITE_COMMAND response_status uvm_tlm_response_status_e 32 UVM_TLM_OK_RESPONSE streaming_width integral 32 'h0 data darray(byte) 8 - [0] byte 8 'h01 x [1] byte 8 'h02 x [2] byte 8 'h03 x [3] byte 8 'h04 x [4] byte 8 'h05 x [5] byte 8 'h06 x [6] byte 8 'h07 x [7] byte 8 'h08 x extensions aa(obj,obj) 0 - ------------------------------------------------------------------------- UVM_INFO /home/synopsys/vcs-mx/O-2018.09-1/etc/uvm-1.1/base/uvm_objection.svh(1273) @ 1000000: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase --- UVM Report Summary --- ** Report counts by severity UVM_INFO : 5 UVM_WARNING : 0 UVM_ERROR : 0 UVM_FATAL : 0 ** Report counts by id [INITRSP] 1 [RNTST] 1 [TEST_DONE] 1 [TGTTRSP] 2 $finish called from file "/home/synopsys/vcs-mx/O-2018.09-1/etc/uvm-1.1/base/uvm_root.svh", line 439. $finish at simulation time 1000000
Le vent se lève! . . . il faut tenter de vivre!
Le vent se lève! . . . il faut tenter de vivre!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2019-02-24 蚂蚁森林自动收能量的最新脚本