0
votes

What is the meaning of "virtual tinyalu_bfm" in the SystemVerilog code below? example:

        uvm_config_db #(virtual tinyalu_bfm)::set(null, "*", "bfm", bfm);

would it make any difference if i omitted the virtual keyword? Just curious, because the usually oop meaning of virtual is applied only to classes or class members and here's an example where its applied to an interface being passed into a static function that's part of UVM package... just wanted to know why I need to call it virutal in this case and what its purpose is to make it virtual.

    module top;

        // UVM Framework
        import uvm_pkg::*;
        `include "uvm_macros.svh"

        import   tinyalu_pkg::*;       //import all tb classes and types

        tinyalu_bfm       bfm();

        // invoke APIs from uvm_pkg to start test...
        initial begin
            uvm_config_db #(virtual tinyalu_bfm)::set(null, "*", "bfm", bfm);

            run_test();  
        end

    endmodule : top
    interface tinyalu_bfm;

       byte         unsigned        A;
       byte         unsigned        B;
       bit          clk;
       bit          reset_n;

       initial begin
          clk = 0;
          forever begin
             #10;
             clk = ~clk;
          end
       end

       task reset_alu();
          reset_n = 1'b0;
          @(negedge clk);
          @(negedge clk);
          reset_n = 1'b1;
          start = 1'b0;
       endtask : reset_alu

      task send_op(input byte iA, input byte iB, input operation_t iop, output shortint alu_result);
           // ...       
       endtask : send_op

    endinterface : tinyalu_bfm

see here again... the interface object is declared virtual as well...why?

 // FILE: random_test.svh
    class random_test extends uvm_test;
        // ... 
        virtual tinyalu_bfm bfm;

        function new (string name, uvm_component parent);
            super.new(name,parent);
            if(!uvm_config_db #(virtual tinyalu_bfm)::get(null, "*","bfm", bfm))
                $fatal("Failed to get BFM");
        endfunction : new

        task run_phase(uvm_phase phase);
            //...
        endtask : run_phase

    endclass

3
See, Chapter 10: Advanced Interfaces, of "System Verilog for Verification" 3rd Edition, 2012, By Chris Spear, and Greg Tumbush..."A better name for a virtual interface would be a "ref interface." - pico

3 Answers

2
votes

SystemVerilog was created to be fully backward compatible with Verilog with the exception being newly reserved keywords. So SystemVerilog re-uses, or overloads existing keywords as much as possible to reduce keyword bloat. The virtual keyword in front of an interface name means you are declaring variable type that contains a handle to an actual interface instance, and not an actual interface instance,

1
votes

Analog to a virtual interface in normal programming languages is a pointer or a reference (to the interface object). It is used as a reference in system verilog test bench components, passing it as function or task arguments or storing it in classes or other places.

System verilog is a huge language with a lot of ugliness in it. The virtual keyword is definitely overused, as in this case. There could have been a better choice.

|

0
votes

I suggest the following define macro to make up for bad language choose by the designers of SystemVerilog to overload virtual keyword is a strange way:

    `define REFERENCE virtual

    module top;

        // UVM Framework
        import uvm_pkg::*;
        `include "uvm_macros.svh"

        import   tinyalu_pkg::*;       //import all tb classes and types

        tinyalu_bfm       bfm();

        // invoke APIs from uvm_pkg to start test...
        initial begin
            uvm_config_db #(`REFERENCE tinyalu_bfm)::set(null, "*", "bfm", bfm);

            run_test();  
        end

    endmodule : top
    interface tinyalu_bfm;
    // ...

    endinterface : tinyalu_bfm

see here again... the interface object is declared virtual as well...why?

 // FILE: random_test.svh
    class random_test extends uvm_test;
        // ... 
        `REFERENCE tinyalu_bfm bfm;

        function new (string name, uvm_component parent);
            super.new(name,parent);
            if(!uvm_config_db #(`REFERENCE tinyalu_bfm)::get(null, "*","bfm", bfm))
                $fatal("Failed to get BFM");
        endfunction : new

        task run_phase(uvm_phase phase);
            //...
        endtask : run_phase

    endclass