[CU]uvm lab5-router

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

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

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

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

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

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

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

学习目标

(1) 在monitor中实现TLM analysis port;

(2) 采用uvm_in_order_class_comparator实现uvm_scoreboard;

(3) virtual sequence和virtual sequencer的使用;

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:注意main_phase中set_drain_time的使用;

  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   //virtual router_io router_vif,reset_vif;
  9   router_env env;
 10   //top_reset_sequencer top_reset_sqr;  //(virtual sequencer)
 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 5 - Task 4, Step 6
 22     //
 23     // In the environment, the input agent has changed from a single instance to an array of 16
 24     // agents.  Within the test, the corresponding change also must take place.
 25     //
 26     // Change the configuration for the input agent objects to the following:
 27     //
 28     // uvm_config_db#(virtual router_io)::set(this, "env.i_agent[*]", "router_io", router_test_top.sigs);
 29     //
 30     // ToDo
 31     uvm_config_db#(virtual router_io)::set(this, "env.i_agent[*]", "router_io", router_test_top.sigs);
 32     //top_reset_sqr=top_reset_sequencer::type_id::create("top_reset_sqr",this);
 33 
 34     // Lab 5 - Task 7, Step 8
 35     //
 36     // In the environment, an array of output agent has been added.  Each of these agents need to
 37     // access the physical signal.  Configure the agents as follows:
 38     //
 39     // uvm_config_db#(virtual router_io)::set(this, "env.o_agent[*]", "router_io", router_test_top.sigs);
 40     // ToDo
 41     uvm_config_db#(virtual router_io)::set(this, "env.o_agent[*]", "router_io", router_test_top.sigs);
 42     //uvm_config_db#(uvm_object_wrapper)::set(this,"env.r_agt.sqr.reset_phase","default_sequence", null);  
 43     //uvm_config_db#(uvm_object_wrapper)::set(this,"top_reset_sqr.reset_phase","default_sequence",top_reset_sequence::get_type());
 44     uvm_config_db#(virtual router_io)::set(this, "env.r_agent", "router_io", router_test_top.sigs);
 45   endfunction
 46 
 47   //connect_phase中,为top_reset_sqr的sub-sequencer赋值,建立virtual sequencer与physical sequencer的联系;
 48   /*virtual function void connect_phase(uvm_phase phase);
 49         super.connect_phase(phase);
 50         foreach(env.i_agt[i]) begin
 51             top_reset_sqr.pkt_sqr.push_back(env.i_agt[i].sqr);
 52         end
 53         top_reset_sqr.r_sqr=env.r_agt.sqr;
 54   endfunction*/
 55   virtual task shutdown_phase(uvm_phase phase);
 56      super.shutdown_phase(phase); 
 57          phase.raise_objection(this); 
 58          env.sb.wait_for_done(); 
 59      phase.drop_objection(this);
 60   endtask: shutdown_phase
 61 
 62   /* virtual task main_phase(uvm_phase phase);
 63      uvm_objection objection;   
 64      super.main_phase(phase);  
 65      objection=phase.get_objection(); 
 66      objection.set_drain_time(this,1us); 
 67   endtask */
 68   
 69   virtual function void final_phase(uvm_phase phase);
 70     super.final_phase(phase);
 71     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 72     uvm_top.print_topology();
 73     uvm_factory::get().print();
 74   endfunction
 75 endclass
 76 
 77 
 78 `include "packet_da_3.sv"
 79 
 80 class test_da_3_inst extends test_base;
 81   `uvm_component_utils(test_da_3_inst)
 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     set_inst_override_by_type("env.i_agent*.seqr.*", packet::get_type(), packet_da_3::get_type());
 92   endfunction
 93 endclass
 94 
 95 class test_da_3_type extends test_base;
 96   `uvm_component_utils(test_da_3_type)
 97 
 98   function new(string name, uvm_component parent);
 99     super.new(name, parent);
100     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
101   endfunction
102 
103   virtual function void build_phase(uvm_phase phase);
104     super.build_phase(phase);
105     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
106     set_type_override_by_type(packet::get_type(), packet_da_3::get_type());
107   endfunction
108 endclass
109 
110 class test_da_3_seq extends test_base;
111   `uvm_component_utils(test_da_3_seq)
112 
113   function new(string name, uvm_component parent);
114     super.new(name, parent);
115     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
116   endfunction
117 
118   virtual function void build_phase(uvm_phase phase);
119     super.build_phase(phase);
120     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
121     uvm_config_db#(bit[15:0])::set(this, "env.i_agent*.seqr", "da_enable", 16'h0008);
122     uvm_config_db#(int)::set(this, "env.i_agent*.seqr", "item_count", 20);
123   endfunction
124 endclass
125 
126 `endif

3.router_env.sv(派生于uvm_env)

注1:注意该段code中出现多个uvm_analysis_port连向同一个uvm_analysis_imp的情况;

  1 `ifndef ROUTER_ENV__SV
  2 `define ROUTER_ENV__SV
  3 
  4 `include "input_agent.sv"
  5 `include "reset_agent.sv"
  6 
  7 // Lab 5 - Task 7, Step 2
  8 //
  9 // Include the scoreboard.sv and output_agent.sv files
 10 //
 11 // ToDo
 12 //`include "scoreboard.sv"
 13 `include "output_agent.sv"
 14 
 15 
 16 // Lab 5 - Task 8, step 8
 17 //
 18 // Comment out the include statement above for the scoreboard.sv.
 19 // Replace it with an include statement for ms_scoreboard.sv
 20 //
 21 // ToDo
 22 `include "ms_scoreboard.sv"
 23 
 24 
 25 class router_env extends uvm_env;
 26 
 27   // Lab 5 - Task 4, Step 2
 28   //
 29   // The environment need 16 individual input agents.  One for each DUT port.
 30   //
 31   // Change the following single instance of agent into an array of 16 agents: i_agent[16].
 32   //
 33   // ToDo
 34   input_agent i_agent[16];
 35 
 36 
 37 
 38   // Lab 5 - Task 7, Step 3
 39   //
 40   // Create an instance of scoreboard, call it sb.
 41   // Create an array of output_agent, call it o_agent[16].
 42   //
 43   // If you examine the output_agent code, you will find that the output_agent only contains
 44   // an instance of oMonitor.  This is because for the sake of lab simplicity, the DUT output
 45   // protocal was designed without the need of a responder (push mode).  Even though there are
 46   // no sequencer nor drivers in the output agent, the output agent should still be created and
 47   // instantiated in the environment.  For flexibility of environment maintenance, this will be
 48   // better in the longer run for unanticipated changes.
 49   //
 50   // ToDo
 51   scoreboard sb;
 52   output_agent o_agent[16];
 53 
 54 
 55   reset_agent r_agent;
 56 
 57   `uvm_component_utils(router_env)
 58 
 59   function new(string name, uvm_component parent);
 60     super.new(name, parent);
 61     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 62   endfunction
 63 
 64   virtual function void build_phase(uvm_phase phase);
 65     super.build_phase(phase);
 66     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 67 
 68     // Lab 5 - Task 4, Step 3
 69     //
 70     // Change the following construction and configuration of a single instance of input agent into
 71     // construction and configuration of all agents in the agent array.
 72     //
 73     // First, construct each input agent via the factory create() method.
 74     // Then, for each agent, assign it to a dedicated port by setting the port_id field.
 75     // Finally, for each agent, set the sequencer's default_sequence to packet_sequence.
 76     //
 77     // foreach (i_agent[i]) begin
 78     //   i_agent[i] = input_agent::type_id::create($sformatf("i_agent[%0d]", i), this);
 79     //   uvm_config_db #(int)::set(this, i_agent[i].get_name(), "port_id", i);
 80     //   uvm_config_db #(uvm_object_wrapper)::set(this, {i_agent[i].get_name(), ".", "seqr.main_phase"}, "default_sequence", packet_sequence::get_type());
 81     // end
 82     //
 83     // ToDo
 84     foreach (i_agent[i]) begin
 85       i_agent[i] = input_agent::type_id::create($sformatf("i_agent[%0d]", i), this);
 86       uvm_config_db #(int)::set(this, i_agent[i].get_name(), "port_id", i);     //采用get_name()函数,非常好;
 87       uvm_config_db #(uvm_object_wrapper)::set(this, {i_agent[i].get_name(), ".", "seqr.main_phase"}, "default_sequence", packet_sequence::get_type());
 88       //uvm_config_db #(uvm_object_wrapper)::set(this,{i_agent[i].get_name(),".", "seqr.reset_phase"},"default_sequence", router_input_port_reset_sequence::get_type());
 89     end
 90     
 91     // Lab 5 - Task 7, Step 4
 92     //
 93     // Construct the scoreboard and the output_agent objects with factory create() method.
 94     //
 95     // For each output_agent object, also configure its port_id field to a designated port.
 96     //
 97     // foreach (o_agent[i]) begin
 98     //   o_agent[i] = output_agent::type_id::create($sformatf("o_agent[%0d]", i), this);
 99     //   uvm_config_db #(int)::set(this, o_agent[i].get_name(), "port_id", i);
100     // end
101     //
102     // ToDo
103     sb = scoreboard::type_id::create("sb", this);
104     foreach (o_agent[i]) begin
105       o_agent[i] = output_agent::type_id::create($sformatf("o_agent[%0d]",i),this);
106       uvm_config_db #(int)::set(this, o_agent[i].get_name(), "port_id", i);
107     end
108 
109 
110     r_agent = reset_agent::type_id::create("r_agent", this);
111     uvm_config_db #(uvm_object_wrapper)::set(this, "r_agent.seqr.reset_phase", "default_sequence", reset_sequence::get_type());
112   endfunction
113 
114   virtual function void connect_phase(uvm_phase phase);
115     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
116 
117     // Lab 5 - Task 7, Step 5
118     //
119     // Connect the scoreboard's before and after TLM exports to each agent's TLM analysis port.
120     //
121     // ToDo
122     foreach (i_agent[i]) begin
123       i_agent[i].analysis_port.connect(sb.before_export);     //比较少使用,多个analysis_ap连向同一个imp;
124     end
125     foreach (o_agent[i]) begin
126       o_agent[i].analysis_port.connect(sb.after_export);
127     end
128 
129 
130   endfunction
131 
132 endclass
133 
134 `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 `include "packet_sequence.sv"
  6 `include "driver.sv"
  7 
  8 // Lab 5 - Task 3, Step 2
  9 // include the iMonitor.sv file
 10 //
 11 // ToDo
 12 `include "iMonitor.sv"
 13 
 14 
 15 typedef uvm_sequencer #(packet) packet_sequencer;
 16 
 17 class input_agent extends uvm_agent;
 18   // The input agent already contains the following properties from the previous lab:
 19   virtual router_io sigs;          // DUT virtual interface
 20   int               port_id = -1;  // Agent's designated port
 21   packet_sequencer seqr;
 22   driver drv;
 23 
 24   // Lab 5 - Task 3, Step 3
 25   // Add an instance of iMonitor.  Call it mon.
 26   // And an instance of uvm_analysis_port #(packet).  Call it analysis_port.
 27   //
 28   // This analysis port is just a pass-through port for the iMonitor's analysis port
 29   // for the convinience of connection at the environment level.
 30   //
 31   // ToDo
 32   iMonitor mon;
 33   uvm_analysis_port #(packet) analysis_port;
 34 
 35 
 36   `uvm_component_utils_begin(input_agent)
 37     `uvm_field_int(port_id, UVM_DEFAULT | UVM_DEC)
 38   `uvm_component_utils_end
 39 
 40   function new(string name, uvm_component parent);
 41     super.new(name, parent);
 42     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 43   endfunction
 44 
 45   virtual function void build_phase(uvm_phase phase);
 46     super.build_phase(phase);
 47     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 48 
 49     // The agent retrieves port_id and virtual interface.
 50     uvm_config_db#(int)::get(this, "", "port_id", port_id);
 51     uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs);
 52 
 53     // Lab 5 - Task 3, Step 4
 54     //
 55     // Change the following construction and configure statements to obey the requirements
 56     // of the is_active flag.
 57     //
 58     // Check the state of the is_active flag.  If the is_active flag is UVM_ACTIVE,
 59     // use the existing statements to construct and configure the sequencer and driver objects.
 60     //
 61     // ToDo
 62     if (is_active == UVM_ACTIVE) begin
 63       seqr = packet_sequencer::type_id::create("seqr", this);
 64       drv  = driver::type_id::create("drv", this);
 65 
 66       uvm_config_db#(int)::set(this, "drv", "port_id", port_id);
 67       uvm_config_db#(int)::set(this, "seqr", "port_id", port_id);
 68       uvm_config_db#(virtual router_io)::set(this, "drv", "router_io", sigs);
 69       uvm_config_db#(virtual router_io)::set(this, "seqr", "router_io", sigs);
 70     end
 71 
 72 
 73     // Lab 5 - Task 3, Step 5
 74     //
 75     // Regardless of the state of the is_active flag, construct and configure the iMonitor (mon)
 76     // object.
 77     //
 78     // ToDo
 79     mon  = iMonitor::type_id::create("mon", this);
 80     uvm_config_db#(int)::set(this, "mon", "port_id", port_id);
 81     uvm_config_db#(virtual router_io)::set(this, "mon", "router_io", sigs);
 82 
 83 
 84   endfunction
 85 
 86   virtual function void connect_phase(uvm_phase phase);
 87     super.connect_phase(phase);
 88     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 89 
 90     // Lab 5 - Task 3, Step 6
 91     // Change the following connect statement to obey the requirement of the is_active flag.
 92     //
 93     // If the is_active flag is UVM_ACTIVE, connect drv's seq_item_port to seqr's seq_item_export
 94     //
 95     // ToDo
 96     if (is_active == UVM_ACTIVE) begin
 97       drv.seq_item_port.connect(seqr.seq_item_export);
 98     end
 99 
100 
101     // Lab 5 - Task 3, Step 7
102     // Set the agent's pass-through analyais port (analysis_port) to reference the analysis port
103     // in iMonitor (mon).
104     //
105     // ToDo
106     this.analysis_port = mon.analysis_port;
107 
108 
109   endfunction
110 
111   virtual function void start_of_simulation_phase(uvm_phase phase);
112     super.start_of_simulation_phase(phase);
113     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
114     `uvm_info("AGNTCFG", $sformatf("Using port_id of %0d", port_id), UVM_MEDIUM);
115   endfunction: start_of_simulation_phase
116 
117 endclass
118 
119 `endif

4.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
 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 
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

4.2 iMonitor.sv

  1 `ifndef IMONITOR__SV
  2 `define IMONITOR__SV
  3 
  4 class iMonitor extends uvm_monitor;
  5   // Just like in the driver, the monitors will need a port designater variable
  6   // and access to DUT virtual interface.  They are exactly the same as driver.
  7   // There are no additional learning points in creating and configuring these
  8   // fields, so they are done for you.
  9   virtual router_io sigs;
 10   int               port_id = -1;
 11 
 12 
 13   // Lab 5 - Task 2, Step 2
 14   // Create a TLM analysis port typed to packet.  Call the handle analysis_port.
 15   //
 16   // ToDo
 17   uvm_analysis_port #(packet) analysis_port;
 18 
 19   `uvm_component_utils_begin(iMonitor)
 20     `uvm_field_int(port_id, UVM_DEFAULT | UVM_DEC)
 21   `uvm_component_utils_end
 22 
 23   function new(string name, uvm_component parent);
 24     super.new(name, parent);
 25     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 26   endfunction
 27 
 28   function void build_phase(uvm_phase phase);
 29     super.build_phase(phase);
 30     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 31     if (!uvm_config_db#(int)::get(this, "", "port_id", port_id)) begin
 32       `uvm_fatal("CFGERR", "iMonitor port_id not set");
 33     end
 34     if (!uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs)) begin
 35       `uvm_fatal("CFGERR", "iMonitor DUT interface not set");
 36     end
 37 
 38     // Lab 5 - Task 2, Step 3
 39     // Construct analysis_port.
 40     //
 41     // TLM ports in UVM do not have factory support.  You cannot construct
 42     // TLM ports with the factory create() method.
 43     // You can only construct TLM ports by calling its constructor.
 44     //
 45     // ToDo
 46     analysis_port = new("analysis_port", this);
 47 
 48   endfunction
 49 
 50   virtual task run_phase(uvm_phase phase);
 51 
 52     // The job of the monitor is to passively monitor the physical signals,
 53     // interprete and report the activities that it sees.  In this case, to
 54     // re-construct the packet that it sees on the DUT's input port as specified
 55     // by port_id.
 56     //
 57     // The observed packet need to be stored in an object.  In this task, that
 58     // object handle is tr as declared below.
 59 
 60     packet tr;
 61     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
 62 
 63     forever begin
 64 
 65       // Lab 5 - Task 2, Step 5
 66       // Within the forever loop, you need to construct the object (tr) in which the
 67       // observed transaction on the DUT input port can be stored.  As always, use the
 68       // factory create() method to do the construction.
 69       //
 70       // In the observed transaction object, there are three fields that needs to be
 71       // populated: source address (sa), destination address (da) and the payload array
 72       // (payload).
 73       //
 74       // The source address is not part of the observable bit stream on the DUT interface.
 75       // It is, by definition, the port_id of the iMonitor object.  You should set this
 76       // field before calling the device driver (get_packet).
 77       //
 78       // Both the destination address and the payload can be extracted from the obserable
 79       // bit stream on the DUT interface.  These will be populated by the device driver.
 80       //
 81       // After setting the source address field, call get_packet() to retrieve the observed
 82       // transaction.  Then, display the content of the observed transaction and pass the
 83       // observed transaction on to all other interested component via the TLM analysis port
 84       // (analysis_port) by calling its write() method.
 85       //
 86       // tr = packet::type_id::create("tr", this);
 87       // tr.sa = this.port_id;
 88       // get_packet(tr);
 89       // `uvm_info("Got Input Packet", {"\n", tr.sprint()}, UVM_MEDIUM);
 90       // analysis_port.write(tr);
 91       //
 92       // ToDo
 93       tr = packet::type_id::create("tr", this);
 94       tr.sa = this.port_id;
 95       get_packet(tr);
 96       `uvm_info("Got Input Packet", {"\n", tr.sprint()}, UVM_MEDIUM);
 97       analysis_port.write(tr);
 98 
 99 
100     end
101   endtask
102 
103   //
104   // In the interest of lab time, the device driver code is done for you.
105   //
106 
107   virtual task get_packet(packet tr);
108     logic [7:0] datum;
109     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
110     @(negedge sigs.iMonClk.frame_n[port_id]);
111 
112     for (int i=0; i<4; i++) begin
113       if (!sigs.iMonClk.frame_n[port_id]) begin
114         tr.da[i] = sigs.iMonClk.din[port_id];
115       end else begin
116         `uvm_fatal("Header Error", $sformatf("@ Header cycle %0d, Frame not zero", i));
117       end
118       @(sigs.iMonClk);
119     end
120 
121     for (int i=0; i<5; i++) begin
122       if (!sigs.iMonClk.frame_n[port_id]) begin
123         if (sigs.iMonClk.valid_n[port_id] && sigs.iMonClk.din[port_id]) begin
124           @(sigs.iMonClk);
125           continue;
126         end else begin
127           `uvm_fatal("Header Error", $sformatf("@%0d Valid or Din zero", i));
128         end
129       end else begin
130         `uvm_fatal("Header Error", "Frame not zero");
131       end
132     end
133 
134     forever begin
135       for(int i=0; i<8; i=i) begin
136         if (!sigs.iMonClk.valid_n[port_id]) begin
137           if (sigs.iMonClk.busy_n[port_id]) begin
138             datum[i++] = sigs.iMonClk.din[port_id];
139             if (i == 8) begin
140               tr.payload.push_back(datum);
141             end
142           end else begin
143             `uvm_fatal("Payload Error", "Busy & Valid conflict");
144           end
145         end
146         if (sigs.iMonClk.frame_n[port_id]) begin
147           if (i == 8) begin
148             return;
149           end else begin
150             `uvm_fatal("Payload Error", "Not byte aligned");
151           end
152         end
153 @(sigs.iMonClk);
154       end
155     end
156   endtask: get_packet
157 
158 endclass
159 
160 `endif

5.output_agent.sv

 1 `ifndef OUTPUT_AGENT__SV
 2 `define OUTPUT_AGENT__SV
 3 
 4 // include the oMonitor.sv file
 5 `include "oMonitor.sv"
 6 
 7 class output_agent extends uvm_agent;
 8   // This output agent does not have seqeuncer and driver, but still require a monitor
 9   // and the associated port_id,virtual interface and analysis port.
10   virtual router_io sigs;          // DUT virtual interface
11   int               port_id = -1;  // Agent's designated port
12   oMonitor          mon;
13   uvm_analysis_port #(packet) analysis_port;
14 
15   `uvm_component_utils_begin(output_agent)
16     `uvm_field_int(port_id, UVM_DEFAULT | UVM_DEC)
17   `uvm_component_utils_end
18 
19   function new(string name, uvm_component parent);
20     super.new(name, parent);
21     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
22   endfunction
23 
24   virtual function void build_phase(uvm_phase phase);
25     super.build_phase(phase);
26     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
27 
28     // The agent retrieves port_id and virtual interface.
29     uvm_config_db#(int)::get(this, "", "port_id", port_id);
30     uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs);
31 
32     mon  = oMonitor::type_id::create("mon", this);
33     uvm_config_db#(int)::set(this, "mon", "port_id", port_id);
34     uvm_config_db#(virtual router_io)::set(this, "mon", "router_io", sigs);
35   endfunction
36 
37   virtual function void connect_phase(uvm_phase phase);
38     super.connect_phase(phase);
39     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
40 
41     this.analysis_port = mon.analysis_port;
42   endfunction
43 
44   virtual function void start_of_simulation_phase(uvm_phase phase);
45     super.start_of_simulation_phase(phase);
46     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
47     `uvm_info("AGNTCFG", $sformatf("Using port_id of %0d", port_id), UVM_MEDIUM);
48   endfunction: start_of_simulation_phase
49 
50 endclass
51 
52 `endif

5.1oMonitor.sv

 1 `ifndef OMONITOR__SV
 2 `define OMONITOR__SV
 3 
 4 class oMonitor extends uvm_monitor;
 5   int port_id = -1;
 6   virtual router_io sigs;
 7   uvm_analysis_port #(packet) analysis_port;
 8 
 9   `uvm_component_utils_begin(oMonitor)
10     `uvm_field_int(port_id, UVM_DEFAULT | UVM_DEC)
11   `uvm_component_utils_end
12 
13   function new(string name, uvm_component parent);
14     super.new(name, parent);
15     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
16   endfunction
17 
18   function void build_phase(uvm_phase phase);
19     super.build_phase(phase);
20     if (!uvm_config_db#(virtual router_io)::get(this, "", "router_io", sigs)) begin
21       `uvm_fatal("CFGERR", "oMonitor DUT interface not set");
22     end
23     analysis_port = new("analysis_port", this);
24   endfunction
25 
26   virtual task run_phase(uvm_phase phase);
27     packet tr;
28     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
29     forever begin
30       tr = packet::type_id::create("tr", this);
31       tr.da = this.port_id;
32       this.get_packet(tr);
33       `uvm_info("Got Output Packet", {"\n", tr.sprint()}, UVM_MEDIUM);
34       analysis_port.write(tr);
35     end
36   endtask
37 
38   task get_packet(packet tr);
39     logic [7:0] datum;
40     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
41     @(negedge sigs.oMonClk.frameo_n[port_id]);
42 
43     forever begin
44       for(int i=0; i<8; i=i) begin
45         if (!sigs.oMonClk.valido_n[port_id]) begin
46           datum[i++] = sigs.oMonClk.dout[port_id];
47           if (i == 8) begin
48             tr.payload.push_back(datum);
49           end
50           if (sigs.oMonClk.frameo_n[port_id]) begin
51             if (i == 8) begin
52               return;
53             end else begin
54               `uvm_fatal("Payload Error", "Not byte aligned");
55             end
56           end
57         end
58         @(sigs.oMonClk);
59       end
60     end
61   endtask: get_packet
62 
63 endclass
64 
65 `endif

6.ms_scoreboard.sv(ms-multi_stream)

注1:uvm_in_order_class_comparator的使用;

 1 `ifndef SCOREBOARD__SV
 2 `define SCOREBOARD__SV
 3 
 4 `uvm_analysis_imp_decl(_before)
 5 `uvm_analysis_imp_decl(_after)
 6 
 7 class scoreboard extends uvm_scoreboard;
 8   uvm_analysis_imp_before #(packet, scoreboard) before_export;
 9   uvm_analysis_imp_after  #(packet, scoreboard) after_export;
10   uvm_in_order_class_comparator #(packet) comparator[16];
11   //int count=0;
12   //realtime timeout = 10us;
13   `uvm_component_utils(scoreboard)
14 
15   function new(string name, uvm_component parent);
16     super.new(name, parent);
17     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
18   endfunction
19 
20   virtual function void build_phase(uvm_phase phase);
21     super.build_phase(phase);
22     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
23     before_export = new("before_export", this);
24     after_export  = new("after_export", this);
25     for (int i=0; i < 16; i++) begin
26       comparator[i] = uvm_in_order_class_comparator #(packet)::type_id::create($sformatf("comparator_%0d", i), this);
27     end
28   endfunction
29 
30   virtual function void write_before(packet pkt);
31     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
32     comparator[pkt.da].before_export.write(pkt);
33     //count++;
34   endfunction
35 
36   virtual function void write_after(packet pkt);
37     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
38     comparator[pkt.da].after_export.write(pkt);
39     //count--;
40   endfunction
41 
42   /* virtual task wait_for_done();
43     fork
44         begin
45             fork
46                 wait(count==0);
47                 begin
48                     #timeout;
49                 end
50       join_any;
51             disable fork;
52         end
53     join
54   endtask: wait_for_done */
55 
56   virtual function void report();
57     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
58     foreach (comparator[i]) begin
59       `uvm_info("Scoreboard Report",
60         $sformatf("Comparator[%0d] Matches = %0d, Mismatches = %0d",
61           i, comparator[i].m_matches, comparator[i].m_mismatches), UVM_MEDIUM);
62     end
63   endfunction
64 
65 endclass
66 
67 `endif

7.scoreboard.sv(not used)

 1 `ifndef SCOREBOARD__SV
 2 `define SCOREBOARD__SV
 3 
 4 class scoreboard extends uvm_scoreboard;
 5  
 6   // Lab 5 - Task 6, Step 2
 7   //
 8   // Add an instance of uvm_in_order_class_comparator typed to packet.  Call it comparator.
 9   //
10   // ToDo
11   uvm_in_order_class_comparator #(packet) comparator;
12 
13 
14   // Lab 5 - Task 6, Step 3
15   //
16   // Create two uvm_analysis_export, one called before_export and the other after_export.
17   //
18   // ToDo
19   uvm_analysis_export #(packet) before_export;
20   uvm_analysis_export #(packet) after_export;
21 
22 
23   `uvm_component_utils(scoreboard)
24 
25   function new(string name, uvm_component parent);
26     super.new(name, parent);
27     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
28   endfunction
29 
30   virtual function void build_phase(uvm_phase phase);
31     super.build_phase(phase);
32     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
33     //before_export=new("before_export",this);  after_export=new("after_export",this);
34     // Lab 5 - Task 6, Step 4
35     //
36     // Construct the comparator.
37     // Set the two analysis exports to the corresponding exports in the comparators.
38     //
39     // ToDo
40     comparator = uvm_in_order_class_comparator #(packet)::type_id::create("comparator", this);
41     before_export = comparator.before_export;
42     after_export  = comparator.after_export;
43     //this.before_export.connect(comparator.before_export);
44     //this.after_export.connect(comparator.after_export);
45   endfunction
46 
47   //
48   // You should always print the comparison results in the report phase/
49   // This is done for you.
50   //
51   virtual function void report_phase(uvm_phase phase);
52     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
53     `uvm_info("Scoreboard Report",
54       $sformatf("Comparator Matches = %0d, Mismatches = %0d", comparator.m_matches, comparator.m_mismatches), UVM_MEDIUM);
55   endfunction
56 
57 endclass
58 
59 `endif

8.reset_agent.sv(reset_driver, reset_monitor, reset_sequencer)

(1)注意reset_monitor内uvm_event的使用;

  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 
 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   //uvm_event reset_event=uvm_event_pool::get_global("reset");
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;   //reset_event.trigger();
136     end else begin
137       tr.kind = reset_tr::DEASSERT; //reset_event.reset(.wakeup(1));为什么需要指定wakeup参数??
138     end
139   endtask: detect
140 endclass
141 
142 `endif

9.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   int       item_count = 10;
 8   int       port_id    = -1;
 9   bit[15:0] da_enable  = '1;
10   int       valid_da[$];
11 
12   `uvm_object_utils_begin(packet_sequence)
13     `uvm_field_int(item_count, UVM_ALL_ON)
14     `uvm_field_int(port_id, UVM_ALL_ON)
15     `uvm_field_int(da_enable, UVM_ALL_ON)
16     `uvm_field_queue_int(valid_da, UVM_ALL_ON)
17   `uvm_object_utils_end
18 
19   function void pre_randomize();
20     uvm_config_db#(int)::get(m_sequencer, "", "item_count", item_count);  //m_sequencer或者get_sequencer();
21     uvm_config_db#(int)::get(m_sequencer, "", "port_id", port_id);
22     uvm_config_db#(bit[15:0])::get(m_sequencer, "", "da_enable", da_enable);
23     if (!(port_id inside {-1, [0:15]})) begin
24       `uvm_fatal("CFGERR", $sformatf("Illegal port_id value of %0d", port_id));
25     end
26 
27     valid_da.delete();
28     for (int i=0; i<16; i++)
29       if (da_enable[i])
30         valid_da.push_back(i);
31   endfunction
32 
33   function new(string name = "packet_sequence");
34     super.new(name);
35     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
36   endfunction
37 
38   virtual task body();
39     `uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
40     uvm_config_db#(int)::get(m_sequencer, "*", "item_count", item_count);
41 
42     if (starting_phase != null) begin
43 
44       // Lab 5 - Task 8, Step 3
45       // Retrieve the objection handle for the phase.  Then, set the drain time to 1us.
46       //
47       // uvm_objection objection = starting_phase.get_objection();
48       // objection.set_drain_time(this, 1us);
49       //
50       // ToDo
51       uvm_objection objection = starting_phase.get_objection();
52       objection.set_drain_time(this, 1us);
53 
54 
55       starting_phase.raise_objection(this);
56     end
57 
58     repeat(item_count) begin
59       `uvm_do_with(req, {if (port_id == -1) sa inside {[0:15]}; else sa == port_id; da inside valid_da;});
60     end
61 
62     if (starting_phase != null)
63       starting_phase.drop_objection(this);
64  endtask
65 
66 endclass
67 
68 `endif

9.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

9.2packet_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

10.与reset相关的sequence

10.1reset_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

10.2 router_input_port_reset_sequence.sv

 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

11.top_reset_sequencer.sv & top_reset_sequence.sv

注1:使用了virtual sequencer和virtual sequence机制,在top_reset_sequence.sv内协调reset_sequence与router_input_port_reset_sequence的执行;

 

注2:在reset信号assert前,DUT的其他输入信号0时刻值应该是unknown的;

 

注3:如果每个agent的sequencer独立执行它们的reset sequence,那么就可能造成reset信号assert前,其他input信号不是unknown值;

 1 class router_env extends uvm_env;
 2     ...
 3     virtual function void build_phase(uvm_phase phase);
 4         super.build_phase(phase);
 5         uvm_config_db#(uvm_object_wrapper)::set(this,"r_agt.sqr.reset_phase","default_sequence",reset_sequence::get_type());
 6 
 7         foreach(i_agent[i]) begin
 8             uvm_config_db#(uvm_object_wrapper)::set(this,{i_agent[i].get_name(),".sqr.reset_phase"},"default_sequence", router_input_port_reset_sequence::get_type());
 9         end
10     endfunction
11     ...
12 endclass

注4:正确的处理方法是在reset assert前,其他输入信号应该置于它们的默认态(x for logic, z for wire);接着,检测到reset信号后,为这些信号设置合理的复位值;推荐使用top reset sequence(virtual sequence)和top reset sequencer(virtual sequencer);

 

11.1 top_reset_sequencer.sv

 1 class top_reset_sequencer extends uvm_sequencer;
 2     `uvm_component_utils(top_reset_sequencer)
 3     typedef uvm_sequencer#(reset_tr) reset_sequencer;
 4     typedef uvm_sequencer#(packet)   packet_sequencer;
 5 
 6     reset_sequencer  r_sqr;
 7     packet_sequencer pkt_sqr[$];
 8 
 9     function new(string name, uvm_component parent);
10         super.new(name,parent);
11         `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH)
12     endfunction
13 endclass

11.2 top_reset_sequence.sv

 1 class top_reset_sequence extends uvm_sequence;
 2     `uvm_object_utils(top_reset_sequence)
 3     `uvm_declare_p_sequencer(top_reset_sequencer)
 4     
 5     reset_sequence  r_seq;
 6     router_input_port_reset_sequence i_seq;
 7     uvm_event reset_event=uvm_event_pool::get_global("reset");
 8 
 9     function new(string name="top_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 body();
18         `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH)
19         fork
20             `uvm_do_on(r_seq,p_sequencer.r_sqr);
21             foreach(p_sequencer.pkt_sqr[i]) begin
22                 fork
23                     int j=i;
24                     begin
25                         reset_event.wait_on();//该处采用了wait_on()而不是wait_trigger,与sequence和driver行为相关;
26                         `uvm_do_on(i_seq,p_sequencer.pkt_sqr[j]);
27                     end
28                 join_none
29             end
30         join
31     endtask
32     
33     `ifdef UVM_VERSION_1_1
34     virtual task pre_start();
35         `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH)
36         if((get_parent_sequence()==null) && (starting_phase!=null))    
37             starting_phase.raise_objection(this);
38     endtask
39     virtual task post_start();
40         `uvm_info("TRACE",$sformatf("%m"),UVM_HIGH)
41         if((get_parent_sequence()==null) && (starting_phase!=null))    
42             starting_phase.raise_objection(this);
43     endtask
44     `endif
45 endclass

 

posted on 2022-05-01 22:25  知北游。。  阅读(525)  评论(0编辑  收藏  举报

导航