[CU]uvm lab1-router
注1:lab1相应的makefile见IC仿真makefile示例3 - __见贤思齐 - 博客园 (cnblogs.com);
注2:结合synopsys uvm lab guide阅读;
注3:uvm1.1 lab链接第三方资源 – 路科验证 (rockeric.com).
注4:synopsys uvm1.2 lab guide - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
注5:uvm1.2 lab链接UVM1.2 Lab验证资料(入门必备) - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
学习目标
(1) 创建一个简单的uvm test(需要使用uvm基类和uvm宏);
(2) report messages的使用;
(3) 编译test;
(4) 仿真并观察结果;
(5) 为test添加env组件;
1.test.sv
(1) 编译命令
1 vcs -sverilog -ntb_opts uvm-1.2 test.sv
注1: -sverilog开关使能vcs识别system verilog代码;
注2: -ntb_opts uvm-1.2开关使能vcs在vcs安装目录下查找uvm_pkg;
(2) 仿真命令
1 ./simv +UVM_TESTNAME=test_base +UVM_VERBOSITY=UVM_HIGH -l simv.log
注1: 当调用run_test()时,uvm_root会读取+UVM_TESTNAME开关,然后使用factory机制根据类名创建实例;
注2: test_base的实例名为uvm_test_top;
1 program automatic test; 2 import uvm_pkg::*; 3 4 `include "test_collection.sv" 5 6 initial begin //可以放在program或module中.将testbench代码放到program中,能更好地避免竞争现象; 7 $timeformat(-9, 1, "ns", 10); 8 run_test(); 9 end 10 11 endprogram
1.1 可以把uvc中include的文件统一放置到test.sv内
1 program automatic test; 2 import uvm_pkg::*; 3 4 `include "packet.sv" 5 `include "driver.sv" 6 `include "input_agent.sv" 7 `include "router_env.sv" 8 `include "test_collection.sv" 9 10 initial begin 11 $timeformat(-9, 1, "ns", 10); 12 run_test(); 13 end 14 15 endprogram
1.2 可以把uvc文件放置与package内
1 package router_stimulus_pkg; 2 import uvm_pkg::*; 3 `include "packet.sv" 4 endpackage
1 package router_env_pkg; 2 import uvm_pkg::*; 3 `include "driver.sv" 4 `include "input_agent.sv" 5 `include "router_env.sv" 6 endpackage
1 package router_test_pkg; 2 import uvm_pkg::*; 3 import router_stimulus_pkg::*; 4 import router_env_pkg::*; 5 `include "test_collection.sv" 6 endpackage
2.test_collection.sv(派生于uvm_test)
注1:%m的使用(不推荐);
注2:uvm_printer的使用;
注3:uvm_report_enabled()函数的使用;
1 function int uvm_report_enabled(int verbosity, 2 uvm_severity severity = UVM_INFO, string id = ""); 3 if (get_report_verbosity_level(severity, id) < verbosity) 4 return 0; 5 return 1; 6 endfunction
1 if(uvm_report_enabled(UVM_MEDIUM, UVM_INFO, "TOPOLOGY")) begin 2 uvm_root::get().print_topology(); 3 end 4 5 if(uvm_report_enabled(UVM_MEDIUM, UVM_INFO, "FACTORY")) begin 6 uvm_factory::get().print(); 7 end
1 `ifndef TEST_COLLECTION__SV 2 `define TEST_COLLECTION__SV 3 4 // Lab 1: task 2, step 11 - bring in the environment class with: `include "router_env.sv" 5 // 6 // ToDo 7 `include "router_env.sv" 8 9 // Lab 1: task 1, step 2 - Declare the class test_base that extends uvm_test 10 // 11 // ToDo 12 class test_base extends uvm_test; 13 14 // Lab 1: task 1, step 3 - register the class in factory via `uvm_component_utils macro 15 // 16 // ToDo 17 `uvm_component_utils(test_base)//factory机制 18 19 // Lab 1: task 2, step 11 - Declare a handle named env of type router_env 20 // 21 // ToDo 22 router_env env; 23 24 // Lab 1: task 1, step 4 - Create the constructor with two argument: string name, and uvm_component parent 25 // Call super.new() with these two arguments 26 // Lastly, print a message with: `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 27 // 28 // ToDo 29 function new(string name, uvm_component parent); 30 super.new(name, parent); 31 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 32 endfunction: new 33 34 35 virtual function void build_phase(uvm_phase phase); 36 super.build_phase(phase); 37 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 38 39 // Lab 1: task 2, step 11 - Create a router environment object with: env = router_env::type_id::create("env", this); 40 // 41 // ToDo 42 env = router_env::type_id::create("env", this); 43 44 endfunction: build_phase 45 46 virtual function void start_of_simulation_phase(uvm_phase phase); 47 super.start_of_simulation_phase(phase); 48 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 49 50 // Lab 1: task 2, step 11 - Call uvm_top.print_topology() to the test topology 51 // Note: If you want to see the topology as a tree format try: uvm_top.print_topology(uvm_default_tree_printer); 52 // Calling print_topology without any argument defaults to: print_topology(uvm_default_table_printer); 53 // Try out both foramts to see what the differences are 54 // 55 // ToDo 56 uvm_top.print_topology();//uvm_top=uvm_root::get() 57 58 // Lab 1: task 1, step 5 - Call factory.print() to see all classes registered with the factory 59 // 60 // ToDo 61 uvm_factory::get().print(); //打印user注册的类; 62 63 endfunction: start_of_simulation_phase 64 65 endclass: test_base 66 `endif
3.router_env.sv(派生于uvm_env)
1 `ifndef ROUTER_ENV__SV 2 `define ROUTER_ENV__SV 3 4 // The files content needed by the environment must be included 5 6 `include "input_agent.sv" 7 8 9 // Lab 1 - Declare the router_env class, extended from uvm_env 10 // 11 // ToDo 12 class router_env extends uvm_env; 13 14 // Lab 1 - Create an input_agent handle called i_agent 15 // 16 // ToDo 17 input_agent i_agent; 18 19 `uvm_component_utils(router_env) 20 21 function new(string name, uvm_component parent); 22 super.new(name, parent); 23 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 24 endfunction: new 25 26 virtual function void build_phase(uvm_phase phase); 27 super.build_phase(phase); 28 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 29 30 // Lab 1 - Construct the i_agent object using the proxy create() method 31 // 32 // ToDo 33 i_agent = input_agent::type_id::create("i_agent", this); 34 35 // Lab 1 - Set the input sequencer to execute packet_sequence as the default_sequence in main_phase 36 // Use uvm_config_db #(uvm_object_wrapper)::set(this, "i_agent.seqr.main_phase", "default_sequence", packet_sequence::get_type()); 37 // 38 // ToDo 39 uvm_config_db #(uvm_object_wrapper)::set(this, "i_agent.seqr.main_phase", "default_sequence", packet_sequence::get_type()); 40 41 endfunction: build_phase 42 43 endclass: router_env 44 45 `endif
4.input_agent.sv(派生于uvm_agent)
1 `ifndef INPUT_AGENT__SV 2 `define INPUT_AGENT__SV 3 4 // The files content needed by the agent must be included 5 6 `include "packet_sequence.sv" 7 `include "driver.sv" 8 9 // Lab 1 - Use typedef to create a class called packet_sequencer from the uvm_sequencer class parameterized with packet type 10 // 11 // ToDo 12 typedef uvm_sequencer #(packet) packet_sequencer; 13 14 // Lab 1 - Declare the input_agent class, extended from uvm_agent 15 // 16 // ToDo 17 class input_agent extends uvm_agent; 18 19 // Lab 1 - Create a packet_sequencer handle, call it seqr 20 // 21 // ToDo 22 packet_sequencer seqr; 23 24 // Lab 1 - Create a driver handle, call it drv 25 // 26 // ToDo 27 driver drv; 28 29 `uvm_component_utils(input_agent) 30 31 function new(string name, uvm_component parent); 32 super.new(name, parent); 33 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 34 endfunction: new 35 36 virtual function void build_phase(uvm_phase phase); 37 super.build_phase(phase); 38 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 39 40 // Lab 1 - Construct the packet_sequencer and driver objects using the proxy create() method 41 // 42 // ToDo 43 seqr = packet_sequencer::type_id::create("seqr", this); 44 drv = driver::type_id::create("drv", this); 45 46 endfunction: build_phase 47 48 virtual function void connect_phase(uvm_phase phase); 49 super.connect_phase(phase); 50 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 51 52 // Lab 1 - Connect the seq_item_port in drv to the seqr's seq_item_export 53 // 54 // ToDo 55 drv.seq_item_port.connect(seqr.seq_item_export); 56 57 endfunction: connect_phase 58 59 endclass: input_agent 60 61 `endif
4.1driver.sv(派生于uvm_driver)
1 `ifndef DRIVER__SV 2 `define DRIVER__SV 3 4 // Lab 1 - Declare a class driver that extends uvm_driver processing packet type 5 // 6 // ToDo 7 class driver extends uvm_driver #(packet); 8 9 // Since the factory registration and the constructor are the same as what 10 // you have already done. There is no learning benefit in re-typing them. 11 // These are entered for you in all subsequence tasks and labs. 12 `uvm_component_utils(driver) 13 14 function new(string name, uvm_component parent); 15 super.new(name, parent); 16 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 17 endfunction: new 18 19 virtual task run_phase(uvm_phase phase); 20 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 21 forever begin 22 // seq_item_port is built into the uvm_driver base class 23 // It is typically used to pull a sequence_item from the sequencer connected to the driver 24 // You will be doing the driver to sequencer connection in the environment 25 seq_item_port.get_next_item(req); 26 27 // Lab 1 - Call the req object's print() method to display content 28 // 29 // ToDo 30 req.print(); 31 32 // Once the driver finishes processing the requested sequence item, the driver must call item_done() 33 // to indicate to the sequencer that the sequence item has completed processing 34 seq_item_port.item_done(); 35 end 36 endtask: run_phase 37 38 endclass: driver 39 40 `endif
5.packet_sequence.sv(派生于uvm_sequence)
1 `ifndef PACKET_SEQUENCE__SV 2 `define PACKET_SEQUENCE__SV 3 4 `include "packet.sv" 5 6 // Lab 1 - Declare the class packet_sequence that extends uvm_sequence typed to packet 7 // 8 // ToDo 9 class packet_sequence extends uvm_sequence #(packet); 10 11 12 // Since the factory registration and the constructor are the same as what 13 // you have already done. There is no learning benefit in re-typing them. 14 // These are entered for you in all subsequence tasks and labs. 15 16 `uvm_object_utils(packet_sequence) 17 18 function new(string name = "packet_sequence"); 19 super.new(name); 20 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 21 endfunction: new 22 23 // Lab 1 - Create the body task with no argument 24 // Lab 1 - Add trace statement: `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 25 // Lab 1 - Check to see if there is a starting phase 26 // Lab 1 - If yes, raise the phase objection 27 // Lab 1 - Then, generate 10 random packets 28 // Lab 1 - When done, drop the phase objection 29 // Lab 1 - Reference the lecture slides for exact syntax 30 // 31 // ToDo 32 virtual task body(); 33 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 34 if (starting_phase != null) 35 starting_phase.raise_objection(this); 36 repeat(10) begin 37 `uvm_do(req); 38 end 39 if (starting_phase != null) 40 starting_phase.drop_objection(this); 41 endtask: body 42 43 endclass: packet_sequence 44 45 `endif
5.1 packet.sv(派生于uvm_sequence_item)
1 `ifndef PACKET__SV 2 `define PACKET__SV 3 4 // Lab 1 - Declare the class packet that extends uvm_sequence_item 5 // 6 // ToDo 7 class packet extends uvm_sequence_item; 8 9 // Lab 1 - Declare the random 4-bit sa and da fields 10 // 11 // ToDo 12 rand bit [3:0] sa, da; 13 14 // Lab 1 - Declare the random 8-bit payload queue 15 // 16 // ToDo 17 rand bit[7:0] payload[$]; 18 19 `uvm_object_utils_begin(packet) 20 `uvm_field_int(sa, UVM_ALL_ON | UVM_NOCOMPARE) 21 `uvm_field_int(da, UVM_ALL_ON) 22 `uvm_field_queue_int(payload, UVM_ALL_ON) 23 `uvm_object_utils_end 24 25 constraint valid { 26 payload.size inside {[1:10]}; 27 } 28 29 // Lab 1 - Create the constructor with one argument: string name="packet" 30 // Lab 1 - Call super.new() with this argument 31 // Lab 1 - Lastly, print a message with: 32 // Lab 1 - `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 33 // 34 // ToDo 35 function new(string name = "packet"); 36 super.new(name); 37 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 38 endfunction: new 39 40 41 endclass: packet 42 `endif
6.makefile在uvm lab1中的应用
(1) make
(2) make verbosity=UVM_HIGH
(3) make plus=uvm_set_verbosity=\*,TRACE,UVM_DEBUG,time,0
(4) make verbosity=UVM_HIGH plus=uvm_set_verbosity=\*,TOPOLOGY,UVM_NONE,time,0