From 2781aa05e170cbb675193672e3d1ef18919c8267 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 11 Apr 2022 20:46:06 -0700 Subject: [PATCH] Documentation: Transferring more content from the wiki This finishes up most of the User Guide from the Wiki. Some bits from the wiki are just too aweful, or obsolete, so are left out. --- Documentation/targets/index.rst | 4 +- Documentation/targets/pcb.rst | 61 ++++ Documentation/targets/verilog95.rst | 101 ++++++ Documentation/targets/vhdl.rst | 82 +++++ Documentation/usage/command_files.rst | 198 +++++++++++ Documentation/usage/index.rst | 5 + Documentation/usage/installation.rst | 146 ++++++++ Documentation/usage/ivl_target.rst | 106 ++++++ Documentation/usage/simulation.rst | 487 ++++++++++++++++++++++++++ Documentation/usage/vpi.rst | 246 +++++++++++++ 10 files changed, 1435 insertions(+), 1 deletion(-) create mode 100644 Documentation/targets/pcb.rst create mode 100644 Documentation/targets/verilog95.rst create mode 100644 Documentation/targets/vhdl.rst create mode 100644 Documentation/usage/command_files.rst create mode 100644 Documentation/usage/installation.rst create mode 100644 Documentation/usage/ivl_target.rst create mode 100644 Documentation/usage/simulation.rst create mode 100644 Documentation/usage/vpi.rst diff --git a/Documentation/targets/index.rst b/Documentation/targets/index.rst index 6e8bbbe4fa..9664de14e6 100644 --- a/Documentation/targets/index.rst +++ b/Documentation/targets/index.rst @@ -13,4 +13,6 @@ Icarus Verilog. The code generator is selected by the "-t" command line flag. vvp stub null - + vhdl + verilog95 + pcb diff --git a/Documentation/targets/pcb.rst b/Documentation/targets/pcb.rst new file mode 100644 index 0000000000..68c886bbff --- /dev/null +++ b/Documentation/targets/pcb.rst @@ -0,0 +1,61 @@ + +Using the PCB code generator +============================ + +The PCB target code generator is designed to allow a user to enter a netlist +in Verilog format, then generate input files for the GNU PCB layout program. + +Invocation +---------- + +The PCB target code generation is invoked with the -tpcb flag to the iverilog +command. The default output file, "a.out", contains the generated .PCB +file. Use the "-o" flag to set the output file name explicitly. The default +output file contains only the elements. To generate a "netlist" file, add the +flag "-pnetlist=" command line flag. + +Altogether, this example generates the foo.net and foo.pcb files from the +foo.v source file:: + + % iverilog -tpcb -ofoo.pcb -pnetlist=foo.net foo.v + +Flags +----- + +* -o + + Set the output (pcb) file path + +* -pnetlist=path + + Write a netlist file to the given path. + +Attributes Summary +------------------ + +Attributes are attached to various constructs using the Verilog "(* *)" +attribute syntax. + +* ivl_black_box + + Attached to a module declaration or module instantiation, this indicates + that the module is a black box. The code generator will create an element + for black box instances. + +Parameters Summary +------------------ + +Within modules, The PCB code generator uses certain parameters to control +details. Parameters may have defaults, and can be overridden using the usual +Verilog parameter override syntax. Parameters have preferred types. + +* description (string, default="") + + The "description" is a text string that describes the black box. This string + is written into the description field of the PCB Element. + +* value (string, default="") + + The "value" is a text tring that describes some value for the black + box. Like the description, the code generator does not interpret this value, + other then to write it to the appropriate field in the PCB Element." diff --git a/Documentation/targets/verilog95.rst b/Documentation/targets/verilog95.rst new file mode 100644 index 0000000000..5312229ce6 --- /dev/null +++ b/Documentation/targets/verilog95.rst @@ -0,0 +1,101 @@ + +Using The Verilog '95 Code Generator +==================================== + +Icarus Verilog contains a code generator to emit 1995 compliant Verilog from +the input Verilog netlist. This allows Icarus Verilog to function as a Verilog +> 1995 to Verilog 1995 translator. The main goal of the project was to convert +@*, ANSI style arguments and other constructs to something allowed in 1995 +Verilog. + +Invocation +---------- + +To translate a Verilog program to 1995 compliant Verilog, invoke "iverilog" +with the -tvlog95 flag:: + + % iverilog -tvlog95 -o my_design_95.v my_design.v + +The generated Verilog will be placed in a single file (a.out by default), even +if the input Verilog is spread over multiple files. + +Generator Flags +--------------- + +* -pspacing=N + + Set the indent spacing (the default is 2). + +* -pallowsigned=1 + + Allow emitting the various signed constructs as an extension to 1995 Verilog + (off by default). + +* -pfileline=1 + + Emit the original file and line information as a comment for each generated + line (off by default). + +Structures that cannot be converted to 1995 compatible Verilog +-------------------------------------------------------------- + +The following Verilog constructs are not translatable to 1995 compatible Verilog: + +* Automatic tasks or functions. + +* The power operator (**). Expressions of the form (2**N)** (where N + is a constant) can be converter to a shift. + +* Some System Verilog constructs (e.g. final blocks, ++/-- operators, + etc.). 2-state variables are converted to 4-state variables. + +Icarus extensions that cannot be translated: + +* Integer constants greater than 32 bits. + +* Real valued nets. + +* Real modulus. + +* Most Verilog-A constructs. + + +Known Issues and Limitations +---------------------------- + +Some things are just not finished and should generate an appropriate +warning. Here is a list of the major things that still need to be looked at. + +* There are still a few module instantiation port issues (pr1723367 and + partselsynth). + +* inout ports are not converted (tran-VP). + +* Variable selects of a non-zero based vector in a continuous assignment are + not converted. + +* There is no support for translating a zero repeat in a continuous + assignment. It is currently just dropped. + +* A pull device connected to a signal select is not translated correctly (this + may be fixed). + +* L-value indexed part selects with a constant undefined base in a continuous + assignment are not translated. + +* Logic gates are not arrayed exactly the same as the input and the instance + name is not always the same. + +* The signed support does not generate $signed() or $unsigned() function calls + in a continuous assignment expression. + +* The special power operator cases are not converted in a continuous + assignment. + +* Currently a signed constant that sets the MSB in an unsigned context will be + displayed as a negative value (e.g. bit = 1 translates to bit = -1). + +* Can net arrays, etc. be unrolled? + +* Can generate blocks be converted? + diff --git a/Documentation/targets/vhdl.rst b/Documentation/targets/vhdl.rst new file mode 100644 index 0000000000..d9a095c0ca --- /dev/null +++ b/Documentation/targets/vhdl.rst @@ -0,0 +1,82 @@ + +The VHDL Code Generator (-tvhdl) +================================ + +Icarus Verilog contains a code generator to emit VHDL from the Verilog +netlist. This allows Icarus Verilog to function as a Verilog to VHDL +translator. + +Invocation +---------- + +To translate a Verilog program to VHDL, invoke "iverilog" with the -tvhdl +flag:: + + % iverilog -t vhdl -o my_design.vhd my_design.v + +The generated VHDL will be placed in a single file (a.out by default), even if +the Verilog is spread over multiple files. + +Flags +----- + +* -pdebug=1 + + Print progress messages as the code generator visits each part of the + design. + +* -pdepth=N + + Only output VHDL entities for modules found at depth < N in the + hierarchy. N=0, the default, outputs all entities. For example, -pdepth=1 + outputs only the top-level entity. + +Supported Constructs +-------------------- + +TODO + +Limitations +----------- + +Signal Values and Resolution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are several cases where the behaviour of the translated VHDL deviates +from the source Verilog: + +* The result of division by zero is x in Verilog but raises an exception in + VHDL. + +* Similarly, the result of reading past the end of an array in Verilog is x, + whereas VHDL raises an exception. + +* Any signal that is driven by two or more processes will have the value + 'U'. This is the result of the signal resolution function in the + std_logic_1164 package. + +Constructs Not Supported +^^^^^^^^^^^^^^^^^^^^^^^^ + +The following Verilog constructs cannot be translated to VHDL: + +* fork and join + +* force and release + +* disable + +* real-valued variables + +* switches + +* hierarchical dereferencing + +Other Limitations +^^^^^^^^^^^^^^^^^ + +* The test expressions in case statements must be constant. + +* Translation of a parameter to a corresponding VHDL generic + declaration. Instead the default parameter value is used. + diff --git a/Documentation/usage/command_files.rst b/Documentation/usage/command_files.rst new file mode 100644 index 0000000000..c48cf12861 --- /dev/null +++ b/Documentation/usage/command_files.rst @@ -0,0 +1,198 @@ + +Command File Format +=================== + +The basic format of a command file is one source file or compiler argument per +line. Command files may also have comments of various form, and options for +controlling the compiler. + +Comments +-------- + +Lines that start with a "#" character are comments. All text after the "#" +character, is ignored. + +The "//" character sequence also starts a comment that continues to the end of +the line. + +The "/\*" and "\*/" character sequences surround multi-line comments. All the +text between the comment start and comment end sequences is ignored, even when +that text spans multiple lines. This style of comment does not nest, so a "/\*" +sequence within a multi-line comment is probably an error. + +Plus-args +--------- + +Outside of comments, lines that start with a "+" character are compiler +arguments. These are called plusargs but they are not the same as extended +arguments passed to the "vvp" command. The supported plusargs are definitively +listed in the iverilog manual page. + +The plusargs lines are generally "++..." where the name is the name of +an switch, and the arguments are separated by "+" characters, as in:: + + +libext+.v+.V+.ver + +With plusargs lines, the "+" character separates tokens, and not white space, +so arguments, which may include file paths, may include spaces. A plusarg line +is terminated by the line end. + +The line in the command file may also be a "-y" argument. This works exactly +the same as the:: + + -y + +argument to the compiler; it declares a library directory. The "-y" syntax is +also a shorthand for the "+libdir" plusarg, which is a more general form:: + + +libdir+... + +File Names +---------- + +Any lines that are not comments, compiler arguments or plusargs are taken by +the compiler to be a source file. The path can contain any characters (other +then comment sequences) including blanks, although leading and trailing white +space characters are stripped. The restriction of one file name per line is in +support of operating systems that can name files any which way. It is not +appropriate to expect white spaces to separate file names. + +Variable Substitution +--------------------- + +The syntax "$(name)" is a variable reference, and may be used anywhere within +filenames or directory names. The contents of the variable are read from the +environment and substituted in place of the variable reference. In Windows, +these environment variables are the very same variables that are set through +the Control Panel->System dialog box, and in UNIX these variables are +environment variables as exported by your shell. + +Variables are useful for giving command files some installation +independence. For example, one can import a vendor library with the line:: + + -y $(VENDOR)/verilog/library + +in the command file, and the next programmer will be able to use this command +file without editing it to point to the location of VENDOR on his +machine. Note the use of forward slashes as a directory separator. This works +even under Windows, so always use forward slashes in file paths and Windows +and UNIX users will be able to share command files. + +An Example +---------- + +This sample:: + + # This is a comment in a command file. + # The -y statement declares a library + # search directory + -y $(PROJ_LIBRARY)/prims + # + # This plusarg tells the compiler that + # files in libraries may have .v or .vl + # extensions. + +libext+.v+.vl + # + main.v // This is a source file + # + # This is a file name with blanks. + C:/Project Directory/file name.vl + +is a command file that demonstrates the major syntactic elements of command +files. It demonstrates the use of comments, variables, plusargs and file +names. It contains a lot of information about the hypothetical project, and +suggests that command files can be used to describe the project as a whole +fairly concisely. + +The syntax of command files is rich enough that they can be used to document +and control the assembly and compilation of large Verilog programs. It is not +unusual to have command files that are hundreds of lines long, although +judicious use of libraries can lead to very short command files even for large +designs. It is also practical to have different command files that pull +together combinations of sources and compiler arguments to make different +designs from the same Verilog source files. + +Summary +------- + +Given the above description of the command file format, the following is a +list of the special records with their meaning. + +* +libdir+*dir-path* + + Specify directories to be searched for library modules. The *dir-path* can + have multiple directories, separated by "+" characters. + +* +libdir-nocase+dir-path + + This is the same as "+libdir+", but when searching "nocase" libraries for + module files, case will not be taken as significant. This is useful when the + library is on a case insensitive file system. + +* +libext+*suffix-string* + + Declare the suffix strings to use when searching library directories for + Verilog files. The compiler may test a list of suffix strings to support a + variety of naming conventions. + +* -y dir-path + + This is like "+libdir+" but each line takes only one path. Like "+libdir+" + there can be multiple "-y" records to declare multiple library + directories. This is similar to the "-y" flag on the iverilog command line. + +* -v *file-name* or -l *file-name* + + This declares a library file. A library file is just like any other Verilog + source file, except that modules declared within it are not implicitly + possible root modules. + + NOTE: The "-l" alias is new as of 2 October 2016. It will become available + in releases and snapshots made after that date. + +* +incdir+*include-dir-path* + + Declare a directory or list of directories to search for files included by + the "include" compiler directive. The directories are searched in + order. This is similar to the "-I" flag on the iverilog command line. + +* +define+*name=value* + + Define the preprocessor symbol "name" to have the string value "value". If + the value (and the "=") are omitted, then it is assumed to be the string + "1". This is similar to the "-D" on the iverilog command line. + +* +timescale+*units/precision* + + Define the default timescale. This is the timescale that is used if there is + no other timescale directive in the Verilog source. The compiler default + default is "+timescale+1s/1s", which this command file setting can + change. The format of the units/precision is the same as that for the + timescale directive in the verilog source. + +* +toupper-filename + + This token causes file names after this in the command file to be translated + to uppercase. this helps with situations where a directory has passed + through a DOS machine (or a FAT file system) and in the process the file + names become munged. This is not meant to be used in general, but only in + emergencies. + +* +tolower-filename + + The is the lowercase version of "+toupper-filename". + +* +parameter+*name=value* + + This token causes the compiler to override a parameter value for a top-level + module. For example, if the module main has the parameter WIDTH, set the + width like this "+parameter+main.WIDTH=5". Note the use of the complete + hierarchical name. This currently only works for parameters defined in root + (top level) modules and a defparam may override the command file value. + +* +vhdl-work+*path* + + When compiling VHDL, this token allows control over the directory to use for + holding working package declarations. For example, "+vhdl-work+workdir" will + cause the directory "workdir" to be used as a directory for holding working + working copies of package headers. diff --git a/Documentation/usage/index.rst b/Documentation/usage/index.rst index e4292bc73c..cd6eabc55d 100644 --- a/Documentation/usage/index.rst +++ b/Documentation/usage/index.rst @@ -8,7 +8,12 @@ Icarus Verilog. .. toctree:: :maxdepth: 1 + installation getting_started + simulation command_line_flags + command_files verilog_attributes vvp_flags + vpi + ivl_target diff --git a/Documentation/usage/installation.rst b/Documentation/usage/installation.rst new file mode 100644 index 0000000000..859c87321f --- /dev/null +++ b/Documentation/usage/installation.rst @@ -0,0 +1,146 @@ + +Installation Guide +================== + +Icarus Verilog may be installed from source code, or from pre-packaged binary +distributions. If you don't have need for the very latest, and prepackaged +binaries are available, that would be the best place to start. + +Installation From Source +------------------------ + +Icarus is developed for Unix-like environments but can also be compiled on +Windows systems using the Cygwin environment or MinGW compilers. The following +instructions are the common steps for obtaining the Icarus Verilog source, +compiling and installing. Note that there are precompiled and/or prepackaged +versions for a variety of systems, so if you find an appropriate packaged +version, then that is the easiest way to install. + +The source code for Icarus is stored under the git source code control +system. You can use git to get the latest development head or the latest of a +specific branch. Stable releases are placed on branches, and in particular v11 +stable releases are on the branch "v11-branch" To get the development version +of the code follow these steps:: + + % git config --global user.name "Your Name Goes Here" + % git config --global user.email you@yourpublicemail.example.com + % git clone https://github.com/steveicarus/iverilog.git + +The first two lines are optional and are used to tell git who you are. This +information is important if/when you submit a patch. We suggest that you add +this information now so you don't forget to do it later. The clone will create +a directory, named iverilog, containing the source tree, and will populate +that directory with the most current source from the HEAD of the repository. + +Change into this directory using:: + + % cd iverilog + +Normally, this is enough as you are now pointing at the most current +development code, and you have implicitly created a branch "master" that +tracks the development head. However, If you want to actually be working on +the v11-branch (the branch where the latest v11 patches are) then you checkout +that branch with the command:: + + % git checkout --track -b v11-branch origin/v11-branch + +This creates a local branch that tracks the v11-branch in the repository, and +switches you over to your new v11-branch. The tracking is important as it +causes pulls from the repository to re-merge your local branch with the remote +v11-branch. You always work on a local branch, then merge only when you +push/pull from the remote repository. + +Now that you've cloned the repository and optionally selected the branch you +want to work on, your local source tree may later be synced up with the +development source by using the git command:: + + % git pull + +The git system remembers the repository that it was cloned from, so you don't +need to re-enter it when you pull. + +Finally, configuration files are built by the extra step:: + + % sh autoconf.sh + +The source is then compiled as appropriate for your system. See the specific +build instructions below for your operation system for what to do next. + +You will need autoconf and gperf installed in order for the script to work. +If you get errors such as:: + + Autoconf in root... + autoconf.sh: 10: autoconf: not found + Precompiling lexor_keyword.gperf + autoconf.sh: 13: gperf: not found. + +You will need to install download and install the autoconf and gperf tools. + +Icarus Specific Configuration Options +------------------------------------- + +Icarus takes many of the standard configuration options and those will not be +described here. The following are specific to Icarus:: + + --enable-suffix[=suffix] + +This option allows the user to build Icarus with a default suffix or when +provided a user defined suffix. Older stable releases have this flag on by +default e.g.(V0.8 by default will build with a "-0.8" suffix). All versions +have an appropriate default suffix ("-"). + +All programs or directories are tagged with this suffix. e.g.(iverilog-0.8, +vvp-0.8, etc.). The output of iverilog will reference the correct run time +files and directories. The run time will check that it is running a file with +a compatible version e.g.(you can not run a V0.9 file with the V0.8 run +time). :: + + --with-valgrind + +This option adds extra memory cleanup code and pool management code to allow +better memory leak checking when valgrind is available. This option is not +need when checking for basic errors with valgrind. + +Compiling on Linux/Unix +----------------------- + +(Note: You will need to install bison, flex, g++ and gcc) This is probably the +easiest case. Given that you have the source tree from the above instructions, +the compile and install is generally as simple as:: + + % ./configure + % make + (su to root) + # make install + +The "make install" typically needs to be done as root so that it can install +in directories such as "/usr/local/bin" etc. You can change where you want to +install by passing a prefix to the "configure" command:: + + % ./configure --prefix=/my/special/directory + +This will configure the source for eventual installation in the directory that +you specify. Note that "rpm" packages of binaries for Linux are typically +configured with "--prefix=/usr" per the Linux File System Standard. + +Make sure you have the latest version of flex otherwise you will get an error +when parsing lexor.lex. + +Compiling on Macintosh OS X +--------------------------- + +Since Mac OS X is a BSD flavor of Unix, you can install Icarus Verilog from +source using the procedure described above. You need to install the Xcode +software, which includes the C and C++ compilers for Mac OS X. The package is +available for free download from Apple's developer site. Once Xcode is +installed, you can build Icarus Verilog in a terminal window just like any +other Unix install. + +For versions newer than 10.3 the GNU Bison tool (packaged with Xcode) needs to +be updated to version 3. :: + + brew install bison + echo 'export PATH="/usr/local/opt/bison/bin:$PATH"' >> ~/.bash_profile + +Icarus Verilog is also available through the Homebrew package manager: "brew +install icarus-verilog". diff --git a/Documentation/usage/ivl_target.rst b/Documentation/usage/ivl_target.rst new file mode 100644 index 0000000000..192e00e9b9 --- /dev/null +++ b/Documentation/usage/ivl_target.rst @@ -0,0 +1,106 @@ + +Loadable Target API (ivl_target.h) +================================== + +In addition to the standard VPI API, Icarus Verilog supports a non-standard +loadable target module API. This API helps C programmers write modules that +Icarus Verilog can use to generate code. These modules are used at compile +time to write the elaborated design to the simulation or netlist files. For +example, the vvp code generator is a loadable target module that writes vvp +code into the specified file. + +Loadable target modules gain access to the 'elaborated' design. That means, +the source files have been checked for syntax and correctness, any synthesis +and general optimization steps have been performed, and what is left is a +design that reflects but is not exactly the same as the input Verilog source +code. This relieves the modules of the burden of supporting all the odd +corners and complexities of the Verilog language. + +The Target Module API +--------------------- + +The API is defined in the header file "ivl_target.h" which is installed with +Icarus Verilog. The header defines the functions that the module writer can +use to get at the elaborated design during the course of writing the output +format. + +The target module API function "target_design" is special in that the API does +not provide this function: The target module itself provides it. When the +compiler loads the target module, it invokes the "target_design" function with +a handle to the design. This is the point where the target module takes over +to process the design. + +Compiling Target Modules +------------------------ + +Compiling loadable target modules is similar to compiling VPI modules, in that +the module must be compiled with the "-fPIC" flag to gcc, and linked with the +"-shared" flag. The module that you compile is then installed in a place where +the "iverilog" command can find it, and configuration files are adjusted to +account for the new module. + +This code:: + + # include + + int target_design(ivl_design_t des) + { + return 0; + } + +is an example module that we can write into the file "empty.c"; and let us +compile it into the module file "empty.tgt" like so:: + + % gcc -o empty.tgt -fpic -shared empty.c + +This makes the "empty.tgt" file an a dynamically loaded shared object. + +Creating the Target Config File +------------------------------- + +The target config file tells the Icarus Verilog core how to process your new +code generator. The ivl core expects two configuration files: the name.conf +and the name-s.config files. The "-s" version is what is used if the user +gives the "-S" (synthesis) flag on the command line. + +The stub target, included in most distributions, demonstrates the config +files. The "stub.conf" file is:: + + functor:cprop + functor:nodangle + -t:dll + flag:DLL=stub.tgt + +and the "stub-s.conf" file is:: + + functor:synth2 + functor:synth + functor:syn-rules + functor:cprop + functor:nodangle + -t:dll + flag:DLL=stub.tgt + +Note that the "stub-s.conf" file contains more lines to invoke internal +synthesis functions, whereas the "stub.conf" invokes only the basic +optimization steps. + +In general, only the last line (The "flag:DLL=.tgt" record) varies for +each target. For your target, replace the with the name of your target +and you have a configuration file ready to install. Note that this is the name +of your target module. This is in fact how the config file tells the compiler +the name of your module. + +The rest of the config file is best taken as boiler plate and installed as is, +with one difference. If your target is a synthesis target (for example a mosis +code generator or a pld code generator) that expects synthesis to happen, then +it makes the most sense to create both your config file like the "stub-s.conf" +config file. This causes the compiler to do synthesis for your target whether +the user gives the "-S" flag or not. + +Installing the Target Module +---------------------------- + +Finally, the "empty.conf", the "empty-s.conf" and the "empty.tgt" files need +to be installed. Where they go depends on your system, but in Linux they are +normally installed in "/usr/lib/ivl". diff --git a/Documentation/usage/simulation.rst b/Documentation/usage/simulation.rst new file mode 100644 index 0000000000..35685f1e30 --- /dev/null +++ b/Documentation/usage/simulation.rst @@ -0,0 +1,487 @@ + +Simulation Using Icarus Verilog +=============================== + +Simulation is the process of creating models that mimic the behavior of the +device you are designing (simulation models) and creating models to exercise +the device (test benches). The simulation model need not reflect any +understanding of the underlying technology, and the simulator need not know +that the design is intended for any specific technology. + +The Verilog simulator, in fact, is usually a different program than the +synthesizer. It may even come from a different vendor. The simulator need not +know of or generate netlists for the target technology, so it is possible to +write one simulator that can be used to model designs intended for a wide +variety of technologies. A synthesizer, on the other hand, does need to know a +great deal about the target technology in order to generate efficient +netlists. Synthesizers are often technology specific and come from vendors +with specialized knowledge, whereas simulators are more general purpose. + +Simulation models and test benches, therefore, can use the full range of +Verilog features to model the intended design as clearly as possible. This is +the time to test the algorithms of the design using language that is +relatively easy for humans to read. The simulator, along with the test bench, +can test that the clearly written model really does behave as intended, and +that the intended behavior really does meet expectations. + +The test benches model the world outside the design, so they are rarely +destined for real hardware. They are written in Verilog simply as a matter of +convenience, and sometimes they are not written in Verilog at all. The test +benches are not throw-away code either, as they are used to retest the device +under test as it is transformed from a simulation model to a synthesizeable +description. + +Compilation and Elaboration +--------------------------- + +Simulation of a design amounts to compiling and executing a program. The +Verilog source that represents the simulation model and the test bench is +compiled into an executable form and executed by a simulation +engine. Internally, Icarus Verilog divides the compilation of program source +to an executable form into several steps, and basic understanding of these +steps helps understand the nature of failures and errors. The first step is +macro preprocessing, then compilation, elaboration, optional optimizations and +finally code generation. The boundary between these steps is often blurred, +but this progression remains a useful model of the compilation process. + +The macro preprocessing step performs textual substitutions of macros defined +with "\`define" statements, textual inclusion with "\`include" statements, and +conditional compilation by "\`ifdef" and "\`ifndef" statements. The +macropreprocessor for Icarus Verilog is internally a separate program that can +be accessed independently by using the "-E" flag to the "iverilog" command, +like so:: + + % iverilog -E -o out.v example.v + +This command causes the input Verilog file "example.v" to be preprocessed, and +the output, a Verilog file without preprocessor statements, written into +"out.v". The "\`include" and "\`ifdef" directives in the input file are interpreted, +and defined macros substituted, so that the output, a single file, is the same +Verilog but with the preprocessor directives gone. All the explicitly +specified source files are also combined by the preprocessor, so that the +preprocessed result is a single Verilog stream. + +Normally, however, the "-E" flag is not used and the preprocessed Verilog is +instead sent directly to the next step, the compiler. The compiler core takes +as input preprocessed Verilog and generates an internal parsed form. The +parsed form is an internal representation of the Verilog source, in a format +convenient for further processing, and is not accessible to the user. + +The next step, elaboration, takes the parsed form, chooses the root modules, +and instantiates (makes *instances* of) those roots. The root instances may +contain instances of other modules, which may in turn contain instances of yet +other modules. The elaboration process creates a hierarchy of module instances +that ends with primitive gates and statements. + +Note that there is a difference between a module and a module instance. A +module is a type. It is a description of the contents of module instances that +have its type. When a module is instantiated within another module, the module +name identifies the type of the instance, and the instance name identifies the +specific instance of the module. There can be many instances of any given +module. + +Root modules are a special case, in that the programmer does not give them +instance names. Instead, the instance names of root modules are the same as +the name of the module. This is valid because, due to the nature of the +Verilog syntax, a module can be a root module only once, so the module name +itself is a safe instance name. + +Elaboration creates a hierarchy of scopes. Each module instance creates a new +scope within its parent module, with each root module starting a +hierarchy. Every module instance in the elaborated program has a unique scope +path, a hierarchical name, that starts with its root scope and ends with its +own instance name. Every named object, including variables, parameters, nets +and gates, also has a hierarchical name that starts with a root scope and ends +with its own base name. The compiler uses hierarchical names in error messages +generated during or after elaboration, so that erroneous items can be +completely identified. These hierarchical names are also used by waveform +viewers that display waveform output from simulations. + +The elaboration process creates from the parsed form the scope hierarchy +including the primitive objects within each scope. The elaborated design then +is optimized to reduce it to a more optimal, but equivalent design. The +optimization step takes the fully elaborated design and transforms it to an +equivalent design that is smaller or more efficient. These optimizations are, +for example, forms of constant propagation and dead code elimination. Useless +logic is eliminated, and constant expressions are pre-calculated. The +resulting design behaves as if the optimizations were not performed, but is +smaller and more efficient. The elimination (and spontaneous creation) of +gates and statements only affects the programmer when writing VPI modules, +which through the API have limited access to the structures of the design. + +Finally, the optimized design, which is still in an internal form not +accessible to users, is passed to a code generator that writes the design into +an executable form. For simulation, the code generator is selected to generate +the vvp format--a text format that can be executed by the simulation +engine. Other code generators may be selected by the Icarus Verilog user, even +third party code generators, but the vvp code generator is the default for +simulation purposes. + +Making and Using Libraries +-------------------------- + +Although simple programs may be written into a single source file, this gets +inconvenient as the designs get larger. Also, writing the entire program into +a single file makes it difficult for different programs to share common +code. It therefore makes sense to divide large programs into several source +files, and to put generally useful source code files somewhere accessible to +multiple designs. + +Once the program is divided into many files, the compiler needs to be told how +to find the files of the program. The simplest way to do that is to list the +source files on the command line or in a command file. This is for example the +best way to divide up and integrate test bench code with the simulation model +of the device under test. + +The Macro Preprocessor +^^^^^^^^^^^^^^^^^^^^^^ + +Another technique is to use the macro preprocessor to include library files +into a main file. The `include` directive takes the name of a source file to +include. The preprocessor inserts the entire contents of the included file in +place of the `include` directive. The preprocessor normally looks in the +current working directory (the current working directory of the running +compiler, and not the directory where the source file is located) for the +included file, but the "-I" switch to "iverilog" can add directories to the +search locations list. :: + + % iverilog -I/directory/to/search example.v + +It is common to create include directories shared by a set of programs. The +preprocessor `include` directive can be used by the individual programs to +include the source files that it needs. + +The preprocessor method of placing source code into libraries is general +(arbitrary source code can be placed in the included files) but is static, in +the sense that the programmer must explicitly include the desired library +files. The automatic module library is a bit more constrained, but is +automatic. + +Automatic Module Libraries +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A common use for libraries is to store module definitions that may be of use +to a variety of programs. If modules are divided into a single module per +file, and the files are named appropriately, and the compiler is told where to +look, then the compiler can automatically locate library files when it finds +that a module definition is missing. + +For this to work properly, the library files must be Verilog source, they +should contain a single module definition, and the files must be named after +the module they contain. For example, if the module "AND2" is a module in the +library, then it belongs in a file called "AND2.v" and that file contains only +the "AND2" module. A library, then, is a directory that contains properly +named and formatted source files. :: + + % iverilog -y/library/to/search example.v + +The "-y" flag to "iverilog" tells the compiler to look in the specified +directory for library modules whenever the program instantiates a module that +is not otherwise defined. The programmer may include several "-y" flags on the +command line (or in a command file) and the compiler will search each +directory in order until an appropriate library file is found to resolve the +module. + +Once a module is defined, either in the program or by reading a library +module, the loaded definition is used from then on within the program. If the +module is defined within a program file or within an included file, then the +included definition is used instead of any library definition. If a module is +defined in multiple libraries, then the first definition that the compiler +finds is used, and later definitions are never read. + +Icarus Verilog accesses automatic libraries during elaboration, after it has +already preprocessed and parsed the non-library source files. Modules in +libraries are not candidates for root modules, and are not even parsed unless +they are instantiated in other source files. However, a library module may +reference other library modules, and reading in a library module causes it to +be parsed and elaborated, and further library references resolved, just like a +non-library module. The library lookup and resolution process iterates until +all referenced modules are resolved, or known to be missing from the +libraries. + +The automatic module library technique is useful for including vendor or +technology libraries into a program. Many EDA vendors offer module libraries +that are formatted appropriately; and with this technique, Icarus Verilog can +use them for simulation. + +Advanced Command Files +---------------------- + +Command files were mentioned in the "Getting Started" chapter, but only +briefly. In practice, Verilog programs quickly grow far beyond the usefulness +of simple command line options, and even the macro preprocessor lacks the +flexibility to combine source and library modules according to the advancing +development process. + +The main contents of a command file is a list of Verilog source files. You can +name in a command file all the source files that make up your design. This is +a convenient way to collect together all the files that make up your +design. Compiling the design can then be reduced to a simple command line like +the following:: + + % iverilog -c example.cf + +The command file describes a configuration. That is, it lists the specific +files that make up your design. It is reasonable, during the course of +development, to have a set of different but similar variations of your +design. These variations may have different source files but also many common +source files. A command file can be written for each variation, and each +command file lists the source file names used by each variation. + +A configuration may also specify the use of libraries. For example, different +configurations may be implementations for different technologies so may use +different parts libraries. To make this work, command files may include "-y" +statements. These work in command files exactly how they work on "iverilog" +command line. Each "-y" flag is followed by a directory name, and the +directories are searched for library modules in the order that they are listed +in the command file. + +The include search path can also be specified in configuration files with +"+incdir+" tokens. These tokens start with the "+incdir+" string, then +continue with directory paths, separated from each other with "+" characters +(not spaces) for the length of the line. + +Other information can be included in the command file. See the section Command +File Format for complete details on what can go in a command file. + +Input Data at Runtime +--------------------- + +Often, it is useful to compile a program into an executable simulation, then +run the simulation with various inputs. This requires some means to pass data +and arguments to the compiled program each time it is executed. For example, +if the design models a micro-controller, one would like to run the compiled +simulation against a variety of different ROM images. + +There are a variety of ways for a Verilog program to get data from the outside +world into the program at run time. Arguments can be entered on the command +line, and larger amounts of data can be read from files. The simplest method +is to take arguments from the command line. + +Consider this running example of a square root calculator:: + + module sqrt32(clk, rdy, reset, x, .y(acc)); + input clk; + output rdy; + input reset; + + input [31:0] x; + output [15:0] acc; + + // acc holds the accumulated result, and acc2 is + // the accumulated square of the accumulated result. + reg [15:0] acc; + reg [31:0] acc2; + + // Keep track of which bit I'm working on. + reg [4:0] bitl; + wire [15:0] bit = 1 << bitl; + wire [31:0] bit2 = 1 << (bitl << 1); + + // The output is ready when the bitl counter underflows. + wire rdy = bitl[4]; + + // guess holds the potential next values for acc, + // and guess2 holds the square of that guess. + wire [15:0] guess = acc | bit; + wire [31:0] guess2 = acc2 + bit2 + ((acc << bitl) << 1); + + task clear; + begin + acc = 0; + acc2 = 0; + bitl = 15; + end + endtask + + initial clear; + + always @(reset or posedge clk) + if (reset) + clear; + else begin + if (guess2 <= x) begin + acc <= guess; + acc2 <= guess2; + end + bitl <= bitl - 1; + end + + endmodule + +One could write the test bench as a program that passes a representative set +of input values into the device and checks the output result. However, we can +also write a program that takes on the command line an integer value to be +used as input to the device. We can write and compile this program, then pass +different input values on the run time command line without recompiling the +simulation. + +This example demonstrates the use of the "$value$plusargs" to access command +line arguments of a simulation:: + + module main; + + reg clk, reset; + reg [31:0] x; + wire [15:0] y; + wire rdy; + + sqrt32 dut (clk, rdy, reset, x, y); + + always #10 clk = ~clk; + + initial begin + clk = 0; + reset = 1; + + if (! $value$plusargs("x=%d", x)) begin + $display("ERROR: please specify +x= to start."); + $finish; + end + + #35 reset = 0; + + wait (rdy) $display("y=%d", y); + $finish; + end // initial begin + + endmodule // main + +The "$value$plusargs" system function takes a string pattern that describes +the format of the command line argument, and a reference to a variable that +receives the value. The "sqrt_plusargs" program can be compiled and executed +like this:: + + % iverilog -osqrt_plusargs.vvp sqrt_plusargs.v sqrt.v + % vvp sqrt_plusargs.vvp +x=81 + y= 9 + +Notice that the "x=%d" string of the "$value$plusargs" function describes the +format of the argument. The "%d" matches a decimal value, which in the sample +run is "81". This gets assigned to "x" by the "$value$plusargs" function, +which returns TRUE, and the simulation continues from there. + +If two arguments have to be passed to the testbench then the main module would +be modified as follows:: + + module main; + + reg clk, reset; + reg [31:0] x; + reg [31:0] z; + wire [15:0] y1,y2; + wire rdy1,rdy2; + + sqrt32 dut1 (clk, rdy1, reset, x, y1); + sqrt32 dut2 (clk, rdy2, reset, z, y2); + + always #10 clk = ~clk; + + initial begin + clk = 0; + reset = 1; + + if (! $value$plusargs("x=%d", x)) begin + $display("ERROR: please specify +x= to start."); + $finish; + end + + if (! $value$plusargs("z=%d", z)) begin + $display("ERROR: please specify +z= to start."); + $finish; + end + + + #35 reset = 0; + + wait (rdy1) $display("y1=%d", y1); + wait (rdy2) $display("y2=%d", y2); + $finish; + end // initial begin + + endmodule // main + +and the "sqrt_plusargs" program would be compiled and executed as follows:: + + % iverilog -osqrt_plusargs.vvp sqrt_plusargs.v sqrt.v + % vvp sqrt_plusargs.vvp +x=81 +z=64 + y1= 9 + y2= 8 + +In general, the "vvp" command that executes the compiled simulation takes a +few predefined argument flags, then the file name of the simulation. All the +arguments after the simulation file name are extended arguments to "vvp" and +are passed to the executed design. Extended arguments that start with a "+" +character are accessible through the "$test$plusargs" and "$value$plusargs" +system functions. Extended arguments that do not start with a "+" character +are only accessible to system tasks and functions written in C using the VPI. + +In the previous example, the program pulls the argument from the command line, +assigns it to the variable "x", and runs the sqrt device under test with that +value. This program can take the integer square root of any single value. Of +course, if you wish to test with a large number of input values, executing the +program many times may become tedious. + +Another technique would be to put a set of input values into a data file, and +write the test bench to read the file. We can then edit the file to add new +input values, then rerun the simulation without compiling it again. The +advantage of this technique is that we can accumulate a large set of test +input values, and run the lot as a batch. + +This example:: + + module main; + + reg clk, reset; + reg [31:0] data[4:0]; + reg [31:0] x; + wire [15:0] y; + wire rdy; + + sqrt32 dut (clk, rdy, reset, x, y); + + always #10 clk = ~clk; + + integer i; + initial begin + /* Load the data set from the hex file. */ + $readmemh("sqrt.hex", data); + for (i = 0 ; i <= 4 ; i = i + 1) begin + clk = 0; + reset = 1; + + x = data[i]; + + #35 reset = 0; + + wait (rdy) $display("y=%d", y); + end + $finish; + end // initial begin + + endmodule // main + +demonstrates the use of "$readmemh" to read data samples from a file into a +Verilog array. Start by putting into the file "sqrt.hex" the numbers:: + + 51 + 19 + 1a + 18 + 1 + +Then run the simulation with the command sequence:: + + % iverilog -osqrt_readmem.vvp sqrt_readmem.vl sqrt.vl + % vvp sqrt_readmem.vvp + y= 9 + y= 5 + y= 5 + y= 4 + y= 1 + +It is easy enough to change this program to work with larger data sets, or to +change the "data.hex" file to contain different data. This technique is also +common for simulating algorithms that take in larger data sets. One can extend +this idea slightly by using a "$value$plusargs" statement to select the file +to read. diff --git a/Documentation/usage/vpi.rst b/Documentation/usage/vpi.rst new file mode 100644 index 0000000000..24cd6f8b69 --- /dev/null +++ b/Documentation/usage/vpi.rst @@ -0,0 +1,246 @@ + +Using VPI +========= + +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. + +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. + +How It Works +------------ + +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:: + + % vvp -msample foo.vvp + +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. + +(There is a special module, the system.vpi module, that is always loaded to +provide the core system tasks.) + +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:: + + void (*vlog_startup_routines[])() = { + hello_register, + 0 + }; + +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. + +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. + +Compiling VPI Modules +--------------------- + +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:: + + % gcc -c -fpic hello.c + % gcc -shared -o hello.vpi hello.o -lvpi + +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:: + + % iverilog-vpi hello.c + +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. + +A Worked Example +---------------- + +Let us try a complete, working example. Place the C code that follows into the +file hello.c:: + + # include + + static int hello_compiletf(char*user_data) + { + return 0; + } + + static int hello_calltf(char*user_data) + { + vpi_printf("Hello, World!\n"); + return 0; + } + + void hello_register() + { + 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[])() = { + hello_register, + 0 + }; + +and place the Verilog code that follows into hello.v:: + + module main; + initial $hello; + endmodule + +Next, compile and execute the code with these steps:: + + % iverilog-vpi hello.c + % iverilog -ohello.vvp hello.v + % vvp -M. -mhello hello.vvp + Hello, World! + +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. + +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. + +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. + +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. + +System Function Return Types +---------------------------- + +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. + +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. + +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:: + + # Example sft declarations of some common functions + $random vpiSysFuncInt + $bitstoreal vpiSysFuncReal + $realtobits vpiSysFuncSized 64 unsigned + +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: + +* vpiSysFuncInt +* vpiSysFuncReal +* vpiSysFuncSized + +Any functions that do not have an explicit type declaration in an SFT file are +implicitly taken to be "vpiSysFuncSized 32 unsigned". + +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. + +Cadence PLI Modules +------------------- + +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. + +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":: + + % vvp -mcadpli a.out -cadpli=./product.so:my_boot + +The "-mcadpli" argument causes vvp to load the cadpli.vpl library module. This +activates the -cadpli= argument interpreter. The -cadpli=: +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. + +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. + +Other References +---------------- + +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. + +* Principles of Verilog PLI by Swapnajit Mittra. ISBN 0-7923-8477-6 +* The Verilog PLI Handbook by Stuart Sutherland. ISBN 0-7923-8489-X