357 lines
18 KiB
HTML
357 lines
18 KiB
HTML
<!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 — 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 user’s 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 <vpi_user.h>
|
||
|
||
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("Hello, World!\n");
|
||
return 0;
|
||
}
|
||
|
||
void hello_register(void)
|
||
{
|
||
s_vpi_systf_data tf_data;
|
||
|
||
tf_data.type = vpiSysTask;
|
||
tf_data.tfname = "$hello";
|
||
tf_data.calltf = hello_calltf;
|
||
tf_data.compiletf = hello_compiletf;
|
||
tf_data.sizetf = 0;
|
||
tf_data.user_data = 0;
|
||
vpi_register_systf(&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 user’s 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 don’t 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 <wid> <signed|unsigned></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=<module>:<boot_func>
|
||
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">
|
||
©2024-2025, Stephen Williams.
|
||
|
||
|
|
||
Powered by <a href="http://sphinx-doc.org/">Sphinx 7.2.6</a>
|
||
& <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> |