diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 0000000000..79f6fd14c8 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 0e3ab3ab22694cd097aa6155d93605f9 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/_images/GTKWave_Example2.png b/_images/GTKWave_Example2.png new file mode 100644 index 0000000000..2de993933e Binary files /dev/null and b/_images/GTKWave_Example2.png differ diff --git a/_sources/developer/getting_started.rst.txt b/_sources/developer/getting_started.rst.txt new file mode 100644 index 0000000000..b0a2316604 --- /dev/null +++ b/_sources/developer/getting_started.rst.txt @@ -0,0 +1,225 @@ + +Getting Started as a Contributer +================================ + +Icarus Verilog development is centered around the github repository at +`github.com/steveicarus/iverilog `_. +Contributing to Icarus Verilog requires a basic knowledge of git and github, +so see the github documentation for more information. The sections below will +step you through the basics of getting the source code from github, making a +branch, and submitting a pull request for review. + +Getting Icarus Verilog +---------------------- + +To start, you will need to clone the code. It is preferred that you use the +"ssh" method, and the ssh based clone with the command: + +.. code-block:: console + + % git clone git@github.com:steveicarus/iverilog.git + +This assumes that you have a github account (accounts are free) and you have +set up your ssh authentication keys. See the +`Authentication Guides here `_. + +The "git clone" command will get you all the source: + +.. code-block:: console + + % git clone git@github.com:steveicarus/iverilog.git + Cloning into 'iverilog'... + remote: Enumerating objects: 66234, done. + remote: Counting objects: 100% (6472/6472), done. + remote: Compressing objects: 100% (4123/4123), done. + remote: Total 66234 (delta 2412), reused 6039 (delta 2190), pack-reused 59762 + Receiving objects: 100% (66234/66234), 27.98 MiB | 2.53 MiB/s, done. + Resolving deltas: 100% (50234/50234), done. + % 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 a +specific version, say for example version 11, the v11-branch, you checkout +that branch with the command: + +.. code-block:: console + + % 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: + +.. code-block:: console + + % git pull + Already up to date. + +Finally, configuration files are built by the extra step: + +.. code-block:: console + + % sh autoconf.sh + Autoconf in root... + Precompiling lexor_keyword.gperf + Precompiling vhdlpp/lexor_keyword.gperf + +You will need autoconf and gperf installed in order for the script to work. +If you get errors such as: + +.. code-block:: console + + % sh autoconf.sh + 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. + +Now you are ready to configure and compile the source. + +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 Verilog: + +.. code-block:: none + + --enable-suffix[=suffix] + +This option allows the user to build Icarus with a default suffix or when +provided a user defined 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). + +A debug options is: + +.. code-block:: none + + --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 +------------------ + +(Note: You will need to install bison, flex, g++ and gcc) This is probably the +easiest step. Given that you have the source tree from the above instructions, +the compile and install is generally as simple as: + +.. code-block:: console + + % ./configure + configure: loading site script /usr/share/site/x86_64-unknown-linux-gnu + checking build system type... x86_64-unknown-linux-gnu + checking host system type... x86_64-unknown-linux-gnu + checking for gcc... gcc + checking whether the C compiler works... yes + checking for C compiler default output file name... a.out + checking for suffix of executables... + [...and so on...] + + % make + mkdir dep + Using git-describe for VERSION_TAG + g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c main.cc -o main.o + mv main.d dep/main.d + g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c async.cc -o async.o + mv async.d dep/async.d + g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c design_dump.cc -o design_dump.o + mv design_dump.d dep/design_dump.d + g++ -DHAVE_CONFIG_H -I. -Ilibmisc -Wall -Wextra -Wshadow -g -O2 -MD -c discipline.cc -o discipline.o + [...and so on...] + +The end result is a complete build of Icarus Verilog. You can install your +compiled version with a command like this: + +.. code-block:: console + + % sudo make install + +Regression Tests +---------------- + +Icarus Verilog comes with a fairly extensive regression test suite. As of +2022, that test suite is included with the source in the "ivtest" +directory. Contained in that directory are a couple driver scripts that run +all the regression tests on the installed version of Icarus Verilog. So for +example: + +.. code-block:: console + + % cd ivtest + % ./vvp_reg.pl --strict + +will run all the regression tests for the simulation engine. (This is what +most people will want to do.) You should rerun this test before submitting +patches to the developers. Also, if you are adding a new feature, you should +add test programs to the regression test suite to validate your new feature +(or bug fix.) + +Note that pull requests will be required to pass these regression tests before +being merged. + +Forks, Branches and Pull Requests +--------------------------------- + +Currently, the preferred way to submit patches to Icarus Verilog is via pull +requests. +`Pull requests `_ +can be created from the main repository if you have write access (very few +people have write access) or more commonly from a fork, so the first step is +to create a fork that you can work with. It is easy enough to create a fork, +just go to the +`github.com/steveicarus/iverilog `_ +page and use the "fork" button in the upper right corner. This will create +a new repository that you can clone instead of the steveicarus/iverilog +repository. You then use your local repository to create feature branches, +then submit them for inclusion in the main repository as pull +requests. Remember to `synchronize your fork +`_ +periodically with the main repository. This will make sure your work is based +on the latest upstream and avoid merge conflicts. + +Create your patch by first creating a branch that contains your commits: + +.. code-block:: console + + % git checkout -b my-github-id/branch-name + +We are encouraging using this scheme for naming your branches that are +destined for pull requests. Use your github id in the branch name. So for +example: + +.. code-block:: console + + % git checkout -b steveicarus/foo-feature + +Do your work in this branch, then when you are ready to create a pull request, +first push the branch up to github: + +.. code-block:: console + + % git push -u origin my-github-id/branch-name + +Then go to github.com to create your pull request. `Create your pull request +against the "master" branch of the upstream repository +`_, +or the version branch that you are working on. Your pull reuqest will be run +through continuous integration, and reviewed by one of the main +authors. Feedback may be offered to your PR, and once accepted, an approved +individual will merge it for you. Then you are done. + diff --git a/_sources/developer/glossary.rst.txt b/_sources/developer/glossary.rst.txt new file mode 100644 index 0000000000..4bbf648147 --- /dev/null +++ b/_sources/developer/glossary.rst.txt @@ -0,0 +1,48 @@ + +Glossary +======== + +Throughout Icarus Verilog descriptions and source code, I use a +variety of terms and acronyms that might be specific to Icarus +Verilog, have an Icarus Verilog specific meaning, or just aren't +widely known. So here I define these terms. + + +LRM - Language Reference Manual + This is a generic acronym, but in the Verilog world we sometimes + mean *the* language reference manual, the IEEE1364 standard. + + +PLI - Programming Language Interface + This is a C API into Verilog simulators that is defined by the + IEEE1364. There are two major interfaces, sometimes called PLI 1 + and PLI 2. PLI 2 is also often called VPI. + + +UDP - User Defined Primitive + These are objects that Verilog programmers define with the + "primitive" keyword. They are truth-table based devices. The + syntax for defining them is described in the LRM. + + +VPI - Verilog Procedural Interface + This is the C API that is defined by the Verilog standard, and + that Icarus Verilog partially implements. See also PLI. + + +VVM - Verilog Virtual Machine + This is the Icarus Verilog runtime that works with the code + generator that generates C++. + + +VVP - Verilog Virtual Processor + This is the Icarus Verilog runtime that reads in custom code in a + form that I call "VVP Assembly". + +LPM - Library of Parameterized Modules + LPM (Library of Parameterized Modules) is EIS-IS standard 103-A. It is + a standard library of abstract devices that are designed to be close + enough to the target hardware to be easily translated, yet abstract + enough to support a variety of target technologies without excessive + constraints. Icarus Verilog uses LPM internally to represent idealized + hardware, especially when doing target neutral synthesis. diff --git a/_sources/developer/guide/cadpli/cadpli.rst.txt b/_sources/developer/guide/cadpli/cadpli.rst.txt new file mode 100644 index 0000000000..c08b617a76 --- /dev/null +++ b/_sources/developer/guide/cadpli/cadpli.rst.txt @@ -0,0 +1,34 @@ + +Cadence PLI1 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. + +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. diff --git a/_sources/developer/guide/index.rst.txt b/_sources/developer/guide/index.rst.txt new file mode 100644 index 0000000000..bd2ad2d745 --- /dev/null +++ b/_sources/developer/guide/index.rst.txt @@ -0,0 +1,169 @@ + +Developer Guide +=============== + +The developer guide is intended to give you a gross structure of the +Icarus Verilog compiler source. This will help orient you to the +source code itself, so that you can find the global parts where you +can look for even better detail. + +The documentation for getting, building and installing Icarus Verilog +is kept and maintained at :doc:`Getting Started as a Contributer <../getting_started>` + +See the Installation Guide for getting the current source from the git +repository (and how to use the git repository) and see the Developer Guide +for instructions on participating in the Icarus Verilog development process. +That information will not be repeated here. + +Scroll down to a listing with further readings. + +Compiler Components +------------------- + +- The compiler driver (driver/) + +This is the binary that is installed as "iverilog". This program takes +the command line arguments and assembles invocations of all the other +subcommands to perform the steps of compilation. + +- The preprocessor (ivlpp/) + +This implements the Verilog pre-processor. In Icarus Verilog, the +compiler directives \`define, \`include, \`ifdef and etc. are implemented +in an external program. The ivlpp/ directory contains the source for +this program. + +- The core compiler (root directory) + +The "ivl" program is the core that does all the Verilog compiler +processing that is not handled elsewhere. This is the main core of the +Icarus Verilog compiler, not the runtime. See below for more details +on the core itself. + +- The loadable code generators (tgt-\*/) + +This core compiler, after it is finished with parsing and semantic +analysis, uses loadable code generators to emit code for supported +targets. The tgt-\*/ directories contains the source for the target +code generators that are bundled with Icarus Verilog. The tgt-vvp/ +directory in particular contains the code generator for the vvp +runtime. + + +Runtime Components +------------------ + +- The vvp runtime (vvp/) + +This program implements the runtime environment for Icarus +Verilog. It implements the "vvp" command described in the user +documentation. See the vvp/ subdirectory for further developer +documentation. + +- The system tasks implementations (vpi/) + +The standard Verilog system tasks are implemented using VPI (PLI-2) +and the source is in this subdirectory. + +- The PLI-1 compatibility library (libveriuser/) + +The Icarus Verilog support for the deprecated PLI-1 is in this +subdirectory. The vvp runtime does not directly support the +PLI-1. Instead, the libveriuser library emulates it using the builtin +PLI-2 support. + +- The Cadence PLI module compatibility module (cadpli/) + +It is possible in some specialized situations to load and execute +PLI-1 code written for Verilog-XL. This directory contains the source +for the module that provides the Cadence PLI interface. + + +The Core Compiler +----------------- + +The "ivl" binary is the core compiler that does the heavy lifting of +compiling the Verilog source (including libraries) and generating the +output. This is the most complex component of the Icarus Verilog +compilation system. + +The process in the abstract starts with the Verilog lexical analysis +and parsing to generate an internal "pform". The pform is then +translated by elaboration into the "netlist" form. The netlist is +processed by some functors (which include some optimizations and +optional synthesis) then is translated into the ivl_target internal +form. And finally, the ivl_target form is passed via the ivl_target.h +API to the code generators. + +- Lexical Analysis + +Lexical analysis and parsing use the tools "flex", "gperf", and +"bison". The "flex" input file "lexor.lex" recognizes the tokens in +the input stream. This is called "lexical analysis". The lexical +analyzer also does some processing of compiler directives that are not +otherwise taken care of by the external preprocessor. The lexical +analyzer uses a table of keywords that is generated using the "gperf" +program and the input file "lexor_keywords.gperf". This table allows +the lexical analyzer to efficiently check input words with the rather +large set of potential keywords. + +- Parsing + +The parser input file "parse.y" is passed to the "bison" program to +generate the parser. The parser uses the functions in parse*.h, +parse*.cc, pform.h, and pform*.cc to generate the pform from the +stream of input tokens. The pform is what compiler writers call a +"decorated parse tree". + +The pform itself is described by the classes in the header files +"PScope.h", "Module.h", "PGenerate.h", "Statement.h", and +"PExpr.h". The implementations of the classes in those header files +are in the similarly named C++ files. + +- Elaboration + +Elaboration transforms the pform to the netlist form. Elaboration is +conceptually divided into several major steps: Scope elaboration, +parameter overrides and defparam propagation, signal elaboration, and +statement and expression elaboration. + +The elaboration of scopes and parameter overrides and defparam +propagation are conceptually separate, but are in practice +intermingled. The elaboration of scopes scans the pform to find and +instantiate all the scopes of the design. New scopes are created by +instantiation of modules (starting with the root instances) by user +defined tasks and functions, named blocks, and generate schemes. The +elaborate_scope methods implement scope elaboration, and the +elab_scope.cc source file has the implementations of those +methods. + +The elaborate.cc source file contains the initial calls to the +elaborate_scope for the root scopes to get the process started. In +particular, see the "elaborate" function near the bottom of the +elaborate.cc source file. The calls to Design::make_root_scope create +the initial root scopes, and the creation and enqueue of the +elaborate_root_scope_t work items primes the scope elaboration work +list. + +Intermingled in the work list are defparms work items that call the +Design::run_defparams and Design::evaluate_parameters methods that +override and evaluate parameters. The override and evaluation of +parameters must be intermingled with the elaboration of scopes because +the exact values of parameters may impact the scopes created (imagine +generate schemes and instance arrays) and the created scopes in turn +create new parameters that need override and evaluation. + +Further Reading +--------------- + +For further information on the individual parts of Icarus Verilog, see this listing: + +.. toctree:: + :maxdepth: 2 + + ivl/index + vvp/index + tgt-vvp/tgt-vvp + vpi/index + cadpli/cadpli + misc/index diff --git a/_sources/developer/guide/ivl/attributes.rst.txt b/_sources/developer/guide/ivl/attributes.rst.txt new file mode 100644 index 0000000000..48fb143e76 --- /dev/null +++ b/_sources/developer/guide/ivl/attributes.rst.txt @@ -0,0 +1,91 @@ + +Icarus Verilog Attributes +========================= + +Attribute Naming Conventions +---------------------------- + +Attributes that are specific to Icarus Verilog, and are intended to be +of use to programmers, start with the prefix "ivl\_". + +Attributes with the "_ivl_" prefix are set aside for internal +use. They may be generated internally by the compiler. They need not +be documented here. + +Attributes To Control Synthesis +------------------------------- + +The following is a summary of Verilog attributes that Icarus Verilog +understands within Verilog source files to control synthesis +behavior. This section documents generic synthesis attributes. For +target specific attributes, see target specific documentation. + +These attributes only effect the behavior of the synthesizer. For +example, the ivl_combinational will not generate an error message +if the Verilog is being compiled for simulation. (It may generate a +warning.) + + +* Attributes for "always" and "initial" statements + +(\* ivl_combinational \*) + + This attribute tells the compiler that the statement models + combinational logic. If the compiler finds that it cannot make + combinational logic out of a marked always statement, it will + report an error. + + This attribute can be used to prevent accidentally inferring + latches or flip-flops where the user intended combinational + logic. + +(\* ivl_synthesis_on \*) + + This attribute tells the compiler that the marked always statement + is synthesizable. The compiler will attempt to synthesize the + code in the marked "always" statement. If it cannot in any way + synthesize it, then it will report an error. + +(\* ivl_synthesis_off \*) + + If this value is attached to an "always" statement, then the + compiler will *not* synthesize the "always" statement. This can be + used, for example, to mark embedded test bench code. + + +* Attributes for modules + +(\* ivl_synthesis_cell \*) + + If this value is attached to a module during synthesis, that + module will be considered a target architecture primitive, and + its interior will not be synthesized further. The module can + therefore hold a model for simulation purposes. + + +* Attributes for signals (wire/reg/integer/tri/etc.) + +(\* PAD = "" \*) + + If this attribute is attached to a signal that happens to be a + root module port, then targets that support it will use the string + value as a list of pin assignments for the port/signal. The format + is a comma separated list of location tokens, with the format of + the token itself defined by the back-end tools in use. + +* Other Attributes + +[ none defined yet ] + + +Misc +---- + +(\* _ivl_schedule_push \*) + + If this attribute is attached to a thread object (always or + initial statement) then the vvp code generator will generate code + that causes the scheduler to push this thread at compile time. The + compiler may internally add this attribute to always statements if + it detects that it is combinational. This helps resolve time-0 + races. diff --git a/_sources/developer/guide/ivl/index.rst.txt b/_sources/developer/guide/ivl/index.rst.txt new file mode 100644 index 0000000000..c581fed5ae --- /dev/null +++ b/_sources/developer/guide/ivl/index.rst.txt @@ -0,0 +1,12 @@ + +IVL - The Core Compiler +======================= + +.. toctree:: + :maxdepth: 1 + + netlist + attributes + ivl_target + lpm + t-dll diff --git a/_sources/developer/guide/ivl/ivl_target.rst.txt b/_sources/developer/guide/ivl/ivl_target.rst.txt new file mode 100644 index 0000000000..6deacd901f --- /dev/null +++ b/_sources/developer/guide/ivl/ivl_target.rst.txt @@ -0,0 +1,131 @@ + +Loadable Target API (ivl_target) +================================ + +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". + + +LPM Devices +----------- + +All LPM devices support a small set of common LPM functions, as +described in the ivl_target header file. The ivl_lpm_t object has a +type enumerated by ivl_lpm_type_t, and that type is accessible via the +ivl_lpm_type function. + +The following are type specific aspects of LPM devices. + +* IVL_LPM_UFUNC + +This LPM represents a user defined function. It is a way to connect +behavioral code into a structural network. The UFUNC device has a +vector output and a set of inputs. The ivl_lpm_define function returns +the definition as an ivl_scope_t object. + +The output vector is accessible through the ivl_lpm_q, and the output +has the width defined by ivl_lpm_width. This similar to most every +other LPM device with outputs. + +There are ivl_lpm_size() input ports, each with the width +ivl_lpm_data2_width(). The actual nexus is indexed by ivl_lpm_data2(). diff --git a/_sources/developer/guide/ivl/lpm.rst.txt b/_sources/developer/guide/ivl/lpm.rst.txt new file mode 100644 index 0000000000..0774be457f --- /dev/null +++ b/_sources/developer/guide/ivl/lpm.rst.txt @@ -0,0 +1,28 @@ + +What Is LPM +=========== + +LPM (Library of Parameterized Modules) is EIS-IS standard 103-A. It is +a standard library of abstract devices that are designed to be close +enough to the target hardware to be easily translated, yet abstract +enough to support a variety of target technologies without excessive +constraints. Icarus Verilog uses LPM internally to represent idealized +hardware, especially when doing target neutral synthesis. + +In general, the user does not even see the LPM that Icarus Verilog +generates, because the LPM devices are translated into technology +specific devices by the final code generator or target specific +optimizers. + +Internal Uses Of LPM +-------------------- + +Internally, Icarus Verilog uses LPM devices to represent the design in +abstract, especially when synthesizing such functions as addition, +flip-flops, etc. The `synth` functor generates LPM modules when +interpreting procedural constructs. The functor generates the LPM +objects needed to replace a behavioral description, and uses +attributes to tag the devices with LPM properties. + +Code generators need to understand the supported LPM devices so that +they can translate the devices into technology specific devices. diff --git a/_sources/developer/guide/ivl/netlist.rst.txt b/_sources/developer/guide/ivl/netlist.rst.txt new file mode 100644 index 0000000000..0baaea0d6d --- /dev/null +++ b/_sources/developer/guide/ivl/netlist.rst.txt @@ -0,0 +1,285 @@ + +Netlist Format +============== + +The output from the parse and elaboration steps is a "netlist" rooted +in a Design object. Parsing translates the design described in the +initial source file into a temporary symbolic "pform". Elaboration +then expands the design, resolving references and expanding +hierarchies, to produce a flattened netlist. This is the form that +optimizers and code generators use. + +The design optimization processes all manipulate the netlist, +translating it to a (hopefully) better netlist after each step. The +complete netlist is then passed to the code generator, the emit +function, where the final code (in the target format) is produced. + +Structural Items: NetNode and NetNet +------------------------------------ + +Components and wires, memories and registers all at their base are +either NetNode objects or NetNet objects. Even these classes are +derived from the NetObj class. + +All NetNode and NetNet objects have a name and some number of +pins. The name usually comes from the Verilog source that represents +that object, although objects that are artifacts of elaboration will +have a generated (and probably unreadable) name. The pins are the +ports into the device. NetNode objects have a pin for each pin of the +component it represents, and NetNet objects have a pin for each signal +in the vector. + +Node and net pins can be connected together via the connect +function. Connections are transitive (A==B and B==c means A==C) so +connections accumulate on a link as items are connected to it. The +destructors for nets and nodes automatically arrange for pins to be +disconnected when the item is deleted, so that the netlist can be +changed during processing. + +Structural Links +---------------- + +The NetNode and NetNet classes contain arrays of Link objects, one +object per pin. Each pin is a single bit. The Link objects link to all +the NetNode and NetNet objects' links that are connected together in +the design, and to a Nexus object. This way, code that examines a node +of the design can discover what is connected to each pin. + +The connected set of links also has common properties that are stored +or access from the Nexus object. All the Links that are connected +together are also connected to a single Nexus object. This object is +useful for accessing the properties and values that come from the +connected set of links. The Nexus object is also handy for iterating +over the connected set of Links. + +See the Link class definition in netlist.h for a description of the link +methods, and the Nexus class for nexus global methods. + +Currently, a link has 3 possible direction properties: + + PASSIVE -- These pins are sampled by the object that holds the + pin based on some external event. These are used, + for example, by NetESignal objects that read a + point for a procedural expression. + + INPUT -- These pins potentially react to the setting of its + input. + + OUTPUT -- These pins potentially drive the node. (They may be + three-state.) + + +Behavioral Items: NetProcTop, NetProc and derived classes +--------------------------------------------------------- + +Behavioral items are not in general linked to the netlist. Instead, +they represent elaborated behavioral statements. The type of the object +implies what the behavior of the statement does. For example, a +NetCondit object represents an `if` statement, and carries a +condition expression and up to two alternative sub-statements. + +At the root of a process is a NetProcTop object. This class carries a +type flag (initial or always) and a single NetProc object. The +contained statement may, depending on the derived class, refer to +other statements, compound statements, so on. But at the root of the +tree is the NetProcTop object. The Design class keeps a list of the +elaborated NetProcTop objects. That list represents the list of +processes in the design. + +Interaction Of Behavioral And Structural: NetAssign\_ +----------------------------------------------------- + +The behavioral statements in a Verilog design effect the structural +aspects through assignments to registers. Registers are structural +items represented by the NetNet class, linked to the assignment +statement through pins. This implies that the l-value of an assignment +is structural. It also implies that the statement itself is +structural, and indeed it is derived from NetNode. + +The NetAssign\_ class is also derived from the NetProc class because +what it does is brought on by executing the process. By multiple +inheritance we have therefore that the assignment is both a NetNode +and a NetProc. The NetAssign\_ node has pins that represent the l-value +of the statement, and carries behavioral expressions that represent +the r-value of the assignment. + +Memories +-------- + +The netlist form includes the NetMemory type to hold the content of a +memory. Instances of this type represent the declaration of a memory, +and occur once for each memory. References to the memory are managed +by the NetEMemory and NetAssignMem\_ classes. + +An instance of the NetEMemory class is created whenever a procedural +expression references a memory element. The operand is the index to +use to address (and read) the memory. + +An instance of the NetAssignMem\_ class is created when there is a +procedural assignment to the memory. The NetAssignMem\_ object +represents the l-value reference (a write) to the memory. As with the +NetEMemory class, this is a procedural reference only. + +When a memory reference appears in structural context (i.e. continuous +assignments) elaboration creates a NetRamDq. This is a LPM_RAM_DQ +device. Elaboration leaves the write control and data input pins +unconnected for now, because memories cannot appear is l-values of +continuous assignments. However, the synthesis functor may connect +signals to the write control lines to get a fully operational RAM. + +By the time elaboration completes, there may be many NetAssignMem\_, +NetEMemory and NetRamDq objects referencing the same NetMemory +object. Each represents a port into the memory. It is up to the +synthesis steps (and the target code) to figure out what to do with +these ports. + +Expressions +----------- + +Expressions are represented as a tree of NetExpr nodes. The NetExpr +base class contains the core methods that represent an expression +node, including virtual methods to help with dealing with nested +complexities of expressions. + +Expressions (as expressed in the source and p-form) may also be +elaborated structurally, where it makes sense. For example, assignment +l-value expressions are represented as connections to pins. Also, +continuous assignment module items are elaborated as gates instead of +as a procedural expression. Event expressions are also elaborated +structurally as events are like devices that trigger behavioral +statements. + +However, typical expressions the behavioral description are +represented as a tree of NetExpr nodes. The derived class of the node +encodes what kind of operator the node represents. + +Expression Bit Width +-------------------- + +The expression (represented by the NetExpr class) has a bit width that +it either explicitly specified, or implied by context or contents. +When each node of the expression is first constructed during +elaboration, it is given, by type and parameters, an idea what its +width should be. It certain cases, this is definitive, for example +with signals. In others, it is ambiguous, as with unsized constants. + +As the expression is built up by elaboration, operators that combine +expressions impose bit widths of the environment or expose the bit +widths of the sub expressions. For example, the bitwise AND (&) +operator has a bit size implied by its operands, whereas the +comparison (==) operator has a bit size of 1. The building up of the +elaborated expression checks and adjusts the bit widths as the +expression is built up, until finally the context of the expression +takes the final bit width and makes any final adjustments. + +The NetExpr::expr_width() method returns the calculated (or guessed) +expression width. This method will return 0 until the width is set by +calculation or context. If this method returns false, then it is up to +the context that wants the width to set one. The elaboration phase +will call the NetExpr::set_width method on an expression as soon as it +gets to a point where it believes that it knows what the width should +be. + +The NetExpr::set_width(unsigned) virtual method is used by the context +of an expression node to note to the expression that the width is +determined and please adapt. If the expression cannot reasonably +adapt, it will return false. Otherwise, it will adjust bit widths and +return true. + +:: + + I do not yet properly deal with cases where elaboration knows for + certain that the bit width does not matter. In this case, I + really should tell the expression node about it so that it can + pick a practical (and optimal) width. + +Interaction Of Expressions And Structure: NetESignal +---------------------------------------------------- + +The NetAssign\_ class described above is the means for processes to +manipulate the net, but values are read from the net by NetESignal +objects. These objects are class NetExpr because they can appear in +expressions (and have width). They are not NetNode object, but hold +pointers to a NetNet object, which is used to retrieve values with the +expression is evaluated. + + +Hierarchy In Netlists +--------------------- + +The obvious hierarchical structure of Verilog is the module. The +Verilog program may contain any number of instantiations of modules in +order to form an hierarchical design. However, the elaboration of the +design into a netlist erases module boundaries. Modules are expanded +each place they are used, with the hierarchical instance name used to +name the components of the module instance. However, the fact that a +wire or register is a module port is lost. + +The advantage of this behavior is first the simplification of the +netlist structure itself. Backends that process netlists only need to +cope with a list of nets, a list of nodes and a list of +processes. This eases the task of the backend code generators. + +Another advantage of this flattening of the netlist is that optimizers +can operate globally, with optimizations freely crossing module +boundaries. This makes coding of netlist transform functions such as +constant propagation more effective and easier to write. + + +Scope Representation In Netlists +-------------------------------- + +In spite of the literal flattening of the design, scope information is +preserved in the netlist, with the NetScope class. The Design class +keeps a single pointer to the root scope of the design. This is the +scope of the root module. Scopes that are then created within that +(or any nested) module are placed as children of the root scope, and +those children can have further children, and so on. + +Each scope in the tree carries its own name, and its relationship to +its parent and children. This makes it possible to walk the tree of +scopes. In practice, the walking of the scopes is handled by recursive +methods. + +Each scope also carries the parameters that are applicable to the +scope itself. The parameter expression (possibly evaluated) can be +located by name, given the scope object itself. The scan of the pform +to generate scopes also places the parameters that are declared in the +scope. Overrides are managed during the scan, and once the scan is +complete, defparam overrides are applied. + + +Tasks In Netlists +----------------- + +The flattening of the design does not include tasks and named +begin-end blocks. Tasks are behavioral hierarchy (whereas modules are +structural) so do not easily succumb to the flattening process. In +particular, it is logically impossible to flatten tasks that +recurse. (The elaboration process does reserve the right to flatten +some task calls. C++ programmers recognize this as inlining a task.) + + +Time Scale In Netlists +---------------------- + +The Design class and the NetScope classes carry time scale and +resolution information of the elaborated design. There is a global +resolution, and there are scope specific units and resolutions. Units +and resolutions are specified as signed integers, and interpreted as +the power of 10 of the value. For example, a resolution "-9" means +that "1" is 1ns (1e-9). The notation supports units from -128 to +127. +It is up to the back-ends to interpret "-4" as "100us". + +Delays are expressed in the netlist by integers. The units of these +delays are always given in the units of the design precision. This +allows everything to work with integers, and generally places the +burden of scaling delays into elaboration. This is, after all, a +common task. The Design::get_precision() method gets the global design +precision. + +Each NetScope also carries its local time_units and time_precision +values. These are filled in during scope elaboration and are used in +subsequent elaboration phases to arrange for scaling of delays. This +information can also be used by the code generator to scale times back +to the units of the scope, if that is desired. diff --git a/_sources/developer/guide/ivl/t-dll.rst.txt b/_sources/developer/guide/ivl/t-dll.rst.txt new file mode 100644 index 0000000000..fa446614a4 --- /dev/null +++ b/_sources/developer/guide/ivl/t-dll.rst.txt @@ -0,0 +1,61 @@ + +Loadable Targets +================ + +Icarus Verilog supports dynamically loading code generator modules to +perform the back-end processing of the completed design. The user +specifies on the command line the module to load. The compiler loads +the module (once the design is compiled and elaborated) and calls it +to finally handle the design. + +Loadable target modules implement a set of functions that the core +compiler calls to pass the design to it, and the module in turn uses a +collection of functions in the core (the API) to access details of the +design. + +Loading Target Modules +---------------------- + +The target module loader is invoked with the ivl flag "-tdll". That +is, the DLL loader is a linked in target type. The name of the target +module to load is then specified with the DLL flag, i.e. "-fDLL=". + +Compiling Target Modules +------------------------ + + + +Loadable Target Module Api +-------------------------- + +The target module API is defined in the ivl_target.h header file. This +declares all the type and functions that a loadable module needs to +access the design. + + +About Specific Expression Types +------------------------------- + +In this section find notes about the various kinds of expression +nodes. The notes here are in addition to the more general +documentation in the ivl_target.h header file. + +* IVL_EX_CONCAT + + The concatenation operator forms an expression node that holds the + repeat count and all the parameter expressions. The repeat count is + an integer that is calculated by the core compiler so it fully + evaluated, and *not* an expression. + + The parameter expressions are retrieved by the ivl_expr_parm method, + with the index increasing as parameters go from left to right, from + most significant to least significant. (Note that this is different + from the order of bits within an expression node.) + +* IVL_EX_NUMBER + + This is a constant number. The width is fully known, and the bit + values are all represented by the ASCII characters 0, 1, x or z. The + ivl_expr_bits method returns a pointer to the least significant bit, + and the remaining bits are ordered from least significant to most + significant. For example, 5'b1zzx0 is the 5 character string "0xzz1". diff --git a/_sources/developer/guide/misc/extensions.rst.txt b/_sources/developer/guide/misc/extensions.rst.txt new file mode 100644 index 0000000000..7352a70c51 --- /dev/null +++ b/_sources/developer/guide/misc/extensions.rst.txt @@ -0,0 +1,85 @@ + +Icarus Verilog Extensions +========================= + +Icarus Verilog supports certain extensions to the baseline IEEE1364 +standard. Some of these are picked from extended variants of the +language, such as SystemVerilog, and some are expressions of internal +behavior of Icarus Verilog, made available as a tool debugging aid. + +* Builtin System Functions + +** Extended Verilog Data Types + +This feature is turned off if the generation flag "-g" is set to other +then the default "2x". For example, "iverilog -g2x" enables extended +data types, and "iverilog -g2" disables them. + +Icarus Verilog adds support for extended data types. This extended +type syntax is based on a proposal by Cadence Design Systems, +originally as an update to the IEEE1364. That original proposal has +apparently been absorbed by the IEEE1800 SystemVerilog +standard. Icarus Verilog currently only takes the new primitive types +from the proposal. + +Extended data types separates the concept of net/variable from the +data type. Both nets and variables can declared with any data +type. The primitive types available are:: + + logic - The familiar 0, 1, x and z, optionally with strength. + bool - Limited to only 0 and 1 + real - 64bit real values + +Nets with logic type may have multiple drivers with strength, and the +value is resolved the usual way. Only logic values may be driven to +logic nets, so bool values driven onto logic nets are implicitly +converted to logic. + +Nets with any other type may not have multiple drivers. The compiler +should detect the multiple drivers and report an error. + +- Declarations + +The declaration of a net is extended to include the type of the wire, +with the syntax:: + + wire ... ; + +The , if omitted, is taken to be logic. The "wire" can be any of +the net keywords. Wires can be logic, bool, real, or vectors of logic +or bool. Some valid examples:: + + wire real foo = 1.0; + tri logic bus[31:0]; + wire bool addr[23:0]; + ... and so on. + +The declarations of variables is similar. The "reg" keyword is used to +specify that this is a variable. Variables can have the same data +types as nets. + +- Ports + +Module and task ports in standard Verilog are restricted to logic +types. This extension removes that restriction, allowing any type to +pass through the port consistent with the continuous assignment +connectivity that is implied by the type. + +- Expressions + +Expressions in the face of real values is covered by the baseline +Verilog standard. + +The bool type supports the same operators as the logic type, with the +obvious differences imposed by the limited domain. + +Comparison operators (not case compare) return logic if either of +their operands is logic. If both are bool or real (including mix of +bool and real) then the result is bool. This is because comparison of +bools and reals always return exactly true or false. + +Case comparison returns bool. This differs from baseline Verilog, +which strictly speaking returns a logic, but only 0 or 1 values. + +All the arithmetic operators return bool if both of their operands are +bool or real. Otherwise, they return logic. diff --git a/_sources/developer/guide/misc/ieee1364-notes.rst.txt b/_sources/developer/guide/misc/ieee1364-notes.rst.txt new file mode 100644 index 0000000000..39785298cf --- /dev/null +++ b/_sources/developer/guide/misc/ieee1364-notes.rst.txt @@ -0,0 +1,501 @@ + +IEEE1364 Notes +============== + +The IEEE1364 standard is the bible that defines the correctness of the +Icarus Verilog implementation and behavior of the compiled +program. The IEEE1364.1 is also referenced for matters of +synthesis. So the ultimate definition of right and wrong comes from +those documents. + +That does not mean that a Verilog implementation is fully +constrained. The standard document allows for implementation specific +behavior that, when properly accounted for, does not effect the +intended semantics of the specified language. It is therefore possible +and common to write programs that produce different results when run +by different Verilog implementations. + + +Standardization Issues +---------------------- + +These are some issues where the IEEE1364 left unclear, unspecified or +simply wrong. I'll try to be precise as I can, and reference the +standard as needed. I've made implementation decisions for Icarus +Verilog, and I will make clear what those decisions are and how they +affect the language. + +* OBJECTS CAN BE DECLARED ANYWHERE IN THE MODULE + +Consider this module:: + + module sample1; + initial foo = 1; + reg foo; + wire tmp = bar; + initial #1 $display("foo = %b, bar = %b", foo, tmp); + endmodule + +Notice that the `reg foo;` declaration is placed after the first +initial statement. It turns out that this is a perfectly legal module +according to the -1995 and -2000 versions of the standard. The +statement `reg foo;` is a module_item_declaration which is in turn a +module_item. The BNF in the appendix of IEEE1364-1995 treats all +module_item statements equally, so no order is imposed. + +Furthermore, there is no text (that I can find) elsewhere in the +standard that imposes any ordering restriction. The sorts of +restrictions I would look for are "module_item_declarations must +appear before all other module_items" or "variables must be declared +textually before they are referenced." Such statements simply do not +exist. (Personally, I think it is fine that they don't.) + +The closest is the rules for implicit declarations of variables that +are otherwise undeclared. In the above example, `bar` is implicitly +declared and is therefore a wire. However, although `initial foo = 1;` +is written before foo is declared, foo *is* declared within the +module, and declared legally by the BNF of the standard. + +Here is another example:: + + module sample2; + initial x.foo = 1; + test x; + initial #1 $display("foo = %b", x.foo); + endmodule + + module test; + reg foo; + endmodule; + +From this example one can clearly see that foo is once again declared +after its use in behavioral code. One also sees a forward reference of +an entire module. Once again, the standard places no restriction on +the order of module declarations in a source file, so this program is, +according to the standard, perfectly well formed. + +Icarus Verilog interprets both of these examples according to "The +Standard As I Understand It." However, commercial tools in general +break down with these programs. In particular, the first example +may generate different errors depending on the tool. The most common +error is to claim that `foo` is declared twice, once (implicitly) as +a wire and once as a reg. + +So the question now becomes, "Is the standard broken, or are the tools +limited?" Coverage of the standard seems to vary widely from tool to +tool so it is not clear that the standard really is at fault. It is +clear, however, that somebody goofed somewhere. + +My personal opinion is that there is no logical need to require that +all module_item_declarations precede any other module items. I +personally would oppose such a restriction. It may make sense to +require that declarations of variables within a module be preceded by +their use, although even that is not necessary for the implementation +of efficient compilers. + +However, the existence hierarchical naming syntax as demonstrated in +sample2 can have implications that affect any declaration order +rules. When reaching into a module with a hierarchical name, the +module being referenced is already completely declared (or not +declared at all, as in sample2) so module_item order is completely +irrelevant. But a "declare before use" rule would infect module +ordering, by requiring that modules that are used be first defined. + + +* TASK AND FUNCTION PARAMETERS CANNOT HAVE EXPLICIT TYPES + +Consider a function negate that wants to take a signed integer value +and return its negative:: + + function integer negate; + input [15:0] val; + negate = -val; + endfunction + +This is not quite right, because the input is implicitly a reg type, +which is unsigned. The result, then, will always be a negative value, +even if a negative val is passed in. + +It is possible to fix up this specific example to work properly with +the bit pattern of a 16bit number, but that is not the point. What's +needed is clarification on whether an input can be declared in the +port declaration as well as in the contained block declaration. + +As I understand the situation, this should be allowed:: + + function integer negate; + input [15:0] val; + reg signed [15:0] val; + negate = -val; + endfunction + +In the -1995 standard, the variable is already implicitly a reg if +declared within a function or task. However, in the -2000 standard +there is now (as in this example) a reason why one might want to +actually declare the type explicitly. + +I think that a port *cannot* be declared as an integer or time type +(though the result can) because the range of the port declaration must +match the range of the integer/time declaration, but the range of +integers is unspecified. This, by the way, also applies to module +ports. + +With the above in mind, I have decided to *allow* function and task +ports to be declared with types, as long as the types are variable +types, such as reg or integer. Without this, there would be no +portable way to pass integers into functions/tasks. The standard does +not say it is allowed, but it doesn't *disallow* it, and other +commercial tools seem to work similarly. + + +* ROUNDING OF TIME + +When the \`timescale directive is present, the compiler is supposed to +round fractional times (after scaling) to the nearest integer. The +confusing bit here is that it is apparently conventional that if the +\`timescale directive is *not* present, times are rounded towards zero +always. + + +* VALUE OF X IN PRIMITIVE OUTPUTS + +The IEEE1364-1995 standard clearly states in Table 8-1 that the x +symbols is allowed in input columns, but is not allowed in +outputs. Furthermore, none of the examples have an x in the output of +a primitive. Table 8-1 in the IEEE1364-2000 also says the same thing. + +However, the BNF clearly states that 0, 1, x and X are valid +output_symbol characters. The standard is self contradictory. So I +take it that x is allowed, as that is what Verilog-XL does. + + +* REPEAT LOOPS vs. REPEAT EVENT CONTROL + +There seems to be ambiguity in how code like this should be parsed:: + + repeat (5) @(posedge clk) ; + +There are two valid interpretations of this code, from the +IEEE1364-1995 standard. One looks like this:: + + procedural_timing_control_statement ::= + delay_or_event_control statement_or_null + + delay_or_event_control ::= + event_control + | repeat ( expression ) event_control + +If this interpretation is used, then the statement should +be executed after the 5th posedge of clk. However, there is also this +interpretation:: + + loop_statement ::= + repeat ( expression ) statement + +If *this* interpretation is used, then should be executed +5 times on the posedge of clk. The way the -1995 standard is written, +these are both equally valid interpretations of the example, yet they +produce very different results. The standard offers no guidance on how +to resolve this conflict, and the IEEE1364-2000 DRAFT does not improve +the situation. + +Practice suggests that a repeat followed by an event control should be +interpreted as a loop head, and this is what Icarus Verilog does, as +well as all the other major Verilog tools, but the standard does not +say this. + +* UNSIZED NUMERIC CONSTANTS ARE NOT LIMITED TO 32 BITS + +The Verilog standard allows Verilog implementations to limit the size +of unsized constants to a bit width of at least 32. That means that a +constant 17179869183 (36'h3_ffff_ffff) may overflow some compilers. In +fact, it is common to limit these values to 32bits. However, a +compiler may just as easily choose another width limit, for example +64bits. That value is equally good. + +However, it is not *required* that an implementation truncate at 32 +bits, and in fact Icarus Verilog does not truncate at all. It will +make the unsized constant as big as it needs to be to hold the value +accurately. This is especially useful in situations like this:: + + reg [width-1:0] foo = 17179869183; + +The programmer wants the constant to take on the width of the reg, +which in this example is parameterized. Since constant sizes cannot be +parameterized, the programmer ideally gives an unsized constant, which +the compiler then expands/contracts to match the l-value. + +Also, by choosing to not ever truncate, Icarus Verilog can handle code +written for a 64bit compiler as easily as for a 32bit compiler. In +particular, any constants that the user does not expect to be +arbitrarily truncated by his compiler will also not be truncated by +Icarus Verilog, no matter what that other compiler chooses as a +truncation point. + + +* UNSIZED EXPRESSIONS AS PARAMETERS TO CONCATENATION {} + +The Verilog standard clearly states in 4.1.14:: + + "Unsized constant numbers shall not be allowed in + concatenations. This is because the size of each + operand in the concatenation is needed to calculate + the complete size of the concatenation." + +So for example the expression {1'b0, 16} is clearly illegal. It +also stands to reason that {1'b0, 15+1} is illegal, for exactly the +same justification. What is the size of the expression (15+1)? +Furthermore, it is reasonable to expect that (16) and (15+1) are +exactly the same so far as the compiler is concerned. + +Unfortunately, Cadence seems to feel otherwise. In particular, it has +been reported that although {1'b0, 16} causes an error, {1'b0, 15+1} +is accepted. Further testing shows that any expression other than a +simple unsized constant is accepted there, even if all the operands of +all the operators that make up the expression are unsized integers. + +This is a semantic problem. Icarus Verilog doesn't limit the size of +integer constants. This is valid as stated in 2.5.1 Note 3:: + + "The number of bits that make up an unsized number + (which is a simple decimal number or a number without + the size specification) shall be *at*least* 32." + [emphasis added] + +Icarus Verilog will hold any integer constant, so the size will be as +large as it needs to be, whether that is 64bits, 128bits, or +more. With this in mind, what is the value of these expressions? + +:: + + {'h1_00_00_00_00} + {'h1 << 32} + {'h0_00_00_00_01 << 32} + {'h5_00_00_00_00 + 1} + +These examples show that the standard is justified in requiring that +the operands of concatenation have size. The dispute is what it takes +to cause an expression to have a size, and what that size is. +Verilog-XL claims that (16) does not have a size, but (15+1) does. The +size of the expression (15+1) is the size of the adder that is +created, but how wide is the adder when adding unsized constants? + +One might note that the quote from section 4.1.14 says "Unsized +*constant*numbers* shall not be allowed." It does not say "Unsized +expressions...", so arguably accepting (15+1) or even (16+0) as an +operand to a concatenation is not a violation of the letter of the +law. However, the very next sentence of the quote expresses the +intent, and accepting (15+1) as having a more defined size than (16) +seems to be a violation of that intent. + +Whatever a compiler decides the size is, the user has no way to +predict it, and the compiler should not have the right to treat (15+1) +any differently than (16). Therefore, Icarus Verilog takes the +position that such expressions are *unsized* and are not allowed as +operands to concatenations. Icarus Verilog will in general assume that +operations on unsized numbers produce unsized results. There are +exceptions when the operator itself does define a size, such as the +comparison operators or the reduction operators. Icarus Verilog will +generate appropriate error messages. + + +* MODULE INSTANCE WITH WRONG SIZE PORT LIST + +A module declaration like this declares a module that takes three ports:: + + module three (a, b, c); + input a, b, c; + reg x; + endmodule + +This is fine and obvious. It is also clear from the standard that +these are legal instantiations of this module:: + + three u1 (x,y,z); + three u2 ( ,y, ); + three u3 ( , , ); + three u4 (.b(y)); + +In some of the above examples, there are unconnected ports. In the +case of u4, the pass by name connects only port b, and leaves a and c +unconnected. u2 and u4 are the same thing, in fact, but using +positional or by-name syntax. The next example is a little less +obvious:: + + three u4 (); + +The trick here is that strictly speaking, the parser cannot tell +whether this is a list of no pass by name ports (that is, all +unconnected) or an empty positional list. If this were an empty +positional list, then the wrong number of ports is given, but if it is +an empty by-name list, it is an obviously valid instantiation. So it +is fine to accept this case as valid. + +These are more doubtful:: + + three u5(x,y); + three u6(,); + +These are definitely positional port lists, and they are definitely +the wrong length. In this case, the standard is not explicit about +what to do about positional port lists in module instantiations, +except that the first is connected to the first, second to second, +etc. It does not say that the list must be the right length, but every +example of unconnected ports used by-name syntax, and every example of +ordered list has the right size list. + +Icarus Verilog takes the (very weak) hint that ordered lists should be +the right length, and will therefore flag instances u5 and u6 as +errors. The IEEE1364 standard should be more specific one way or the +other. + +* UNKNOWN VALUES IN L-VALUE BIT SELECTS + +Consider this example:: + + reg [7:0] vec; + wire [4:0] idx = ; + [...] + vec[idx] = 1; + +So long as the value of idx is a valid bit select address, the +behavior of this assignment is obvious. However, there is no explicit +word in the standard as to what happens if the value is out of +range. The standard clearly states the value of an expression when the +bit-select or part select is out of range (the value is x) but does +not address the behavior when the expression is an l-value. + +Icarus Verilog will take the position that bit select expressions in +the l-value will select oblivion if it is out of range. That is, if +idx has a value that is not a valid bit select of vec, then the +assignment will have no effect. + + +* SCHEDULING VALUES IN LOGIC + +The interaction between blocking assignments in procedural code and +logic gates in gate-level code and expressions is poorly defined in +Verilog. Consider this example:: + + reg a; + reg b; + wire q = a & b; + + initial begin + a = 1; + b = 0; + #1 b = 1; + if (q !== 0) begin + $display("FAILED -- q changed too soon? %b", q); + $finish; + end + end + +This is a confusing situation. It is clear from the Verilog standard +that an assignment to a variable using a blocking assign causes the +l-value to receive the value before the assignment completes. This +means that a subsequent read of the assigned variable *must* read back +what was blocking-assigned. + +However, in the example above, the "wire q = a & b" expresses some +gate logic between a/b and q. The standard does not say whether a read +out of logic should read the value computed from previous assigns to +the input from the same thread. Specifically, when "a" and "b" are +assigned by blocking assignments, will a read of "q" get the computed +value or the existing value? + +In fact, existing commercial tools do it both ways. Some tools print +the FAILED message in the above example, and some do not. Icarus +Verilog does not print the FAILED message in the above example, +because the gate value change is *scheduled* when inputs are assigned, +but not propagated until the thread gives up the processor. + +Icarus Verilog chooses this behavior in order to filter out zero-width +pulses as early as possible. The implication of this is that a read of +the output of combinational logic will most likely *not* reflect the +changes in inputs until the thread that changed the inputs yields +execution. + + +* BIT AND PART SELECTS OF PARAMETERS + +Bit and part selects are supposed to only be supported on vector nets +and variables (wires, regs, etc.) However, it is common for Verilog +compilers to also support bit and part select on parameters. Icarus +Verilog also chooses to support bit and part selects on parameter +names, but we need to define what that means. + +A bit or a part select on a parameter expression returns an unsigned +value with a defined size. The parameter value is considered be a +constant vector of bits foo[X:0]. That is, zero based. The bit and +part selects operate from that assumption. + +Verilog 2001 adds syntax to allow the user to explicitly declare the +parameter range (i.e. parameter [5:0] foo = 9;) so Icarus Verilog will +(or should) use the explicitly declared vector dimensions to interpret +bit and part selects. + + +* EDGES OF VECTORS + +Consider this example:: + + reg [ 5:0] clock; + always @(posedge clock) [do stuff] + +The IEEE1364 standard clearly states that the @(posedge clock) looks +only at the bit clock[0] (the least significant bit) to search for +edges. It has been pointed out by some that Verilog XL instead +implements it as `@(posedge |clock)`: it looks for a rise in the +reduction or of the vector. Cadence Design Systems technical support +has been rumored to claim that the IEEE1364 specification is wrong, +but NC-Verilog behaves according to the specification, and thus +different from XL. + +Icarus Verilog, therefore, takes the position that the specification +is clear and correct, and it behaves as does NC-Verilog in this +matter. + + +* REAL VARIABLES IN $dumpoff DEAD-ZONES + +The IEEE1364 standard clearly states that in VCD files, the $dumpoff +section checkpoints all the dumped variables as X values. For reg and +wire bits/vectors, this obviously means 'bx values. Icarus Verilog +does this, for example:: + + $dumpoff + x! + x" + $end + +Real variables can also be included in VCD dumps, but it is not at +all obvious what is supposed to be dumped into the $dumpoff-$end +section of the VCD file. Verilog-XL dumps "r0 !" to set the real +variables to the dead-zone value of 0.0, whereas other tools, such as +ModelTech, ignore real variables in this section. + +For example (from XL):: + + $dumpoff + r0 ! + r0 " + $end + +Icarus Verilog dumps NaN values for real variables in the +$dumpoff-$end section of the VCD file. The NaN value is the IEEE754 +equivalent of an unknown value, and so better reflects the unknown +(during the dead zone) status of the variable, like this:: + + $dumpoff + rNaN ! + rNaN " + $end + +It turns out that NaN is conventionally accepted by scanf functions, +and viewers that support real variables support NaN values. So while +the IEEE1364 doesn't require this behavior, and given the variety that +already seems to exist amongst VCD viewers in the wild, this behavior +seems to be acceptable according to the standard, is a better mirror +of 4-value behavior in the dead zone, and appears more user friendly +when viewed by reasonable viewers. diff --git a/_sources/developer/guide/misc/index.rst.txt b/_sources/developer/guide/misc/index.rst.txt new file mode 100644 index 0000000000..5bc9aae358 --- /dev/null +++ b/_sources/developer/guide/misc/index.rst.txt @@ -0,0 +1,11 @@ + +Miscellaneous +============= + +.. toctree:: + :maxdepth: 1 + + extensions + ieee1364-notes + swift + xilinx-hint diff --git a/_sources/developer/guide/misc/swift.rst.txt b/_sources/developer/guide/misc/swift.rst.txt new file mode 100644 index 0000000000..95191f72fe --- /dev/null +++ b/_sources/developer/guide/misc/swift.rst.txt @@ -0,0 +1,68 @@ + +Swift Model Support (Preliminary) +================================= + + Copyright 2003 Stephen Williams + + NOTE: SWIFT support does not work yet, these are provisional + instructions, intended to show what's supposed to happen when I get + it working. + +Icarus Verilog support for SWIFT models is based on the LMTV interface +module from Synopsys. This module is normally distributed along with +the SWIFT models proper. This module can be linked with Icarus Verilog +via the cadpli compatibility object. (See cadpli.txt.) + +* Preliminaries + +First, you need the LMC_HOME environment variable set to point to the +installed directory for your SWIFT software. This setup is documented +in your SWIFT model documentation. + +* Compilation + +When compiling your Verilog design to include a SWIFT model, you need +to include wrappers for the model you intend to use. You may choose to +use ncverilog or verilogxl compatible wrappers, they work the +same. Locate your smartmodel directory, and include it in your command +file like so:: + + +libdir+.../smartmodel/sol/wrappers/verilogxl + +The wrappers directory includes Verilog modules that wrap your SWIFT +module, and with this +libdir+ statement in your command file, the +Icarus Verilog compiler will be able to locate these wrappers. The +wrappers in turn invoke the $lm_model system tasks that are the LMTV +support for your model. + + NOTE: This example uses the solaris directory of VerilogXL support + files as a source of wrappers. The files of interest, however, are + written in Verilog and are identical for all supported platforms, so + long as you choose the verilogxl or ncverilog files. + +* Execution + +After your simulation is compiled, run the simulation with the vvp +command, like this:: + + % vvp -mcadpli a.out -cadpli=$LMC_HOME/lib/x86_linux.lib/swiftpli.so:swift_boot + +What this command line means is:: + + -mcadpli + Include the cadpli compatibility module + + a.out + This is your compiled vvp file + + -cadpli=$LMC_HOME/lib/x86_linux.lib/swiftpli.so:swift_boot + This tells the cadpli module to load the swiftpli.so + shared object, and boot it. This is code that comes with + your SWIFT modules, and provides the generic SWIFT + capabilities (lm_* system tasks) needed by the module + itself. + +Once you start the vvp command, the SWIFT infrastructure will be +initialized as part of the simulation setup, and all should work +normally from here. + diff --git a/_sources/developer/guide/misc/xilinx-hint.rst.txt b/_sources/developer/guide/misc/xilinx-hint.rst.txt new file mode 100644 index 0000000000..4e58e9ef51 --- /dev/null +++ b/_sources/developer/guide/misc/xilinx-hint.rst.txt @@ -0,0 +1,113 @@ + +Xilinx Hint +=========== + +For those of you who wish to use Icarus Verilog, in combination with +the Xilinx back end (Foundation or Alliance), it can be done. I have +run some admittedly simple (2300 equivalent gates) designs through this +setup, targeting a Spartan XCS10. + +Verilog: +-------- + +Older versions of Icarus Verilog (like 19990814) couldn't synthesize +logic buried in procedural (flip-flop) assignment. Newer versions +(like 20000120) don't have this limitation. + +Procedural assignments have to be given one at a time, to be +"found" by xnfsyn. Say + +:: + + always @ (posedge Clk) Y = newY; + always @ (posedge Clk) Z = newZ; + +rather than + +:: + + always @ (posedge Clk) begin + Y = newY; + Z = newZ; + end + +Steve's xnf.txt covers most buffer and pin constructs, but I had reason +to use a global clock net not connected to an input pin. The standard +Verilog for a buffer, combined with a declaration to turn that into a +BUFG, is:: + + buf BUFG( your_output_here, your_input_here ); + $attribute(BUFG,"XNF-LCA","BUFG:O,I") + +I use post-processing on my .xnf files to add "FAST" attributes to +output pins. + +Running ivl: +------------ + +The -F switches are important. The following order seems to robustly +generate valid XNF files, and is used by "verilog -X":: + + -Fsynth -Fnodangle -Fxnfio + +Generating .pcf files: +---------------------- + +The ngdbuild step seems to lose pin placement information that ivl +puts in the XNF file. Use xnf2pcf to extract this information to +a .pcf file, which the Xilinx place-and-route software _will_ pay +attention to. Steve says he now makes that information available +in an NCF file, with -fncf=, but I haven't tested that. + +Running the Xilinx back end: + +You can presumably use the GUI, but that doesn't fit in Makefiles :-). +Here is the command sequence in pseudo-shell-script:: + + ngdbuild -p $part $1.xnf $1.ngd + map -p $part -o map.ncd $1.ngd + xnf2pcf <$1.xnf >$1.pcf # see above + par -w -ol 2 -d 0 map.ncd $1.ncd $1.pcf + bitgen_flags = -g ConfigRate:SLOW -g TdoPin:PULLNONE -g DonePin:PULLUP \ + -g CRC:enable -g StartUpClk:CCLK -g SyncToDone:no \ + -g DoneActive:C1 -g OutputsActive:C3 -g GSRInactive:C4 \ + -g ReadClk:CCLK -g ReadCapture:enable -g ReadAbort:disable + bitgen $1.ncd -l -w $bitgen_flags + +The Xilinx software has diarrhea of the temp files (14, not including +.xnf, .pcf, .ngd, .ncd, and .bit), so this sequence is best done in a +dedicated directory. Note in particular that map.ncd is a generic name. + +I had reason to run this remotely (and transparently within a Makefile) +via ssh. I use the gmake rule:: + + %.bit : %.xnf + ssh -x -a -o 'BatchMode yes' ${ALLIANCE_HOST} \ + remote_alliance ${REMOTE_DIR} $(basename $@) 2>&1 < $< + scp ${ALLIANCE_HOST}:${REMOTE_DIR}/$@ . + +and the remote_alliance script (on ${ALLIANCE_HOST}):: + + /bin/csh + cd $1 + cat >! $2.xnf + xnf2pcf <$2.xnf >! $2.pcf + ./backend $2 + +There is now a "Xilinx on Linux HOWTO" at http://www.polybus.com/xilinx_on_linux.html +I haven't tried this yet, it looks interesting. + +Downloading: +------------ + +I use the XESS (http://www.xess.com/) XSP-10 development board, which +uses the PC parallel (printer) port for downloading and interaction +with the host. They made an old version of their download program +public domain, posted it at http://www.xess.com/FPGA/xstools.zip , +and now there is a Linux port at ftp://ftp.microux.com/pub/pilotscope/xstools.tar.gz . + +The above hints are based on my experience with Foundation 1.5 on NT +(gack) and Alliance 2.1i on Solaris. Your mileage may vary. Good luck! + + - Larry Doolittle August 19, 1999 + updated February 1, 2000 diff --git a/_sources/developer/guide/tgt-vvp/tgt-vvp.rst.txt b/_sources/developer/guide/tgt-vvp/tgt-vvp.rst.txt new file mode 100644 index 0000000000..bc2b863abf --- /dev/null +++ b/_sources/developer/guide/tgt-vvp/tgt-vvp.rst.txt @@ -0,0 +1,36 @@ + +The VVP Target +============== + +Symbol Name Conventions +----------------------- + +There are some naming conventions that the vvp target uses for +generating symbol names. + +* wires and regs + +Nets and variables are named V_ where is the +full hierarchical name of the signal. + +* Logic devices + +Logic devices (and, or, buf, bufz, etc.) are named L_. In +this case the symbol is attached to a functor that is the output of +the logic device. + + +General Functor Web Structure +----------------------------- + +The net of gates, signals and resolvers is formed from the input +design. The basic structure is wrapped around the nexus, which is +represented by the ivl_nexus_t. + +Each nexus represents a resolved value. The input of the nexus is fed +by a single driver. If the nexus in the design has multiple drivers, +the drivers are first fed into a resolver (or a tree of resolvers) to +form a single output that is the nexus. + +The nexus, then, feeds its output to the inputs of other gates, or to +the .net objects in the design. diff --git a/_sources/developer/guide/vpi/index.rst.txt b/_sources/developer/guide/vpi/index.rst.txt new file mode 100644 index 0000000000..77a0754c4f --- /dev/null +++ b/_sources/developer/guide/vpi/index.rst.txt @@ -0,0 +1,9 @@ + +VPI in Icarus Verilog +===================== + +.. toctree:: + :maxdepth: 1 + + vpi + va_math diff --git a/_sources/developer/guide/vpi/va_math.rst.txt b/_sources/developer/guide/vpi/va_math.rst.txt new file mode 100644 index 0000000000..b671b1deae --- /dev/null +++ b/_sources/developer/guide/vpi/va_math.rst.txt @@ -0,0 +1,100 @@ + +Verilog-A math library +====================== + +License. +-------- + + Verilog-A math library built for Icarus Verilog + https://github.com/steveicarus/iverilog/ + + Copyright (C) 2007-2010 Cary R. (cygcary@yahoo.com) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Standard Verilog-A Mathematical Functions. +------------------------------------------ + +The va_math VPI module implements all the standard math functions provided +by Verilog-A as Verilog-D system functions. The names are the same except +like all Verilog-D system functions the name must be prefixed with a '$'. +For reference the functions are:: + + $ln(x) -- Natural logarithm + $log10(x) -- Decimal logarithm + $exp(x) -- Exponential + $sqrt(x) -- Square root + $min(x,y) -- Minimum + $max(x,y) -- Maximum + $abs(x) -- Absolute value + $floor(x) -- Floor + $ceil(x) -- Ceiling + $pow(x,y) -- Power (x**y) + $sin(x) -- Sine + $cos(x) -- Cosine + $tan(x) -- Tangent + $asin(x) -- Arc-sine + $acos(x) -- Arc-cosine + $atan(x) -- Arc-tangent + $atan2(y,x) -- Arc-tangent of y/x + $hypot(x,y) -- Hypotenuse (sqrt(x**2 + y**2)) + $sinh(x) -- Hyperbolic sine + $cosh(x) -- Hyperbolic cosine + $tanh(x) -- Hyperbolic tangent + $asinh(x) -- Arc-hyperbolic sine + $acosh(x) -- Arc-hyperbolic cosine + $atanh(x) -- Arc-hyperbolic tangent + +The only limit placed on the x and y arguments by the library is that they +must be numbers (not constant strings). The underlying C library controls +any other limits placed on the arguments. Most libraries return +-Inf or +NaN for results that cannot be represented with real numbers. All functions +return a real result. + +Standard Verilog-A Mathematical Constants. +------------------------------------------ + +The Verilog-A mathematical constants can be accessed by including the +"constants.vams" header file. It is located in the standard include +directory. Recent version of Icarus Verilog (0.9.devel) automatically +add this directory to the end of the list used to find include files. +For reference the mathematical constants are:: + + `M_PI -- Pi + `M_TWO_PI -- 2*Pi + `M_PI_2 -- Pi/2 + `M_PI_4 -- Pi/4 + `M_1_PI -- 1/Pi + `M_2_PI -- 2/Pi + `M_2_SQRTPI -- 2/sqrt(Pi) + `M_E -- e + `M_LOG2E -- log base 2 of e + `M_LOG10E -- log base 10 of e + `M_LN2 -- log base e of 2 + `M_LN10 -- log base e of 10 + `M_SQRT2 -- sqrt(2) + `M_SQRT1_2 -- 1/sqrt(2) + +Using the Library. +------------------ + +Just add "-m va_math" to your iverilog command line/command file and +\`include the "constants.vams" file as needed. + +Thanks +------ + +I would like to thank Larry Doolittle for his suggestions and +Stephen Williams for developing Icarus Verilog. diff --git a/_sources/developer/guide/vpi/vpi.rst.txt b/_sources/developer/guide/vpi/vpi.rst.txt new file mode 100644 index 0000000000..89c73c0ff4 --- /dev/null +++ b/_sources/developer/guide/vpi/vpi.rst.txt @@ -0,0 +1,50 @@ + +VPI Modules in Icarus Verilog +================================ + +The VPI interface for Icarus Verilog works by creating from a +collection of PLI applications a single vpi module. The vpi module +includes compiled code for the applications linked together (with any +other libraries that the applications need) into a module with two +exported symbols, the vpip_set_callback function and the +vlog_startup_routines array. + +The product that wishes to invoke the module (normally at run time) loads +the module, locates and calls the vpip_set_callback function to pass the +the module a jump table that allows the module to access the VPI routines +implemented by the product, then locates the vlog_startup_routines table +and calls all the startup routines contained in that table. It is possible +for a product to link with many modules. In that case, all the modules are +linked in and startup routines are called in order. + +The product that uses vpi modules uses the environment variable +VPI_MODULE_PATH as a ':' separated list of directories. This is the +module search path. When a module is specified by name (using whatever +means the product supports) the module search path is scanned until +the module is located. + +The special module names "system.vpi", "v2005_math.vpi", "v2009.vpi", +and "va_math.vpi" are part of the core Icarus Verilog distribution and +include implementations of the standard system tasks/functions. The +additional special module names "vhdl_sys.vpi" and "vhdl_textio.vpi" +include implementations of private functions used to support VHDL. + +Compiling A VPI Module +---------------------- + +See the documentation under: :doc:`Using VPI <../../../usage/vpi>` + +Tracing VPI Use +--------------- + +The vvp command includes the ability to trace VPI calls. This is +useful if you are trying to debug a problem with your code. To +activate tracing simply set the VPI_TRACE environment variable, with +the path to a file where trace text gets written. For example:: + + setenv VPI_TRACE /tmp/foo.txt + +This tracing is pretty verbose, so you don't want to run like this +normally. Also, the format of the tracing messages will change +according to my needs (and whim) so don't expect to be able to parse +it in software. diff --git a/_sources/developer/guide/vvp/debug.rst.txt b/_sources/developer/guide/vvp/debug.rst.txt new file mode 100644 index 0000000000..bef2f68296 --- /dev/null +++ b/_sources/developer/guide/vvp/debug.rst.txt @@ -0,0 +1,19 @@ + +Debug Aids For VVP +================== + +Debugging vvp can be fiendishly difficult, so there are some built in +debugging aids. These are enabled by setting the environment variable +VVP_DEBUG to the path to an output file. Then, various detailed debug +tools can be enabled as described below. + +* .resolv + +The .resolv can print debug information along with a label by +specifying the debug output label on the .resolv line:: + + .resolv tri$