Monday, October 24, 2016

UVM Connections.

Using Interface
  • Virtual interface
  • Static interface

Example 1
`include "uvm_macros.svh"

package my_pkg;
   import uvm_pkg::*;
   int shared_int;
   int shared_count;

   virtual interface mem_if global_vmi;
   `include "uvm_macros.svh"
   `include "test_1.svh"
   `include "test_2.svh"

endpackage: my_pkg

import uvm_pkg::*;
import my_pkg::*;

module top;
   mem_if mi();
   sram dut (mi.mem_modport);

   initial begin
      string test_name;
      my_pkg::global_vmi = mi;
     run_test();
   end

endmodule: top

// typedef struct packed
typedef struct {
   bit     sign;
   bit[24:0] mantissa;
   bit[ 5:0] exponent;
} ieee_sp_float;

union packed {
   bit [7:0] data[1500];
   struct packed {
      bit [7:0] dsap;
      bit [7:0] ssap;
      bit [7:0] control;
      bit [7:0] data[1497];
   } label;
} payload;

class test_1 extends uvm_test;
   `uvm_component_utils(test_1)

   ieee_sp_float v1, v2;
   v1 = {1, 24'h800, 6'h0};
   v1 = abs(v1);
   virtual interface mem_if mi;

   function new (string name, uvm_component base);
      super.new(name, base);
   endfunction : new

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      mi = my_pkg::global_vmi;
   endfunction : build_phase

   virtual task run_phase(uvm_phase phase);

      int cnt=5;
      logic [3:0] sub_addr;
      rand logic [11:0] upper_addr;
      sub_addr = $urandom($random);
      phase.raise_objection(this);
      mi.wr = 1'b1;
      mi.rd = ~mi.wr;
      mi.wr_data = $urandom($random);
      `uvm_info("TESTER", 
         $psprintf("addr: %2h  data: %2h  rd: %1b  wr: %1b", 
         mi.addr, mi.data, mi.rd, mi.wr), UVM_INFO);

      super.run();
      mi.addr = {upper_addr, sub_addr};

      repeat (cnt) begin
         @(posedge mi.clk);
         ...
      end
         @(posedge mi.clk);

         phase.drop_objection(this);

   endtask // run_phase


Example 2
import my_pkg::*;

// Virtual interface in driver
class my_driver extends uvm_driver #(my_transaction); 

   `uvm_component_utils(my_driver)

   virtual dut_if dut_vi;

   function new(string name, uvm_component parent); 
      super.new(name, parent);
   endfunction: new

   // function void build;
   virtual function void build_phase (uvm_phase phase);
      super.build();
      dut_vi = global_dutvi;
   endfunction : build_phase

   // task run;
   task run_phase (uvm_phase phase);
      repeat(4)
      begin
         phase.raise_objection(this);
         my_transaction tx;
         @(posedge dut_vi.clock);

         // Driver consumes the transactions generated by
         // my_transaction and wiggles the pins on the DUT
         seq_item_port.get(tx);

         // Pin Wiggling
         dut_vi.cmd  = tx.cmd;
         dut_vi.addr = tx.addr;
         dut_vi.data = tx.data;

      end
      @(posedge dut_vi.clock) top.stop_request();
      phase.drop_objection(this);

   endtask: run

endclass : my_driver


Example 3, connecting sequencer to driver
class my_sequencer extends uvm_sequencer;
   ...
   uvm_put_port #(int) port1;
   port1 = new ("port1", this);

endclass

class my_driver extends uvm_driver;
   ...
   uvm_get_port #(int) port2;
   port2 = new ("port2", this);

endclass

class my_agent extends uvm_agent; 
   `uvm_component_utils(my_agent) // register for type_id

   my_sequencer my_sequencer_h;
   my_driver my_driver_h;

   function new(string name, uvm_component parent); 
      super.new(name, parent);
   endfunction: new

   function void build;
      super.build(); 
      my_sequencer_h = 
         my_sequencer::type_id::create("my_sequencer_h", this);
                                     // instance name,   parent
      my_driver_h =
         my_driver::type_id::create  ("my_driver_h" , this);

   endfunction: build

   // Lower level connection in another function is good practice
   // seq_item_port is the handler of the ports

   function void connect; 
      my_driver_h.seq_item_port.connect(
         my_sequencer_h.seq_item_export ); 
   endfunction: connect

endclass : my_agent


Example 4, connecting through top module
`timescale 1ns/1ns

module top;

   mem_if mi();
   sram dut (mi.mem_modport);
   tester tst (mi.test_modport);

endmodule // top

interface mem_if;
   bit clk, rd, wr;
   logic [15:0] wr_data;
   wire  [15:0] data;
   logic [15:0] addr;

   modport mem_modport (
      inout data,
      input addr,
      input clk,
      input rd,
      input wr
   );

   modport test_modport (
      input clk,
      output wr_data,
      output addr,
      output rd,
      output wr
   );

   clocking cb @ (negedge clk);
      output data <= ...;
      output addr <= ...;
   endclocking: cb

   initial begin
      @(cb) ; wr_data <= ...;
      @(cb) ; wr <= $urandom;
   end

   assign rd = ~wr;
   assign data = (wr) ? wr_data : 16'hzzzz;

   initial begin
      clk = 0;
      $monitor ();
   end

   always #10 clk = ~clk;

endinterface // mem_if


Example 5, connecting in tester
module top;

   mem_if mi();
   sram dut (mi.mem_modport);
   tester tst;

   initial begin
      tst = new(mi);
      fork
         tst.run;
      join_none
   end

endmodule // top

class tester; // driver

   logic [3:0] sub_addr;
   virtual interface mem_if tmi;

   function new (virtual interface mem_if vmi);
      tmi = vmi;
   endfunction // new

   task run;
      // generate transaction data
      tmi.wr = 1'b1;

      @ (posedge tmi.clk); 
      repeat (100) begin
         @ (posedge tmi.clk); 
         tmi.wr = $random;
         tmi.rd = ~tmi.wr;
         tmi.addr = $random;
         tmi.wr_data = $urandom($random);
      end
      $stop;
   endtask // run

endclass // tester


Example 6, use wrapper_if
module top;

import uvm_pkg::*;
import my_pkg::*;

   mem_if mi();
   sram dut (mi.mem_modport);
   // tester tst; // replaced by if_wrapper

   initial begin: blk
      dut_if_wrapper if_wrapper = new ("if_wrapper", dut_if_inst1);
                   // path  field_name        value      0: don't clone
      set_config_object("*", "dut_if_wrapper", if_wrapper, 0);

      run_test ("my_test");
   end

endmodule : top

class dut_if_wrapper extends uvm_object;

   virtual dut_if dut_vi;
   function new (string s, virtual dut_if if_arg); 
      super.new(s);
      dut_vi = if_arg;
   endfunction : new

   // you can have task run; here

endclass : dut_if_wrapper

`include "uvm_macros.svh"

package my_pkg;
import uvm_pkg::*;

// Fixed test environment
class my_env extends uvm_env;
    `uvm_component_utils (my_env)

    virtual dut_if dut_virtual_if_inst;

    // constructor
    function new (string s, uvm_component inst_parent);
        super.new (s, inst_parent);
    endfunction : new

    function void build;
        super.build ();
        begin
            uvm_object obj;
            dut_if_wrapper if_wrapper; 
            get_config_object("dut_if_wrapper", obj, 0);
            assert( $cast(if_wrapper, obj) );
            dut_virtual_if_inst = if_wrapper.dut_vi;
        end
    endfunction : build

    task run;
        #10 dut_virtual_if_inst.data = 0;
        #10 dut_virtual_if_inst.data = 1;
        #10 stop_request();
    endtask : run

endclass : my_env


Example 7, use uvm_get_port and uvm_put_port in tlm_fifo / tlm_analysis_fifo
class producer extends uvm_agent;
   uvm_put_port #(int) phone1;
   ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      phone1 = new("phone1", this);
   endfunction

   virtual task run_phase (uvm_phase phase);
      phase.raise_objection(this);
      for (int i = 0; i < count; i++) begin : loop
         phone1.put(i);
         uvm_report_into ("run_phase", $psprintf("...");
      end : loop
      phase.drop_objection(this);
   endtask : run_phase

endclass : producer

class consumer extends uvm_agent;
   uvm_get_port #(int) phone2;
   ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase(phase);
      phone2 = new("phone2", this);
   endfunction

   virtual task run_phase (uvm_phase phase);
      phase.raise_objection(this);
      for (int i = 0; i < count; i++) begin : loop
         phone1.put(i);
         uvm_report_into ("run_phase", $psprintf("...");
      end : loop
      phase.drop_objection(this);
   endtask : run_phase

endclass : producer

class test_env extends uvm_env;

   producer p;
   consumer c;
   uvm_tlm_fifo #(int) tlmff;

   function new () ...

   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      p = producer::type_id::create ("p", this);
      p = producer::type_id::create ("p", this);
      tlmff = new ("tlmff", this);
   endfunction : build_phase

   virtual function void connect_phase (uvm_phase phase);
      super.connect_phase (phase);
      p.phone1.connect (tlmff.put_export);
      c.phone2.connect (tlmff.get_export);
   endfunction : connect_phase


Example 8, using uvm_config_db
module top;
   ...
   dut_if dut_if1 ();
   initial
   begin: blk
      //             type of value        prefix   path
      uvm_config_db #(virtual dut_if)::set(null, “uvm_test_top”, 
                  "dut_vi", dut_if1);
      //          field name, value
      run_test("my_test");
   end
endmodule: top

class my_test extends uvm_test;
   ...
   my_dut_config dut_config_0; 
   ...

   function void build_phase(uvm_phase phase);
      dut_config_0 = new();
      //             type of value    prefix   path
      if(!uvm_config_db #(dut_if)::get( this, “”, 
                        “dut_vi”, dut_config_0.dut_vi))
             `uvm_fatal(“MY_TEST”, “No DUT_IF”);

      // other DUT configuration settings
      uvm_config_db#(my_dut_config)::set(this, “*”, “dut_config”,
                                       dut_config_0);     
    endfunction
endclass

class my_driver extends uvm_driver;
   `uvm_component_utils(my_driver)
   virtual dut_if dut_vi;

   function new(string name, uvm_component parent); ...

   function void build_phase(uvm_phase phase); ...

   task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      #10 dut_vi.data = 0;
      #10 dut_vi.data = 1;
      #10 phase.drop_objection(this); 
   endtask: run_phase

endclass


No comments:

Post a Comment