iverilog/usage/vpi.html

357 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Using VPI &#8212; Icarus Verilog documentation</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css?v=cb25574f" />
<script src="../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../_static/doctools.js?v=888ff710"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Icarus Verilog Extensions" href="icarus_verilog_extensions.html" />
<link rel="prev" title="Waveforms With GTKWave" href="gtkwave.html" />
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head><body>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="using-vpi">
<h1>Using VPI<a class="headerlink" href="#using-vpi" title="Link to this heading"></a></h1>
<p>Icarus Verilog implements a portion of the PLI 2.0 API to Verilog. This allows
programmers to write C code that interfaces with Verilog simulations to
perform tasks otherwise impractical with straight Verilog. Many Verilog
designers, especially those who only use Verilog as a synthesis tool, can
safely ignore the entire matter of the PLI (and this chapter) but the designer
who wishes to interface a simulation with the outside world cannot escape VPI.</p>
<p>The rest of this article assumes some knowledge of C programming, Verilog PLI,
and of the compiler on your system. In most cases, Icarus Verilog assumes the
GNU Compilation System is the compiler you are using, so tips and instructions
that follow reflect that. If you are not a C programmer, or are not planning
any VPI modules, you can skip this entire article. There are references at the
bottom for information about more general topics.</p>
<section id="how-it-works">
<h2>How It Works<a class="headerlink" href="#how-it-works" title="Link to this heading"></a></h2>
<p>The VPI modules are compiled loadable object code that the runtime loads at
the users request. The user commands vvp to locate and load modules with the
“-m” switch. For example, to load the “sample.vpi” module:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>% vvp -msample foo.vvp
</pre></div>
</div>
<p>The vvp run-time loads the modules first, before executing any of the
simulation, or even before compiling the vvp code. Part of the loading
includes invoking initialization routines. These routines register with the
run-time all the system tasks and functions that the module implements. Once
this is done, the run time loader can match names of the called system tasks
of the design with the implementations in the VPI modules.</p>
<p>(There is a special module, the system.vpi module, that is always loaded to
provide the core system tasks.)</p>
<p>The simulator run time (The “vvp” program) gets a handle on a freshly loaded
module by looking for the symbol “vlog_startup_routines” in the loaded
module. This table, provided by the module author and compiled into the
module, is a null terminated table of function pointers. The simulator calls
each of the functions in the table in order. The following simple C definition
defines a sample table:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>void (*vlog_startup_routines[])(void) = {
hello_register,
0
};
</pre></div>
</div>
<p>Note that the “vlog_startup_routines” table is an array of function pointers,
with the last pointer a 0 to mark the end. The programmer can organize the
module to include many startup functions in this table, if desired.</p>
<p>The job of the startup functions that are collected in the startup table is to
declare the system tasks and functions that the module provides. A module may
implement as many tasks/functions as desired, so a module can legitimately be
called a library of system tasks and functions.</p>
</section>
<section id="compiling-vpi-modules">
<h2>Compiling VPI Modules<a class="headerlink" href="#compiling-vpi-modules" title="Link to this heading"></a></h2>
<p>To compile and link a VPI module for use with Icarus Verilog, you must compile
all the source files of a module as if you were compiling for a DLL or shared
object. With gcc under Linux, this means compiling with the “-fpic” flag. The
module is then linked together with the vpi library like so:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>% gcc -c -fpic hello.c
% gcc -shared -o hello.vpi hello.o -lvpi
</pre></div>
</div>
<p>This assumes that the “vpi_user.h header file and the libvpi.a library file
are installed on your system so that gcc may find them. This is normally the
case under Linux and UNIX systems. An easier, the preferred method that works
on all supported systems is to use the single command:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>% iverilog-vpi hello.c
</pre></div>
</div>
<p>The “iverilog-vpi” command takes as command arguments the source files for
your VPI module, compiles them with proper compiler flags, and links them into
a vpi module with any system specific libraries and linker flags that are
required. This simple command makes the “hello.vpi” module with minimum fuss.</p>
</section>
<section id="a-worked-example">
<h2>A Worked Example<a class="headerlink" href="#a-worked-example" title="Link to this heading"></a></h2>
<p>Let us try a complete, working example. Place the C code that follows into the
file hello.c:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># include &lt;vpi_user.h&gt;
static int hello_compiletf(char*user_data)
{
(void)user_data; // Avoid a warning since user_data is not used.
return 0;
}
static int hello_calltf(char*user_data)
{
(void)user_data; // Avoid a warning since user_data is not used.
vpi_printf(&quot;Hello, World!\n&quot;);
return 0;
}
void hello_register(void)
{
s_vpi_systf_data tf_data;
tf_data.type = vpiSysTask;
tf_data.tfname = &quot;$hello&quot;;
tf_data.calltf = hello_calltf;
tf_data.compiletf = hello_compiletf;
tf_data.sizetf = 0;
tf_data.user_data = 0;
vpi_register_systf(&amp;tf_data);
}
void (*vlog_startup_routines[])(void) = {
hello_register,
0
};
</pre></div>
</div>
<p>and place the Verilog code that follows into hello.v:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>module main;
initial $hello;
endmodule
</pre></div>
</div>
<p>Next, compile and execute the code with these steps:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>% iverilog-vpi hello.c
% iverilog -ohello.vvp hello.v
% vvp -M. -mhello hello.vvp
Hello, World!
</pre></div>
</div>
<p>The compile and link in this example are conveniently combined into the
“iverilog-vpi” command. The “iverilog” command then compiles the “hello.v”
Verilog source file to the “hello.vvp” program. Next, the “vvp” command
demonstrates the use of the “-M” and “-m” flags to specify a vpi module search
directory and vpi module name. Specifically, they tell the “vvp” command where
to find the module we just compiled.</p>
<p>The “vvp” command, when executed as above, loads the “hello.vpi” module that
it finds in the current working directory. When the module is loaded, the
vlog_startup_routines table is scanned, and the “hello_register” function is
executed. The “hello_register” function in turn tells “vvp” about the system
tasks that are included in this module.</p>
<p>After the modules are all loaded, the “hello.vvp” design file is loaded and
its call to the “$hello” system task is matched up to the version declared by
the module. While “vvp” compiles the “hello.vvp” source, any calls to “$hello”
are referred to the “compiletf” function. This function is called at compile
time and can be used to check parameters to system tasks or function. It can
be left empty like this, or left out completely. The “compiletf” function can
help performance by collecting parameter checks in compile time, so they do
not need to be done each time the system task is run, thus potentially saving
execution time overall.</p>
<p>When the run-time executes the call to the hello system task, the
“hello_calltf” function is invoked in the loaded module, and thus the output
is generated. The “calltf” function is called at run time when the Verilog
code actually executes the system task. This is where the active code of the
task belongs.</p>
</section>
<section id="system-function-return-types">
<h2>System Function Return Types<a class="headerlink" href="#system-function-return-types" title="Link to this heading"></a></h2>
<p>Icarus Verilog supports system functions as well as system tasks, but there is
a complication. Notice how the module that you compile is only loaded by the
“vvp” program. This is mostly not an issue, but elaboration of expressions
needs to keep track of types, so the main compiler needs to know the return
type of functions.</p>
<p>Starting with Icarus Verilog v11, the solution is quite simple. The names and
locations of the users VPI modules can be passed to the compiler via the
“iverilog” -m and -L flags and the IVERILOG_VPI_MODULE_PATH environment
variable. The compiler will load and analyse the specified modules to
automatically determine any function return types. The compiler will also
automatically pass the names and locations of the specified modules to the
“vvp” program, so that they dont need to be specified again on the “vvp”
command line.</p>
<p>For Icarus Verilog versions prior to v11, the solution requires that the
developer of a module include the table in a form that the compiler can
read. The System Function Table file carries this information. A simple
example looks like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span># Example sft declarations of some common functions
$random vpiSysFuncInt
$bitstoreal vpiSysFuncReal
$realtobits vpiSysFuncSized 64 unsigned
</pre></div>
</div>
<p>This demonstrates the format of the file and support types. Each line contains
a comment (starts with “#”) or a type declaration for a single function. The
declaration starts with the name of the system function (including the leading
“$”) and ends with the type. The supported types are:</p>
<ul class="simple">
<li><p>vpiSysFuncInt</p></li>
<li><p>vpiSysFuncReal</p></li>
<li><p>vpiSysFuncSized &lt;wid&gt; &lt;signed|unsigned&gt;</p></li>
</ul>
<p>Any functions that do not have an explicit type declaration in an SFT file are
implicitly taken to be “vpiSysFuncSized 32 unsigned”.</p>
<p>The module author provides, along with the “.vpi” file that is the module, a
“.sft” that declares all the function return types. For example, if the file
is named “example.sft”, pass it to the “iverilog” command line or in the
command file exactly as if it were an ordinary source file.</p>
</section>
<section id="cadence-pli-modules">
<h2>Cadence PLI Modules<a class="headerlink" href="#cadence-pli-modules" title="Link to this heading"></a></h2>
<p>With the cadpli module, Icarus Verilog is able to load PLI1 applications that
were compiled and linked to be dynamic loaded by Verilog-XL or
NC-Verilog. This allows Icarus Verilog users to run third-party modules that
were compiled to interface with XL or NC. Obviously, this only works on the
operating system that the PLI application was compiled to run on. For example,
a Linux module can only be loaded and run under Linux. In addition, a 64-bit
version of vvp can only load 64-bit PLI1 applications, etc.</p>
<p>Icarus Verilog uses an interface module, the “cadpli” module, to connect the
worlds. This module is installed with Icarus Verilog, and is invoked by the
usual -m flag to iverilog or vvp. This module in turn scans the extended
arguments, looking for -cadpli= arguments. The latter specify the share object
and bootstrap function for running the module. For example, to run the module
product.so, that has the bootstrap function “my_boot”:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>% vvp -mcadpli a.out -cadpli=./product.so:my_boot
</pre></div>
</div>
<p>The “-mcadpli” argument causes vvp to load the cadpli.vpl library module. This
activates the -cadpli= argument interpreter. The -cadpli=&lt;module&gt;:&lt;boot_func&gt;
argument, then, causes vvp, through the cadpli module, to load the loadable
PLI application, invoke the my_boot function to get a veriusertfs table, and
scan that table to register the system tasks and functions exported by that
object. The format of the -cadpli= extended argument is essentially the same
as the +loadpli1= argument to Verilog-XL.</p>
<p>The integration from this point is seamless. The PLI application hardly knows
that it is being invoked by Icarus Verilog instead of Verilog-XL, so operates
as it would otherwise.</p>
</section>
<section id="other-references">
<h2>Other References<a class="headerlink" href="#other-references" title="Link to this heading"></a></h2>
<p>Since the above only explains how to get PLI/VPI working with Icarus Verilog,
here are some references to material to help with the common aspects of
PLI/VPI.</p>
<ul class="simple">
<li><p>Principles of Verilog PLI by Swapnajit Mittra. ISBN 0-7923-8477-6</p></li>
<li><p>The Verilog PLI Handbook by Stuart Sutherland. ISBN 0-7923-8489-X</p></li>
</ul>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="../index.html">Icarus Verilog</a></h1>
<h3>Navigation</h3>
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Icarus Verilog Usage</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="installation.html">Installation Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="getting_started.html">Getting Started With Icarus Verilog</a></li>
<li class="toctree-l2"><a class="reference internal" href="simulation.html">Simulation Using Icarus Verilog</a></li>
<li class="toctree-l2"><a class="reference internal" href="command_line_flags.html">iverilog Command Line Flags</a></li>
<li class="toctree-l2"><a class="reference internal" href="command_files.html">Command File Format</a></li>
<li class="toctree-l2"><a class="reference internal" href="verilog_attributes.html">Verilog Attributes</a></li>
<li class="toctree-l2"><a class="reference internal" href="ivlpp_flags.html">IVLPP - IVL Preprocessor</a></li>
<li class="toctree-l2"><a class="reference internal" href="vvp_flags.html">VVP Command Line Flags</a></li>
<li class="toctree-l2"><a class="reference internal" href="vvp_debug.html">VVP Interactive Mode</a></li>
<li class="toctree-l2"><a class="reference internal" href="vvp_library.html">VVP as a library</a></li>
<li class="toctree-l2"><a class="reference internal" href="vhdlpp_flags.html">vhdlpp Command Line Flags</a></li>
<li class="toctree-l2"><a class="reference internal" href="gtkwave.html">Waveforms With GTKWave</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Using VPI</a></li>
<li class="toctree-l2"><a class="reference internal" href="icarus_verilog_extensions.html">Icarus Verilog Extensions</a></li>
<li class="toctree-l2"><a class="reference internal" href="icarus_verilog_quirks.html">Icarus Verilog Quirks</a></li>
<li class="toctree-l2"><a class="reference internal" href="reporting_issues.html">Reporting Issues</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../targets/index.html">The Icarus Verilog Targets</a></li>
<li class="toctree-l1"><a class="reference internal" href="../developer/index.html">Icarus Verilog Developer Support</a></li>
</ul>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="../index.html">Documentation overview</a><ul>
<li><a href="index.html">Icarus Verilog Usage</a><ul>
<li>Previous: <a href="gtkwave.html" title="previous chapter">Waveforms With GTKWave</a></li>
<li>Next: <a href="icarus_verilog_extensions.html" title="next chapter">Icarus Verilog Extensions</a></li>
</ul></li>
</ul></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>document.getElementById('searchbox').style.display = "block"</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
&copy;2024-2025, Stephen Williams.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 7.2.6</a>
&amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
<a href="../_sources/usage/vpi.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>