[CU]uvm lab4-router

注1:uvm lab1 - __见贤思齐 - 博客园 (cnblogs.com)

注2:uvm lab2 - __见贤思齐 - 博客园 (cnblogs.com)

注3:uvm lab3 - __见贤思齐 - 博客园 (cnblogs.com)

注4:IC仿真makefile示例4 - __见贤思齐 - 博客园 (cnblogs.com)

注5:结合synopsys uvm lab guide阅读;

注6:uvm1.1 lab链接第三方资源 – 路科验证 (rockeric.com).

注7:synopsys uvm1.2 lab guide - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -

注8:uvm1.2 lab链接UVM1.2 Lab验证资料(入门必备) - IC验证资料 - EETOP 创芯网论坛 (原名:电子顶级开发网) -

学习目标

(1) 添加virtual interface的使用;

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.router_test_top.sv

 1 module router_test_top;
 2   parameter simulation_cycle = 100 ;
 3   bit  SystemClock;
 4 
 5   router_io sigs(SystemClock);
 6   host_io   host(SystemClock);
 7   router    dut(sigs, host);
 8 
 9   initial begin
10     forever #(simulation_cycle/2) SystemClock = ~SystemClock ;
11   end
12 endmodule  

2.1 router_io.sv (interface的使用)

 1 `ifndef ROUTER_IO__SV
 2 `define ROUTER_IO__SV
 3 
 4 interface router_io(input bit clk);
 5 
 6    logic  reset_n ;
 7    logic [15:0] frame_n ;
 8    logic [15:0] valid_n ;
 9    logic [15:0] din ;
10    logic [15:0] dout ;
11    logic [15:0] busy_n ;
12    logic [15:0] valido_n ;
13    logic [15:0] frameo_n ;
14 
15    clocking drvClk @(posedge clk);
16       output  reset_n;
17       output  frame_n;
18       output  valid_n;
19       output  din;
20       input   busy_n;
21    endclocking: drvClk
22 
23    clocking iMonClk @(posedge clk);
24       input  frame_n;
25       input  valid_n;
26       input  din;
27       input  busy_n;
28    endclocking: iMonClk
29 
30    clocking oMonClk @(posedge clk);
31       input  dout;
32       input  valido_n;
33       input  frameo_n;
34    endclocking: oMonClk
35 
36    modport driver(clocking drvClk, output reset_n);
37    modport imon(clocking iMonClk);
38    modport omon(clocking oMonClk);
39    modport dut(input clk, reset_n, frame_n, valid_n, din, output dout, busy_n, valido_n, frameo_n);
40 
41 endinterface: router_io
42 
43 `endif

2.2 host_io.sv (interface的使用)

 1 `ifndef HOST_IO__SV
 2 `define HOST_IO__SV
 3 interface host_io(input logic clk);
 4   logic        wr_n;
 5   logic [15:0] address;
 6   wire  [15:0] data;
 7 
 8   clocking cb @(posedge clk);
 9     inout   data;
10     output  address;
11     output  wr_n;
12   endclocking
13 
14   clocking mon @(posedge clk);
15     input  data;
16     input  address;
17     input  wr_n;
18   endclocking
19 
20   modport dut(input clk, input wr_n, address, inout data);
21 endinterface: host_io
22 `endif

3.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   //virtual router_io router_vif,reset_vif;
 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 
 21     // Lab 4 - Task 5, Step 3
 22     //
 23     // Configure the router environment agents' virtual interface by using SystemVerilog's
 24     // cross module reference (XMR) to access the interface
 25     //
 26     // At the test level, configuration of components dedicated to a DUT interface should be done via
 27     // the agent connected to that interface.  The test developer should treat the agent as the
 28     // Bus Functional Model (BFM) for the interface without needing to know anything about the
 29     // sub-components of the agent.
 30     //
 31     // uvm_config_db#(virtual router_io)::set(this, "env.i_agent", "router_io", router_test_top.sigs);
 32     // uvm_config_db#(virtual router_io)::set(this, "env.r_agent", "router_io", router_test_top.sigs);
 33     //
 34     // ToDo
 35     uvm_config_db#(virtual router_io)::set(this, "env.i_agent", "router_io", router_test_top.sigs);
 36     uvm_config_db#(virtual router_io)::set(this, "env.r_agent", "router_io", router_test_top.sigs);
 37     //注1:可以在test_base中声明virtual router_io router_vif与virtual router_io reset_vif;在test.sv中进行config_db::set(),在test_base中进行config_db::get(),然后config_db::set()给test_base的子组件;
 38     //uvm_resource_db#(virtual router_io)::read_by_type("router_vif",router_vif,this); 
 39     //uvm_config_db#(virtual router_io)::set(this,"env.i_agt","vif",router_vif);
 40     //reset_vif与router_vif仿照line38-39做同样处理;
 41   endfunction
 42 
 43   virtual function void final_phase(uvm_phase phase);
 44     super.final_phase(phase);
 45     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 46     uvm_top.print_topology();
 47 
 48     uvm_factory::get().print();
 49   endfunction
 50 endclass
 51 
 52 `include "packet_da_3.sv"
 53 
 54 class test_da_3_inst extends test_base;
 55   `uvm_component_utils(test_da_3_inst)
 56 
 57   function new(string name, uvm_component parent);
 58     super.new(name, parent);
 59     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 60   endfunction
 61 
 62   virtual function void build_phase(uvm_phase phase);
 63     super.build_phase(phase);
 64     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 65     set_inst_override_by_type("env.i_agent*.seqr.*", packet::get_type(), packet_da_3::get_type());
 66   endfunction
 67 endclass
 68 
 69 class test_da_3_type extends test_base;
 70   `uvm_component_utils(test_da_3_type)
 71 
 72   function new(string name, uvm_component parent);
 73     super.new(name, parent);
 74     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 75   endfunction
 76 
 77   virtual function void build_phase(uvm_phase phase);
 78     super.build_phase(phase);
 79     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 80     set_type_override_by_type(packet::get_type(), packet_da_3::get_type());
 81   endfunction
 82 endclass
 83 
 84 class test_da_3_seq extends test_base;
 85   `uvm_component_utils(test_da_3_seq)
 86 
 87   function new(string name, uvm_component parent);
 88     super.new(name, parent);
 89     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 90   endfunction
 91 
 92   virtual function void build_phase(uvm_phase phase);
 93     super.build_phase(phase);
 94     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 95     uvm_config_db#(bit[15:0])::set(this, "env.i_agent*.seqr", "da_enable", 16'h0008);
 96     uvm_config_db#(int)::set(this, "env.i_agent*.seqr", "item_count", 20);
 97   endfunction
 98 endclass
 99 
100 `endif

4.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     //uvm_config_db #(uvm_object_wrapper)::set(this, "i_agent.seqr.reset_phase", "default_sequence", router_input_port_reset_sequence::get_type());
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

5.input_agent.sv(派生于uvm_agent)

注1:agent包含sequencer, driver,monitor; 更高层次的组件(如env, test)应该将agent当作黑盒子,也就是说,sequencer. driver, monitor的配置应该由agent完成,更高层次的组件仅仅负责配置agent,而不需要负责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 typedef uvm_sequencer #(packet) packet_sequencer;
10 
11 class input_agent extends uvm_agent;
12 
13   // For this lab, the input agent has been modified to have port_id and virtual interface also.
14   virtual router_io sigs;          // DUT virtual interface
15   int               port_id = -1;  // Agent's designated port
16   packet_sequencer seqr;
17   driver drv;
18 
19   // For this lab, the input agent has been modified to have port_id.
20   `uvm_component_utils_begin(input_agent)
21     `uvm_field_int(port_id, UVM_DEFAULT | UVM_DEC)
22   `uvm_component_utils_end
23 
24   function new(string name, uvm_component parent);
25     super.new(name, parent);
26     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
27   endfunction: new
28 
29   virtual function void build_phase(uvm_phase phase);
30     super.build_phase(phase);
31     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
32 
33     // For this lab, the input agent has been modified to retrieve port_id and virtual interface.
34     // The agent then configures its child components to use the same port_id and virtual interface.
35     uvm_config_db#(int)::get(this, "", "port_id", port_id);
36     uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs);
37 
38     seqr = packet_sequencer::type_id::create("seqr", this);
39     drv  = driver::type_id::create("drv", this);
40 
41     uvm_config_db#(int)::set(this, "drv", "port_id", port_id);
42     uvm_config_db#(int)::set(this, "seqr", "port_id", port_id);
43     uvm_config_db#(virtual router_io)::set(this, "drv", "router_io", sigs);
44     uvm_config_db#(virtual router_io)::set(this, "seqr", "router_io", sigs);
45   endfunction: build_phase
46 
47   virtual function void connect_phase(uvm_phase phase);
48     super.connect_phase(phase);
49     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
50     drv.seq_item_port.connect(seqr.seq_item_export);
51   endfunction: connect_phase
52 
53   virtual function void start_of_simulation_phase(uvm_phase phase);
54     super.start_of_simulation_phase(phase);
55     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
56     `uvm_info("AGNTCFG", $sformatf("Using port_id of %0d", port_id), UVM_MEDIUM);
57   endfunction: start_of_simulation_phase
58 endclass
59 
60 `endif

5.1 driver.sv

  1 `ifndef DRIVER__SV
  2 `define DRIVER__SV
  3 
  4 class driver extends uvm_driver #(packet);
  5   // Lab 4 - Task 2, Step 2 and 3
  6   // Create the new fields as shown below.
  7   //
  8   // virtual router_io sigs;          // DUT virtual interface
  9   // int               port_id = -1;  // Driver's designated port
 10   //
 11   // The intent of the port_id field is to designate the driver for driving a specific port.
 12   //
 13   // If port_id is set in the range of 0 through 15, the driver will only drive
 14   // the packet it gets from the sequencer through the DUT if the port_id matches the
 15   // packet's source address (sa) field.  If not, the packet is dropped.
 16   //
 17   // If port_id is -1 (the default), the driver will drive all packets it gets from
 18   // the sequencer through the DUT without checking the packet's source address.
 19   //
 20   // Example:  If port_id is 3 and req.sa is also 3,
 21   // (req is the packet handle that sequencer passed to the driver)
 22   // The driver will drive the packet through port 3 of DUT: sigs.drvClk.din[req.sa];
 23   //
 24   // Example:  If port_id is 3 and req.sa is 7,
 25   // The driver will drop the packet.
 26   //
 27   // Example:  If port_id is -1 and req.sa is 7,
 28   // The driver will drive the packet through port 7 of DUT: sigs.drvClk.din[req.sa];
 29   //
 30   // ToDo
 31   virtual router_io sigs;          // DUT virtual interface
 32   int               port_id = -1;  // Driver's designated port
 33 
 34 
 35   // Lab 4 - Task 2, Step 4
 36   //
 37   // Embed the port_id field in the `uvm_component_utils macro.
 38   // Note: You will need to change the macro to `uvm_component_utils_begin
 39   //       with a corresponding `uvm_component_utils_end
 40   //
 41   // ToDo
 42   `uvm_component_utils_begin(driver)
 43     `uvm_field_int(port_id, UVM_DEFAULT | UVM_DEC)
 44   `uvm_component_utils_end
 45 
 46 
 47   function new(string name, uvm_component parent);
 48     super.new(name, parent);
 49     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 50   endfunction: new
 51 
 52 
 53   function void build_phase(uvm_phase phase);
 54     super.build_phase(phase);
 55     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 56 
 57     // Lab 4 - Task 2, Step 5
 58     //
 59     // Retrieve the port_id configuration and the virtual interface.
 60     //
 61     // uvm_config_db#(int)::get(this, "", "port_id", port_id);
 62     // if (!(port_id inside {-1, [0:15]})) begin
 63     //   `uvm_fatal("CFGERR", $sformatf("port_id must be {-1, [0:15]}, not %0d!", port_id));
 64     // end
 65     // uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs);
 66     // if (sigs == null) begin
 67     //   `uvm_fatal("CFGERR", "Interface for Driver not set");
 68     // end
 69     //
 70     // ToDo
 71     uvm_config_db#(int)::get(this, "", "port_id", port_id);
 72     if (!(port_id inside {-1, [0:15]})) begin
 73       `uvm_fatal("CFGERR", $sformatf("port_id must be {-1, [0:15]}, not %0d!", port_id));
 74     end
 75     uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs);
 76     if (sigs == null) begin //检测virtual interface handle;
 77       `uvm_fatal("CFGERR", "Interface for Driver not set");
 78     end
 79 
 80 
 81   endfunction: build_phase
 82 
 83 
 84   //
 85   // The UVM start_of_simulation phase is designed for displaying the testbench configuration
 86   // before any active verification operation starts.
 87   //
 88   // For the sake of lab time, the start_of_simulation method is done for you.
 89   //
 90   virtual function void start_of_simulation_phase(uvm_phase phase);
 91     super.start_of_simulation_phase(phase);
 92     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 93     `uvm_info("DRV_CFG", $sformatf("port_id is: %0d", port_id), UVM_MEDIUM);
 94   endfunction: start_of_simulation_phase
 95 
 96 
 97   virtual task run_phase(uvm_phase phase);
 98     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 99 
100     forever begin
101       seq_item_port.get_next_item(req);
102 
103       // Lab 4 - Task 2, Step 6
104       //
105       // Check port_id to see if the driver should accept or drop the packet.
106       // If port_id is -1, or if port_id matches req object's sa field,
107       // call send() method to drive the content of the req object through the DUT.
108       // Otherwise, drop the req object without processing.  Like the following:
109       //
110       // if (port_id inside { -1, req.sa }) begin
111       //   send(req);
112       //   `uvm_info("DRV_RUN", {"\n", req.sprint()}, UVM_MEDIUM);
113       // end
114       //
115       // ToDo
116       if (port_id inside { -1, req.sa }) begin
117         send(req);
118         `uvm_info("DRV_RUN", {"\n", req.sprint()}, UVM_MEDIUM);
119       end
120 
121 
122       seq_item_port.item_done();
123     end
124   endtask: run_phase
125 
126 
127   // Lab 4 - Task 8, Step 3
128   //
129   // The driver is fully responsible for asserting and de-asserting the signal set
130   // that it is assigned to handle.  This includes setting the signal state at reset.
131   //
132   // At the pre_reset phase, the signals should be set to default values (x for logic,
133   // z for wire) to emulate power-up condition.
134   //
135   // At the reset phase, the signals should be set to the de-asserted states.
136   //
137   // These two methods are done for you.
138   //
139   // Caution: for this lab, we are not using the port_id because this lab is still
140   // just a part of initial bringup process.  There is only one agent in the
141   // environment.  So, if port_id is -1 (not using port_id), then the reset phases
142   // will initialized the signals for all router (DUT) ports.  In the next lab,
143   // when you implement a dedicated agent for each port, the port_id will be set
144   // and the reset phases will only initialize its designated port.
145   //
146   // For this lab, just un-comment both the pre_reset and reset phase code.
147   //
148   // ToDo
149   //reset信号的assertion与deassertion由reset_sequence和reset_agent处理;其他控制信号,由driver的reset_phase来处理(方法1,不推荐该方法);
150   virtual task pre_reset_phase(uvm_phase phase);
151     super.pre_reset_phase(phase);
152     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
153     phase.raise_objection(this);
154     if (port_id == -1) begin
155       sigs.drvClk.frame_n <= 'x;
156       sigs.drvClk.valid_n <= 'x;
157       sigs.drvClk.din <= 'x;
158     end else begin
159       sigs.drvClk.frame_n[port_id] <= 'x;
160       sigs.drvClk.valid_n[port_id] <= 'x;
161       sigs.drvClk.din[port_id] <= 'x;
162     end
163     phase.drop_objection(this);
164   endtask: pre_reset_phase
165 
166   virtual task reset_phase(uvm_phase phase);
167     super.reset_phase(phase);
168     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
169     phase.raise_objection(this);
170     if (port_id == -1) begin
171       sigs.drvClk.frame_n <= '1;
172       sigs.drvClk.valid_n <= '1;
173       sigs.drvClk.din <= '0;
174     end else begin
175       sigs.drvClk.frame_n[port_id] <= '1;
176       sigs.drvClk.valid_n[port_id] <= '1;
177       sigs.drvClk.din[port_id] <= '0;
178     end
179     phase.drop_objection(this);
180   endtask: reset_phase
181 
182   //
183   // In the interest of lab time, all device drivers have been done for you:
184   //
185 
186   virtual task send(packet tr);
187     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
188     send_address(tr);
189     send_pad(tr);
190     send_payload(tr);
191   endtask: send
192 
193   virtual task send_address(packet tr);
194     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
195     sigs.drvClk.frame_n[tr.sa] <= 1'b0;
196     for(int i=0; i<4; i++) begin
197       sigs.drvClk.din[tr.sa] <= tr.da[i];
198       @(sigs.drvClk);
199     end
200   endtask: send_address
201 
202   virtual task send_pad(packet tr);
203     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
204     sigs.drvClk.din[tr.sa] <= 1'b1;
205     sigs.drvClk.valid_n[tr.sa] <= 1'b1;
206     repeat(5) @(sigs.drvClk);
207   endtask: send_pad
208 
209   virtual task send_payload(packet tr);
210     logic [7:0] datum;
211     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
212     while(!sigs.drvClk.busy_n[tr.sa]) @(sigs.drvClk);
213     foreach(tr.payload[index]) begin
214       datum = tr.payload[index];
215       for(int i=0; i<$size(tr.payload, 2); i++) begin
216         sigs.drvClk.din[tr.sa] <= datum[i];
217         sigs.drvClk.valid_n[tr.sa] <= 1'b0;
218         sigs.drvClk.frame_n[tr.sa] <= ((tr.payload.size()-1) == index) && (i==7);
219         @(sigs.drvClk);
220       end
221     end
222     sigs.drvClk.valid_n[tr.sa] <= 1'b1;
223   endtask: send_payload
224 
225 endclass: driver
226 
227 `endif

6.reset_agent.sv(含reset_sequencer, reset_driver, reset_monitor)

  1 `ifndef RESET_AGENT__SV
  2 `define RESET_AGENT__SV
  3 
  4 `include "reset_sequence.sv"
  5 
  6 typedef class reset_driver;
  7 typedef class reset_monitor;
  8 typedef uvm_sequencer#(reset_tr) reset_sequencer;
  9 
 10 class reset_agent extends uvm_agent;
 11   virtual router_io sigs;          // DUT virtual interface
 12   reset_sequencer seqr;
 13   reset_driver  drv;
 14   reset_monitor mon;
 15   
 16   `uvm_component_utils(reset_agent)
 17 
 18   function new(string name, uvm_component parent);
 19     super.new(name, parent);
 20     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 21   endfunction: new
 22 
 23   function void build_phase(uvm_phase phase);
 24     super.build_phase(phase);
 25     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 26 
 27     uvm_config_db#(uvm_active_passive_enum)::get(this, "", "is_active", is_active);
 28     `uvm_info("RSTCFG", $sformatf("Reset agent %s setting for is_active is: %p", this.get_name(), is_active), UVM_MEDIUM);
 29 
 30     uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs);
 31 
 32     if (is_active == UVM_ACTIVE) begin
 33       seqr = reset_sequencer::type_id::create("seqr", this);
 34       drv  = reset_driver::type_id::create("drv", this);
 35       uvm_config_db#(virtual router_io)::set(this, "drv", "router_io", sigs);
 36       uvm_config_db#(virtual router_io)::set(this, "seqr", "router_io", sigs);
 37     end
 38     mon = reset_monitor::type_id::create("mon", this);
 39     uvm_config_db#(virtual router_io)::set(this, "mon", "router_io", sigs);
 40   endfunction: build_phase
 41 
 42   virtual function void connect_phase(uvm_phase phase);
 43     super.connect_phase(phase);
 44     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 45     if (is_active == UVM_ACTIVE) begin
 46       drv.seq_item_port.connect(seqr.seq_item_export);
 47     end
 48   endfunction: connect_phase
 49 endclass
 50 
 51 /*
 52 class reset_tr extends uvm_sequence_item;
 53   typedef enum {ASSERT, DEASSERT} kind_e;
 54   rand kind_e kind;
 55   rand int unsigned cycles = 1;
 56 endclass
 57 */
 58 
 59 class reset_driver extends uvm_driver #(reset_tr);
 60   virtual router_io sigs;          // DUT virtual interface
 61   `uvm_component_utils(reset_driver)
 62 
 63   function new(string name, uvm_component parent);
 64     super.new(name, parent);
 65     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 66   endfunction: new
 67 
 68   function void build_phase(uvm_phase phase);
 69     super.build_phase(phase);
 70     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 71 
 72     if (!uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs)) begin
 73       `uvm_fatal("CFGERR", "Interface for reset driver not set");
 74     end
 75   endfunction: build_phase
 76 
 77   virtual task run_phase(uvm_phase phase);
 78     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 79 
 80     forever begin
 81       seq_item_port.get_next_item(req);
 82       drive(req);
 83       seq_item_port.item_done();
 84     end
 85   endtask: run_phase
 86   //注1:reset_agent和reset_sequence只处理了reset信号的assertion与de-assertion;其他控制信号的处理要么通过一个单独的sequence来deassert,要么在driver的reset_phase控制;
 87   virtual task drive(reset_tr tr);
 88     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 89     if (tr.kind == reset_tr::ASSERT) begin
 90       sigs.reset_n = 1'b0;
 91       repeat(tr.cycles) @(sigs.drvClk);
 92     end else begin
 93       sigs.reset_n <= '1;
 94       repeat(tr.cycles) @(sigs.drvClk);
 95     end
 96   endtask: drive
 97 endclass
 98 
 99 class reset_monitor extends uvm_monitor;
100   virtual router_io sigs;          // DUT virtual interface
101   uvm_analysis_port #(reset_tr) analysis_port;
102   `uvm_component_utils(reset_monitor)
103 
104   function new(string name, uvm_component parent);
105     super.new(name, parent);
106     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
107   endfunction: new
108 
109   function void build_phase(uvm_phase phase);
110     super.build_phase(phase);
111     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
112 
113     if (!uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs)) begin
114       `uvm_fatal("CFGERR", "Interface for reset monitor not set");
115     end
116 
117     analysis_port = new("analysis_port", this);
118   endfunction: build_phase
119 
120   virtual task run_phase(uvm_phase phase);
121     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
122 
123     forever begin
124       reset_tr tr = reset_tr::type_id::create("tr", this);
125       detect(tr);
126       analysis_port.write(tr);
127     end
128   endtask: run_phase
129 
130   virtual task detect(reset_tr tr);
131     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
132     @(sigs.reset_n);
133     assert(!$isunknown(sigs.reset_n));
134     if (sigs.reset_n == 1'b0) begin
135       tr.kind = reset_tr::ASSERT;
136     end else begin
137       tr.kind = reset_tr::DEASSERT;
138     end
139   endtask: detect
140 endclass
141 
142 `endif

7.packet_sequence.sv

  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

7.1packet.sv

 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

7.2 packet_da_3.sv

 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

8.reset_sequence.sv

 1 `ifndef RESET_SEQUENCE__SV
 2 `define RESET_SEQUENCE__SV
 3 
 4 // Reset structure is done in the same way as all other UVM component structure.
 5 // A reset agent contains a reset sequencer, driver and monitor.
 6 //
 7 // The reset sequencer executes a reset sequence (this file), and passes the reset
 8 // transaction (reset_tr) to the reset driver.  The reset driver then assert/de-assert
 9 // the reset signal as specified in the reset transaction.
10 //
11 // Within the reset transaction class, there is a control command field called kind.
12 // If the kind field is ASSERT, then the driver will assert the reset signal for
13 // the number of clock cycles are specified in the cycles field.  Similar action
14 // takes place for the DEASSERT command.
15 //
16 // For example, if the reset signal need to be asserted for 2 cycles then de-asserted
17 // for 15 clock cycles, the potential code might look like:
18 //
19 // reset_tr tr = reset_tr::type_id::create("tr");
20 // tr.randomize() with {kind == ASSERT; cycles == 2;};
21 // tr.randomize() with {kind == DEASSERT; cycles == 15;;
22 
23 class reset_tr extends uvm_sequence_item;
24   typedef enum {ASSERT, DEASSERT} kind_e;
25   rand kind_e kind;
26   rand int unsigned cycles = 1;
27 
28   `uvm_object_utils_begin(reset_tr)
29     `uvm_field_enum(kind_e, kind, UVM_ALL_ON)
30     `uvm_field_int(cycles, UVM_ALL_ON)
31   `uvm_object_utils_end
32 
33   function new(string name = "reset_tr");
34     super.new(name);
35     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
36   endfunction: new
37 endclass
38 
39 class reset_sequence extends uvm_sequence #(reset_tr);
40   `uvm_object_utils(reset_sequence)
41 
42   function new(string name = "reset_sequence");
43     super.new(name);
44     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
45   endfunction
46 
47   task body();
48     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
49 
50     if (starting_phase != null)
51       starting_phase.raise_objection(this);
52 
53     // Lab 4 - Task 6, Step 2
54     //
55     // Enter the code to assert reset for 2 cycles, followed by de-assert of reset for 15 cycles.
56     //
57     // ToDo
58     `uvm_do_with(req, {kind == ASSERT; cycles == 2;});
59     `uvm_do_with(req, {kind == DEASSERT; cycles == 15;});
60 
61 
62     if (starting_phase != null)
63       starting_phase.drop_objection(this);
64    endtask
65 
66 endclass
67 
68 `endif

9.router_input_port_reset_sequence.sv

注1:reset_sequence和reset_agent仅仅处理了reset信号的assertion与de-assertion,其他控制信号的de-assertion可以由router_input_port_reset_sequence控制(方法2,推荐),该sequence可以在sequencer的reset_phase执行;

注2:注意get_sequencer()的使用;

注3:该sequence可以用input_agent的sequencer执行;

 1 class router_input_port_reset_sequence extends uvm_sequence #(packet);
 2     virtual router_io vif;
 3     input             port_id=-1;
 4     
 5   `uvm_object_utils_begin(router_input_port_reset_sequence)
 6         `uvm_field_int(port_id, UVM_DEFAULT | UVM_DEC)
 7     `uvm_object_utils_end
 8 
 9     function new(string name="router_input_port_reset_sequence");
10         super.new(name);
11         `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH)
12         `ifdef UVM_POST_VERSION_1_1
13         set_automatic_phase_objection(1);
14         `endif
15     endfunction
16 
17     virtual task pre_start();
18         `ifdef UVM_VERSION_1_1
19         if((get_parent_sequence()==null) && (starting_phase!=null)) begin
20             starting_phase.raise_objection(this);
21         end
22         `endif
23 
24         uvm_config_db#(int)::get(get_sequencer(),"","port_id",port_id);
25         if(!(port_id inside {-1,[0:15]})) begin
26             `uvm_fatal("CFGERR",$sformatf("port_id must be {-1,[0:15]}, not %0d!",port_id))
27         end
28         uvm_config_db#(virtual router_io)::get(get_sequencer(),"","vif",vif);
29         if(vif==null) begin
30             `uvm_fatal("CFGERR","Interface for the Driver Reset Sequence not set")
31         end
32     endtask: pre_start
33 
34     `ifdef UVM_VERSION_1_1
35     virtual task post_start();
36         if((get_parent_sequence()==null) && (starting_phase!=null)) begin
37             starting_phase.drop_objection(this);
38         end
39     endtask: post_start
40     `endif
41 
42     virtual task body();
43         if(port_id==-1) begin
44             vif.frame_n='1;
45             vif.valid_n='1;
46             vif.din='0;
47         end
48         else begin
49             vif.frame_n='1;
50             vif.valid_n='1;
51             vif.din='0;
52         end
53     endtask
54 endclass

 

posted on 2022-04-30 21:11  知北游。。  阅读(297)  评论(0编辑  收藏  举报

导航