.. Copyright 2003-2021 by Wilson Snyder.
.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

.. _Connecting:

******************************
Connecting to Verilated Models
******************************

.. _Connecting to C++:

Connecting to C++
=================

Verilator creates a :file:`{prefix}.h` and :file:`{prefix}.cpp` file for
the top level module, together with additional .h and .cpp files for
internals. See the :file:`examples` directory in the kit for examples.  See
:ref:`Files Read/Written` for information on all the files it writes.

After the model is created, there will be a :file:`{prefix}.mk` file that
may be used with Make to produce a :file:`{prefix}__ALL.a` file with all
required objects in it.

The user must write a C++ wrapper and main loop for the simulation, to link
with the Verilated model.  Here is a simple example:

.. code-block:: C++

         #include <verilated.h>          // Defines common routines
         #include <iostream>             // Need std::cout
         #include "Vtop.h"               // From Verilating "top.v"

         Vtop *top;                      // Instantiation of module

         vluint64_t main_time = 0;       // Current simulation time
         // This is a 64-bit integer to reduce wrap over issues and
         // allow modulus.  This is in units of the timeprecision
         // used in Verilog (or from --timescale-override)

         double sc_time_stamp() {        // Called by $time in Verilog
             return main_time;           // converts to double, to match
                                         // what SystemC does
         }

         int main(int argc, char** argv) {
             Verilated::commandArgs(argc, argv);   // Remember args

             top = new Vtop;             // Create instance

             top->reset_l = 0;           // Set some inputs

             while (!Verilated::gotFinish()) {
                 if (main_time > 10) {
                     top->reset_l = 1;   // Deassert reset
                 }
                 if ((main_time % 10) == 1) {
                     top->clk = 1;       // Toggle clock
                 }
                 if ((main_time % 10) == 6) {
                     top->clk = 0;
                 }
                 top->eval();            // Evaluate model
                 cout << top->out << endl;       // Read a output
                 main_time++;            // Time passes...
             }

             top->final();               // Done simulating
             //    // (Though this example doesn't get here)
             delete top;
         }


Note signals are read and written as member variables of the model.  You
call the :code:`eval()` method to evaluate the model.  When the simulation
is complete call the :code:`final()` method to execute any SystemVerilog
final blocks, and complete any assertions. See :ref:`Evaluation Loop`.


Connecting to SystemC
=====================

Verilator will convert the top level module to a SC_MODULE.  This module
will attach directly into a SystemC netlist as an instantiation.

The SC_MODULE gets the same pinout as the Verilog module, with the
following type conversions: Pins of a single bit become bool.  Pins 2-32
bits wide become uint32_t's.  Pins 33-64 bits wide become sc_bv's or
vluint64_t's depending on the :vlopt:`--no-pins64` option.  Wider pins
become sc_bv's.  (Uints simulate the fastest so are used where possible.)

Lower modules are not pure SystemC code.  This is a feature, as using the
SystemC pin interconnect scheme everywhere would reduce performance by an
order of magnitude.


Direct Programming Interface (DPI)
==================================

Verilator supports SystemVerilog Direct Programming Interface import and
export statements.  Only the SystemVerilog form ("DPI-C") is supported, not
the original Synopsys-only DPI.

DPI Example
-----------

In the SYSTEMC example above, if you wanted to import C++ functions into
Verilog, put in our.v:

.. code-block::

    import "DPI-C" function int add (input int a, input int b);

    initial begin
       $display("%x + %x = %x", 1, 2, add(1,2));
    endtask

Then after Verilating, Verilator will create a file Vour__Dpi.h with the
prototype to call this function:

.. code-block:: C++

     extern int add(int a, int b);

From the sc_main.cpp file (or another .cpp file passed to the Verilator
command line, or the link), you'd then:

.. code-block:: C++

     #include "svdpi.h"
     #include "Vour__Dpi.h"
     int add(int a, int b) { return a+b; }


DPI System Task/Functions
-------------------------

Verilator extends the DPI format to allow using the same scheme to
efficiently add system functions.  Simply use a dollar-sign prefixed system
function name for the import, but note it must be escaped.

.. code-block:: sv

    export "DPI-C" function integer \$myRand;

    initial $display("myRand=%d", $myRand());

Going the other direction, you can export Verilog tasks so they can be
called from C++:

.. code-block:: sv

    export "DPI-C" task publicSetBool;

    task publicSetBool;
       input bit in_bool;
       var_bool = in_bool;
    endtask

Then after Verilating, Verilator will create a file Vour__Dpi.h with the
prototype to call this function:

.. code-block:: C++

     extern void publicSetBool(svBit in_bool);

From the sc_main.cpp file, you'd then:

.. code-block:: C++

     #include "Vour__Dpi.h"
     publicSetBool(value);

Or, alternatively, call the function under the design class.  This isn't
DPI compatible but is easier to read and better supports multiple designs.

.. code-block:: C++

     #include "Vour__Dpi.h"
     Vour::publicSetBool(value);
     // or top->publicSetBool(value);

Note that if the DPI task or function accesses any register or net within
the RTL, it will require a scope to be set. This can be done using the
standard functions within svdpi.h, after the module is instantiated, but
before the task(s) and/or function(s) are called.

For example, if the top level module is instantiated with the name "dut"
and the name references within tasks are all hierarchical (dotted) names
with respect to that top level module, then the scope could be set with

.. code-block:: C++

     #include "svdpi.h"
     ...
     svSetScope(svGetScopeFromName("TOP.dut"));

(Remember that Verilator adds a "TOP" to the top of the module hierarchy.)

Scope can also be set from within a DPI imported C function that has been
called from Verilog by querying the scope of that function. See the
sections on DPI Context Functions and DPI Header Isolation below and the
comments within the svdpi.h header for more information.


DPI Imports that access signals
-------------------------------

If a DPI import accesses a signal through the VPI Verilator will not be
able to know what variables are accessed and may schedule the code
inappropriately.  Ideally pass the values as inputs/outputs so the VPI is
not required.  Alternatively a workaround is to use a non-inlined task as a
wrapper:

.. code-block::

     logic din;

     // This DPI function will read "din"
     import "DPI-C" context function void dpi_that_accesses_din();

     always @(...)
        dpi_din_args(din);

     task dpi_din_args(input din);
        /* verilator no_inline_task */
        dpi_that_accesses_din();
     endtask


DPI Display Functions
---------------------

Verilator allows writing $display like functions using this syntax:

.. code-block::

    import "DPI-C" function void
          \$my_display(input string formatted /*verilator sformat*/ );

The :option:`/*verilator&32;sformat*/` metacomment indicates that this
function accepts a $display like format specifier followed by any number of
arguments to satisfy the format.


DPI Context Functions
---------------------

Verilator supports IEEE DPI Context Functions.  Context imports pass the
simulator context, including calling scope name, and filename and line
number to the C code.  For example, in Verilog:

.. code-block::

    import "DPI-C" context function int dpic_line();
    initial $display("This is line %d, again, line %d\n", `line, dpic_line());

This will call C++ code which may then use the svGet\* functions to read
information, in this case the line number of the Verilog statement that
invoked the dpic_line function:

.. code-block:: C++

    int dpic_line() {
        // Get a scope:  svScope scope = svGetScope();

        const char* scopenamep = svGetNameFromScope(scope);
        assert(scopenamep);

        const char* filenamep = "";
        int lineno = 0;
        if (svGetCallerInfo(&filenamep, &lineno)) {
            printf("dpic_line called from scope %s on line %d\n",
               scopenamep, lineno);
            return lineno;
        } else {
            return 0;
        }
    }

See the IEEE Standard for more information.


DPI Header Isolation
--------------------

Verilator places the IEEE standard header files such as svdpi.h into a
separate include directory, vltstd (VeriLaTor STandarD).  When compiling
most applications $VERILATOR_ROOT/include/vltstd would be in the include
path along with the normal $VERILATOR_ROOT/include.  However, when
compiling Verilated models into other simulators which have their own
svdpi.h and similar standard files with different contents, the vltstd
directory should not be included to prevent picking up incompatible
definitions.


Public Functions
----------------

Instead of DPI exporting, there's also Verilator public functions, which
are slightly faster, but less compatible.


Verification Procedural Interface (VPI)
=======================================

Verilator supports a limited subset of the VPI.  This subset allows
inspection, examination, value change callbacks, and depositing of values
to public signals only.

VPI is enabled with the Verilator :vlopt:`--vpi` option.

To access signals via the VPI, Verilator must be told exactly which signals
are to be accessed.  This is done using the Verilator public pragmas
documented below.

Verilator has an important difference from an event based simulator; signal
values that are changed by the VPI will not immediately propagate their
values, instead the top level header file's :code:`eval()` method must be
called.  Normally this would be part of the normal evaluation (i.e. the
next clock edge), not as part of the value change.  This makes the
performance of VPI routines extremely fast compared to event based
simulators, but can confuse some test-benches that expect immediate
propagation.

Note the VPI by its specified implementation will always be much slower
than accessing the Verilator values by direct reference
(structure->module->signame), as the VPI accessors perform lookup in
functions at simulation runtime requiring at best hundreds of instructions,
while the direct references are evaluated by the compiler and result in
only a couple of instructions.

For signal callbacks to work the main loop of the program must call
:code:`VerilatedVpi::callValueCbs()`.


.. _VPI Example:

VPI Example
-----------

In the below example, we have readme marked read-only, and writeme which if
written from outside the model will have the same semantics as if it
changed on the specified clock edge.

.. code-block:: bash

     cat >our.v <<'EOF'
       module our (input clk);
          reg readme   /*verilator public_flat_rd*/;
          reg writeme  /*verilator public_flat_rw @(posedge clk) */;
          initial $finish;
       endmodule
     EOF

There are many online tutorials and books on the VPI, but an example that
accesses the above signal "readme" would be:

.. code-block:: bash

     cat >sim_main.cpp <<'<<EOF'
       #include "Vour.h"
       #include "verilated.h"
       #include "verilated_vpi.h"  // Required to get definitions

       vluint64_t main_time = 0;   // See comments in first example
       double sc_time_stamp() { return main_time; }

       void read_and_check() {
           vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"TOP.our.readme", NULL);
           if (!vh1) vl_fatal(__FILE__, __LINE__, "sim_main", "No handle found");
           const char* name = vpi_get_str(vpiName, vh1);
           printf("Module name: %s\n", name);  // Prints "readme"

           s_vpi_value v;
           v.format = vpiIntVal;
           vpi_get_value(vh1, &v);
           printf("Value of v: %d\n", v.value.integer);  // Prints "readme"
       }

       int main(int argc, char** argv, char** env) {
           Verilated::commandArgs(argc, argv);
           Vour* top = new Vour;
           Verilated::internalsDump();  // See scopes to help debug
           while (!Verilated::gotFinish()) {
               top->eval();
               VerilatedVpi::callValueCbs();  // For signal callbacks
               read_and_check();
           }
           delete top;
           return 0;
       }
     EOF


.. _Evaluation Loop:

Wrappers and Model Evaluation Loop
==================================

When using SystemC, evaluation of the Verilated model is managed by the
SystemC kernel, and for the most part can be ignored.  When using C++, the
user must call :code:`eval()`, or :code:`eval_step()` and
:code:`eval_end_step()`.

1. When there is a single design instantiated at the C++ level that needs
to evaluate within a given context, call :code:`designp->eval()`.

2. When there are multiple designs instantiated at the C++ level that need
to evaluate within a context, call :code:`first_designp->eval_step()` then
:code:`->eval_step()` on all other designs.  Then call
:code:`->eval_end_step()` on the first design then all other designs.  If
there is only a single design, you would call :code:`eval_step()` then
:code:`eval_end_step()`; in fact :code:`eval()` described above is just a
wrapper which calls these two functions.

When :code:`eval()` (or :code:`eval_step()`) is called Verilator looks for
changes in clock signals and evaluates related sequential always blocks,
such as computing always_ff @ (posedge...) outputs.  Then Verilator
evaluates combinatorial logic.

Note combinatorial logic is not computed before sequential always blocks
are computed (for speed reasons). Therefore it is best to set any non-clock
inputs up with a separate :code:`eval()` call before changing clocks.

Alternatively, if all always_ff statements use only the posedge of clocks,
or all inputs go directly to always_ff statements, as is typical, then you
can change non-clock inputs on the negative edge of the input clock, which
will be faster as there will be fewer :code:`eval()` calls.

For more information on evaluation, see :file:`docs/internals.rst` in the
distribution.


Verilated and VerilatedContext
==============================

Multiple Verilated models may be part of the same simulation context, that
is share a VPI interface, sense of time, and common settings.  This common
simulation context information is stored in a ``VerilatedContext``
structure.  If a ``VerilatedContext`` is not created prior to creating a
model, a default global one is created automatically.

The ``Verilated::`` methods, including the ``Verilated::commandArgs`` call
shown above, simply call VerilatedContext methods using the default global
VerilatedContext.  (Technically they operate on the last one used by a
given thread.)  If you are using multiple simulation contexts you should
not use the Verilated:: methods, and instead always use VerilatedContext
methods called on the appropriate VerilatedContext object.

For methods available under Verilated and VerilatedContext see
:file:`include/verilated.h` in the distribution.
