[CU]uvm lab3-router
注1:uvm lab1 - __见贤思齐 - 博客园 (cnblogs.com)
注2:uvm lab2 - __见贤思齐 - 博客园 (cnblogs.com)
注3:结合synopsys uvm lab guide阅读;
注4:uvm1.1 lab链接第三方资源 – 路科验证 (rockeric.com).
注5:synopsys uvm1.2 lab guide - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
注6:uvm1.2 lab链接UVM1.2 Lab验证资料(入门必备) - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
1.test.sv
1 program automatic test; 2 import uvm_pkg::*; 3 4 `include "test_collection.sv" 5 6 initial begin 7 $timeformat(-9, 1, "ns", 10); 8 run_test(); 9 end 10 11 endprogram
2.test_collection.sv(派生于uvm_test)
1 `ifndef TEST_COLLECTION__SV 2 `define TEST_COLLECTION__SV 3 4 `include "router_env.sv" 5 6 class test_base extends uvm_test; 7 `uvm_component_utils(test_base) 8 9 router_env env; 10 11 function new(string name, uvm_component parent); 12 super.new(name, parent); 13 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 14 endfunction 15 16 virtual function void build_phase(uvm_phase phase); 17 super.build_phase(phase); 18 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 19 env = router_env::type_id::create("env", this); 20 endfunction 21 22 virtual function void final_phase(uvm_phase phase); 23 super.final_phase(phase); 24 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 25 uvm_top.print_topology(); 26 27 factory.print(); 28 endfunction 29 endclass 30 31 `include "packet_da_3.sv" 32 33 class test_da_3_inst extends test_base; 34 `uvm_component_utils(test_da_3_inst) 35 36 function new(string name, uvm_component parent); 37 super.new(name, parent); 38 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 39 endfunction 40 41 virtual function void build_phase(uvm_phase phase); 42 super.build_phase(phase); 43 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 44 set_inst_override_by_type("env.i_agent*.seqr.*", packet::get_type(), packet_da_3::get_type()); 45 endfunction 46 endclass 47 48 class test_da_3_type extends test_base; 49 `uvm_component_utils(test_da_3_type) 50 51 function new(string name, uvm_component parent); 52 super.new(name, parent); 53 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 54 endfunction 55 56 virtual function void build_phase(uvm_phase phase); 57 super.build_phase(phase); 58 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 59 set_type_override_by_type(packet::get_type(), packet_da_3::get_type()); 60 endfunction 61 endclass 62 63 // Lab 3 - Task 4 64 // 65 // In this task, you are expected to code the entire test class definition. 66 // Reference the above code or the lecture material if you have questions on syntax. 67 // 68 // Create a test called test_da_3_seq. 69 // 70 // In the build phase, enable only destination address 3 and set item_count to 20. 71 // (via the sequencer because, in UVM, all configuration must be done through component path) 72 // 73 // uvm_config_db#(bit[15:0])::set(this, "env.i_agent*.seqr", "da_enable", 16'h0008); 74 // uvm_config_db#(int)::set(this, "env.i_agent*.seqr", "item_count", 20); 75 // 76 // Don't forget you will need to implement the uvm_component_utils macro and the constructor 77 // 78 // ToDo 79 80 class test_da_3_seq extends test_base; 81 `uvm_component_utils(test_da_3_seq) 82 83 function new(string name, uvm_component parent); 84 super.new(name, parent); 85 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 86 endfunction 87 88 virtual function void build_phase(uvm_phase phase); 89 super.build_phase(phase); 90 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 91 uvm_config_db#(bit[15:0])::set(this, "env.i_agent*.seqr", "da_enable", 16'h0008); //见packet_sequence.sv; 92 uvm_config_db#(int)::set(this, "env.i_agent*.seqr", "item_count", 20); 93 endfunction 94 endclass 95 96 97 `endif
3.router_env.sv (派生于uvm_env)
1 `ifndef ROUTER_ENV__SV 2 `define ROUTER_ENV__SV 3 4 `include "input_agent.sv" 5 6 // Lab 3 - Task 7, Step 2 7 // 8 // To save lab time, the reset agent with its sequencer, driver and monitor has been done 9 // for you. You will need to add an instance of it in the environment. 10 // 11 // Include the reset_agent.sv file 12 // 13 // ToDo 14 `include "reset_agent.sv" 15 16 17 class router_env extends uvm_env; 18 input_agent i_agent; 19 20 // Lab 3 - Task 7, Step 3 21 // 22 // Create an instance of reset_agent, call it r_agent 23 // 24 // ToDo 25 reset_agent r_agent; 26 27 28 `uvm_component_utils(router_env) 29 30 function new(string name, uvm_component parent); 31 super.new(name, parent); 32 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 33 endfunction 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 i_agent = input_agent::type_id::create("i_agent", this); 40 uvm_config_db #(uvm_object_wrapper)::set(this, "i_agent.seqr.main_phase", "default_sequence", packet_sequence::get_type()); 41 42 // Lab 3 - Task 7, Step 4 43 // 44 // Construct the r_agent object with the proxy create() method. 45 // 46 // ToDo 47 r_agent = reset_agent::type_id::create("r_agent", this); 48 49 50 // Lab 3 - Task 7, Step 5 51 // 52 // Configure r_agent's seqr to execute reset_sequence at reset_phase: 53 // uvm_config_db #(uvm_object_wrapper)::set(this, "r_agent.seqr.reset_phase", "default_sequence", reset_sequence::get_type()); 54 // 55 // ToDo 56 uvm_config_db #(uvm_object_wrapper)::set(this, "r_agent.seqr.reset_phase", "default_sequence", reset_sequence::get_type()); 57 58 59 endfunction 60 61 endclass 62 63 `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.1 driver.sv(派生于uvm_driver)
1 `ifndef DRIVER__SV
2 `define DRIVER__SV
3
4 class driver extends uvm_driver #(packet);
5 `uvm_component_utils(driver)
6
7 function new(string name, uvm_component parent);
8 super.new(name, parent);
9 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
10 endfunction
11
12 virtual task run_phase(uvm_phase phase);
13 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
14 forever begin
15 seq_item_port.get_next_item(req);
16
17 // Lab 3 - Task 5, Step 4
18 // Change the req.print() statement into a uvm_info message statement:
19 //
20 // ToDo
21 `uvm_info("DRV_RUN", {"\n", req.sprint()}, UVM_MEDIUM);
22
23 seq_item_port.item_done();
24 end
5.reset_agent.sv(派生于uvm_agent)
1 `ifndef RESET_AGENT__SV 2 `define RESET_AGENT__SV 3 4 `include "reset_sequence.sv" 5 6 typedef uvm_sequencer#(reset_tr) reset_sequencer; 7 8 class reset_agent extends uvm_agent; 9 reset_sequencer seqr; 10 11 `uvm_component_utils(reset_agent) 12 13 function new(string name, uvm_component parent); 14 super.new(name, parent); 15 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 16 endfunction: new 17 18 function void build_phase(uvm_phase phase); 19 super.build_phase(phase); 20 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 21 22 seqr = reset_sequencer::type_id::create("seqr", this); 23 endfunction: build_phase 24 endclass 25 26 `endif
6.packet_sequence.sv(派生于uvm_sequence)
1 `ifndef PACKET_SEQUENCE__SV 2 `define PACKET_SEQUENCE__SV 3 4 `include "packet.sv" 5 6 class packet_sequence extends uvm_sequence #(packet); 7 8 // Lab 3 - Task 2, Step 2 9 // Create the new fields as shown below. 10 // 11 // int item_count = 10; 12 // int port_id = -1; 13 // bit[15:0] da_enable = '1; 14 // int valid_da[$]; 15 // 16 // The intent of the item_count field is to control how many packet objects 17 // to create and pass on to the driver per execution of the body() task. 18 // 19 // The intent of the port_id field is to constrain the packet's source address. 20 // 21 // The lab DUT has 16 input ports needing to be tested. Each input agent created 22 // to drive a particular port will be assigned a port_id specifying which port it 23 // should exercise. Because of this, the sequence within an input agent when 24 // when generating packets need to constrain the packet's source address. 25 // 26 // The rule for constrainint the source address shall be as follows: 27 // If port_id is inside the range of {[0:15]}, then the source address shall be port_id. 28 // If port_id is -1 (unconfigured), the source address shall be in the range of {[0:15]} 29 // port_id outside the range of {-1, {[0:15]} is not allowed. 30 // 31 // The intent of the da_enable fields is to enable corresponding destination 32 // addresses to be generated. A value of 1 in a particular bit position will 33 // enable the corresponding address as a valid address to generate. A value of 0 34 // prohibit the corresponding address from being generated. 35 // 36 // Example: if the sequence were to be configured to generate only packets 37 // for destination address 3, then the da_enable need to be configured as: 38 // 16'b0000_0000_0000_1000 39 // 40 // Note that the default value is '1, meaning that all addresses are enabled. 41 // 42 // To simplify the constraint coding, a corresponding set of queue, valid_da 43 // is needed. This queue is populated based on the value of da_enable. 44 // 45 // Example: if da_enable is 16'b0000_0011_0000_1000, then the valid_da queue 46 // will populated with 3, 8 and 9. 47 // 48 // ToDo 49 int item_count = 10; 50 int port_id = -1; 51 bit[15:0] da_enable = '1; 52 int valid_da[$]; 53 54 55 // 56 // To save lab time, the `uvm_object_utils macro is filled in for you. 57 // 58 `uvm_object_utils_begin(packet_sequence) 59 `uvm_field_int(item_count, UVM_ALL_ON) 60 `uvm_field_int(port_id, UVM_ALL_ON) 61 `uvm_field_int(da_enable, UVM_ALL_ON) 62 `uvm_field_queue_int(valid_da, UVM_ALL_ON) 63 `uvm_object_utils_end 64 65 // 66 // The valid_da queue must be populated with legal set of addresses as specified 67 // by the da_enable field. Since the first thing that the sequencer performs is 68 // the randomization of its default_sequence, a good place to retreive the configuration 69 // fields and populate the valid_da queue is in the pre_randomize() method. 70 // 71 // To simplify your code development, the code is done for you as follows: 72 // 73 function void pre_randomize(); 74 uvm_config_db#(int)::get(m_sequencer, "", "item_count", item_count); 75 uvm_config_db#(int)::get(m_sequencer, "", "port_id", port_id); 76 uvm_config_db#(bit[15:0])::get(m_sequencer, "", "da_enable", da_enable); 77 if (!(port_id inside {-1, [0:15]})) begin 78 `uvm_fatal("CFGERR", $sformatf("Illegal port_id value of %0d", port_id)); 79 end 80 81 valid_da.delete(); 82 for (int i=0; i<16; i++) 83 if (da_enable[i]) 84 valid_da.push_back(i); 85 endfunction 86 87 function new(string name = "packet_sequence"); 88 super.new(name); 89 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 90 endfunction 91 92 task body(); 93 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 94 95 if (starting_phase != null) 96 starting_phase.raise_objection(this); 97 98 // Lab 3 - Task 2, Step 3 99 // Instead of hard coding the number of item to be generated, replace the 100 // hard-coded value 10 in the repeat() statement to use item_count. 101 // 102 // ToDo 103 repeat(item_count) begin 104 105 106 // Lab 3 - Task 2, Step 3 107 // 108 // As stated in the comment at the beginning of the file. If the port_id is unconfigured (-1) 109 // then the legal values for the source address shall be in the range of {[0:15]}. If the 110 // port_id is configured, then the source address shall be port_id. This will give the test 111 // the ability to test whether or not the driver drops the packet it is not configured to drive. 112 // 113 // For destination address, the legal values should be picked out of the valid_da array. 114 // 115 // Change the following `uvm_do(req) macro to: 116 // `uvm_do_with(req, {if (port_id == -1) sa inside {[0:15]}; else sa == port_id; da inside valid_da;}); 117 // 118 // ToDo 119 `uvm_do_with(req, {if (port_id == -1) sa inside {[0:15]}; else sa == port_id; da inside valid_da;}); 120 121 122 end 123 124 if (starting_phase != null) 125 starting_phase.drop_objection(this); 126 endtask 127 128 endclass 129 130 `endif
6.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.2 packet_da_3.sv(派生于uvm_sequence_item)
1 `ifndef PACKET_DA_3__SV 2 `define PACKET_DA_3__SV 3 4 class packet_da_3 extends packet; 5 `uvm_object_utils(packet_da_3) 6 7 // Lab 2 - set the constraint for destination address (da) to 3 8 // 9 // ToDo 10 constraint da_3 { 11 da == 3; 12 } 13 14 function new(string name = "packet_da_3"); 15 super.new(name); 16 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 17 endfunction 18 endclass 19 20 `endif
7.reset_sequence.sv(派生于uvm_sequence_item)
1 `ifndef RESET_SEQUENCE__SV 2 `define RESET_SEQUENCE__SV 3 4 class reset_tr extends uvm_sequence_item; 5 typedef enum {ASSERT, DEASSERT} kind_e; 6 rand kind_e kind; 7 rand int unsigned cycles = 1; 8 9 `uvm_object_utils_begin(reset_tr) 10 `uvm_field_enum(kind_e, kind, UVM_ALL_ON) 11 `uvm_field_int(cycles, UVM_ALL_ON) 12 `uvm_object_utils_end 13 14 function new(string name = "reset_tr"); 15 super.new(name); 16 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 17 endfunction: new 18 endclass 19 20 class reset_sequence extends uvm_sequence#(reset_tr); 21 `uvm_object_utils(reset_sequence) 22 23 function new(string name = "reset_sequence"); 24 super.new(name); 25 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 26 endfunction 27 28 task body(); 29 `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH); 30 31 if (starting_phase != null) 32 starting_phase.raise_objection(this); 33 34 `uvm_info("RESET", "Executing Reset", UVM_MEDIUM); 35 36 if (starting_phase != null) 37 starting_phase.drop_objection(this); 38 endtask 39 endclass 40 41 `endif