diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c4376cc4..74f9ab10d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,14 +19,14 @@ much easier for someone to respond and help. ### Bug reports -Before you submit an issue, please have a search of the existing issues in case -one already exists. Making sure that you have a minimal, complete and -verifiable example (MVCE) is a great way to quickly check an existing issue -against a new one. Stack overflow has a guide on [how to create an -MVCE](https://stackoverflow.com/help/minimal-reproducible-example). The -[`bugpoint` -command](https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/bugpoint.html) -in Yosys can be helpful for this process. +Before you submit an issue, please check out the [how-to guide for +`bugpoint`](https://yosys.readthedocs.io/en/latest/using_yosys/bugpoint.html). +This guide will take you through the process of using the [`bugpoint` +command](https://yosys.readthedocs.io/en/latest/cmd/bugpoint.html) in Yosys to +produce a [minimal, complete and verifiable +example](https://stackoverflow.com/help/minimal-reproducible-example) (MVCE). +Providing an MVCE with your bug report drastically increases the likelihood that +someone will be able to help resolve your issue. # Using pull requests diff --git a/docs/source/cmd_ref.rst b/docs/source/cmd_ref.rst index acf2d1d41..d2d59ba54 100644 --- a/docs/source/cmd_ref.rst +++ b/docs/source/cmd_ref.rst @@ -1,5 +1,3 @@ -.. _cmd_ref: - ================================================================================ Command line reference ================================================================================ diff --git a/docs/source/conf.py b/docs/source/conf.py index 05dcb7d5f..e587b8d31 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -64,7 +64,6 @@ if os.getenv("READTHEDOCS"): # Ensure that autosectionlabel will produce unique names autosectionlabel_prefix_document = True -autosectionlabel_maxdepth = 1 # include todos for previews extensions.append('sphinx.ext.todo') diff --git a/docs/source/getting_started/scripting_intro.rst b/docs/source/getting_started/scripting_intro.rst index 01954c661..6a6e4ff51 100644 --- a/docs/source/getting_started/scripting_intro.rst +++ b/docs/source/getting_started/scripting_intro.rst @@ -26,7 +26,7 @@ of the comment is a semicolon ``;`` or a new line. .. code-block:: :caption: Using the ``-p`` option - $ yosys -p "read_verilog fifo.v; :this is a comment; prep" + $ yosys -p 'read_verilog fifo.v; :this is a comment; prep' .. warning:: @@ -42,6 +42,13 @@ will be raised by Yosys. `exec` provides a much more flexible way of executing commands, allowing the output to be logged and more control over when to generate errors. +.. warning:: + + Take care when using the ``yosys -p`` option. Some shells such as bash will + perform substitution options inside of a double quoted string, such as ``!`` + for history substitution and ``$`` for variable substitution; single quotes + should be used instead to pass the string to Yosys without substitution. + The synthesis starter script ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/using_yosys/bugpoint.rst b/docs/source/using_yosys/bugpoint.rst new file mode 100644 index 000000000..60cabd879 --- /dev/null +++ b/docs/source/using_yosys/bugpoint.rst @@ -0,0 +1,446 @@ +Minimizing failing (or bugged) designs +====================================== + +.. TODO:: pending merge of https://github.com/YosysHQ/yosys/pull/5068 + +This document is a how-to guide for reducing problematic designs to the bare +minimum needed for reproducing the issue. This is a Yosys specific alternative +to the Stack Overflow article: `How to create a Minimal, Reproducible Example`_, +and is intended to help when there's something wrong with your design, or with +Yosys itself. + +.. _How to create a Minimal, Reproducible Example: https://stackoverflow.com/help/minimal-reproducible-example + +.. note:: + + This guide assumes a moderate degree of familiarity with Yosys and requires + some amount of problem solving ability. + + +Before you start +---------------- + +The first (and often overlooked) step, is to check for and *read* any error +messages or warnings. Passing the ``-q`` flag when running Yosys will make it +so that only warnings and error messages are written to the console. Don't just +read the last message either, there may be warnings that indicate a problem +before it happens. While some things may only be regarded as warnings, such as +multiple drivers for the same signal or logic loops, these can cause problems in +some synthesis flows but not others. + +A Yosys error (one that starts with ``ERROR:``) may give you a line number from +your design, or the name of the object causing issues. If so, you may already +have enough information to resolve the problem, or at least understand why it's +happening. + +.. note:: + + If you're not already, try using the latest version from the `Yosys GitHub`_. + You may find that your issue has already been fixed! And even if it isn't, + testing with two different versions is a good way to ensure reproducibility. + +.. _Yosys GitHub: https://github.com/YosysHQ/yosys + +Another thing to be aware of is that Yosys generally doesn't perform rigorous +checking of input designs to ensure they are valid. This is especially true for +the `read_verilog` frontend. It is instead recommended that you try load it +with `iverilog`_ or `verilator`_ first, as an invalid design can often lead to +unexpected issues. + +.. _iverilog: https://steveicarus.github.io/iverilog/ +.. _verilator: https://www.veripool.org/verilator/ + +If you're using a custom synthesis script, try take a bit of time to figure out +which command is failing. Calling ``echo on`` at the start of your script will +`echo` each command executed; the last echo before the error should then be +where the error has come from. Check the help message for the failing command; +does it indicate limited support, or mention some other command that needs to be +run first? You can also try to call `check` and/or ``hierarchy -check`` before +the failure to see if they report and errors or warnings. + + +Minimizing RTLIL designs with bugpoint +-------------------------------------- + +Yosys provides the `bugpoint` command for reducing a failing design to the +smallest portion of that design which still results in failure. While initially +developed for Yosys crashes, `bugpoint` can also be used for designs that lead +to non-fatal errors, or even failures in other tools that use the output of a +Yosys script. + +.. note:: + + Make sure to back up your code (design source and yosys script(s)) before + making any modifications. Even if the code itself isn't important, this can + help avoid "losing" the error while trying to debug it. + +Can I use bugpoint? +~~~~~~~~~~~~~~~~~~~ + +The first thing to be aware of is that `bugpoint` is not available in every +build of Yosys. Because the command works by invoking external processes, it +requires that Yosys can spawn executables. Notably this means `bugpoint` is not +able to be used in WebAssembly builds such as that available via YoWASP. The +easiest way to check your build of Yosys is by running ``yosys -h bugpoint``. If +Yosys displays the help text for `bugpoint` then it is available for use. + +.. code-block:: console + :caption: `bugpoint` is unavailable + + $ yosys -h bugpoint + + -- Running command `help bugpoint' -- + No such command or cell type: bugpoint + +Next you need to separate loading the design from the failure point; you should +be aiming to reproduce the failure by running ``yosys -s -s +``. If the failure occurs while loading the design, such as during +`read_verilog` you will instead have to minimize the input design yourself. +Check out the instructions for :ref:`using_yosys/bugpoint:minimizing verilog +designs` below. + +.. note:: + + You should also be able to run the two scripts separately, calling first + ``yosys -s -p 'write_rtlil design.il'`` and then ``yosys -s + design.il``. If this doesn't work then it may mean that the + failure isn't reproducible from RTLIL and `bugpoint` won't work either. + +When we talk about failure points here, it doesn't just mean crashes or errors +in Yosys. The ```` script can also be a user-defined failure such +as the `select` command with one of the ``-assert-*`` options; an example where +this might be useful is when a pass is supposed to remove a certain kind of +cell, but there is some edge case where the cell is not removed. Another +use-case would be minimizing a design which fails with the `equiv_opt` command, +suggesting that the optimization in question alters the circuit in some way. + +It is even possible to use `bugpoint` with failures *external* to Yosys, by +making use of the `exec` command in ````. This is especially useful +when Yosys is outputting an invalid design, or when some other tool is +incompatible with the design. Be sure to use the ``exec -expect-*`` options so +that the pass/fail can be detected correctly. Multiple calls to `exec` can be +made, or even entire shell scripts: + +.. code-block:: yoscrypt + + exec -expect-return 1 --bash + +Our final failure we can use with `bugpoint` is one returned by a wrapper +process, such as ``valgrind`` or ``timeout``. In this case you will be calling +something like `` yosys -s design.il``. Here, Yosys is +run under a wrapper process which checks for some failure state, like a memory +leak or excessive runtime. + + +How do I use bugpoint? +~~~~~~~~~~~~~~~~~~~~~~ + +At this point you should have: + +1. either an RTLIL file containing the design to minimize (referred to here as + ``design.il``), or a Yosys script, ````, which loads it; and +2. a Yosys script, ````, which produces the failure and returns a + non-zero return status. + +Now call ``yosys -qq -s design.il`` and take note of the error(s) +that get printed. A template script, ````, is provided here which +you can use. Make sure to configure it with the correct filenames and use only +one of the methods to load the design. Fill in the ``-grep`` option with the +error message printed just before. If you are using a wrapper process for your +failure state, add the ``-runner ""`` option to the `bugpoint` call. + +.. code-block:: yoscrypt + :caption: ```` template script + + # Load design + read_rtlil design.il + ## OR + script + + # Call bugpoint with failure + bugpoint -script -grep "" + + # Save minimized design + write_rtlil min.il + +The ``-grep`` option is used to search the log file generated by the Yosys under +test. If the error message is generated by something else, such as a wrapper +process or compiler sanitizer, then you should instead use ``-err_grep``. For +an OS error, like a SEGFAULT, you can also use ``-expect-return`` to check the +error code returned. + +.. note:: + + Checking the error message or return status is optional, but highly + recommended. `bugpoint` can quite easily introduce bugs by creating + malformed designs that commands were not intended to handle. By having some + way to check the error, `bugpoint` can ensure that it is the *right* error + being reproduced. This is even more important when ```` contains + more than one command. + +By default, `bugpoint` is able to remove any part of the design. In order to +keep certain parts, for instance because you already know they are related to +the failure, you can use the ``bugpoint_keep`` attribute. This can be done with +``(* bugpoint_keep *)`` in Verilog, ``attribute \bugpoint_keep 1`` in RTLIL, or +``setattr -set bugpoint_keep 1 [selection]`` from a Yosys script. It is also +possible to limit `bugpoint` to only removing certain *kinds* of objects, such +as only removing entire modules or cells (instances of modules). For more about +the options available, check ``help bugpoint`` or :doc:`/cmd/bugpoint`. + +In some situations, it may also be helpful to use `setenv` before `bugpoint` to +set environment variables for the spawned processes. An example of this is +``setenv UBSAN_OPTIONS halt_on_error=1`` for where you are trying to raise an +error on undefined behaviour but only want the child process to halt on error. + +.. note:: + + Using `setenv` in this way may or may not affect the current process. For + instance the ``UBSAN_OPTIONS halt_on_error`` here only affects child + processes, as does the :doc:`Yosys environment variable` + ``ABC`` because they are only read on start-up. While others, such as + ``YOSYS_NOVERIFIC`` and ``HOME``, are evaluated each time they are used. + +Once you have finished configuration, you can now run ``yosys ``. +The first thing `bugpoint` will do is test the input design fails. If it +doesn't, make sure you are using the right ``yosys`` executable; unless the +``-yosys`` option is provided, it will use whatever the shell defaults to, *not* +the current ``yosys``. If you are using the ``-runner`` option, try replacing +the `bugpoint` command with ``write_rtlil test.il`` and then on a new line, +``! yosys -s test.il`` to check it works as expected and +returns a non-zero status. + +.. seealso:: + + For more on script parsing and the use of ``!``, check out + :ref:`getting_started/scripting_intro:script parsing`. + +Depending on the size of your design, and the length of your ````, +`bugpoint` may take some time; remember, it will run ``yosys -s `` +on each iteration of the design. The bigger the design, the more iterations. +The longer the ````, the longer each iteration will take. As the +design shrinks and `bugpoint` converges, each iteration should take less and +less time. Once all simplifications are exhausted and there are no more objects +that can be removed, the script will continue and the minimized design can be +saved. + + +What do I do with the minimized design? +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First off, check the minimized design still fails. This is especially important +if you're not using `write_rtlil` to output the minimized design. For example, +if you ran :ref:`bugpoint_script` below, then calling ``yosys -s +min.v`` should still fail in the same way. + +.. code-block:: yoscrypt + :caption: example `bugpoint` minimizer + :name: bugpoint_script + + read_verilog design.v + bugpoint -script + write_verilog min.v + +The `write_rtlil` command is generally more reliable, since `bugpoint` will have +run that exact code through the failing script. Other ``write_*`` commands +convert from the RTLIL and then back again during the ``read_*`` which can +result in differences which mean the design no longer fails. + +.. note:: + + Simply calling Yosys with the output of ``write_*``, as in ``yosys -s + min.v``, does not guarantee that the corresponding ``read_*`` + will be used. For more about this, refer to + :doc:`/using_yosys/more_scripting/load_design`, or load the design explicitly + with ``yosys -p 'read_verilog min.v' -s ``. + +Once you've verified the failure still happens, check out +:ref:`using_yosys/bugpoint:identifying issues` for more on what to do next. + + +Minimizing Verilog designs +-------------------------- + +.. seealso:: + + This section is not specific to Yosys, so feel free to use another guide such + as Stack Overflow's `How to create a Minimal, Reproducible Example`_. + +Be sure to check any errors or warnings for messages that might identify source +lines or object names that might be causing the failure, and back up your source +code before modifying it. If you have multiple source files, you should start +by reducing them down to a single file. If a specific file is failing to read, +try removing everything else and just focus on that one. If your source uses +the ``include`` directive, replace it with the contents of the file referenced. + +Unlike RTLIL designs where we can use `bugpoint`, Yosys does not provide any +tools for minimizing Verilog designs. Instead, you should use an external tool +like `C-Reduce`_ (with the ``--not-c`` flag) or `sv-bugpoint`_. + +.. _C-Reduce: https://github.com/csmith-project/creduce +.. _sv-bugpoint: https://github.com/antmicro/sv-bugpoint + +C-Reduce +~~~~~~~~ + +As a very brief overview for using C-Reduce, you want your failing source design +(``test.v``), and some shell script which checks for the error being +investigated (``test.sh``). Below is an :ref:`egtest` which uses `logger` and +the ``-expect error "" 1`` option to perform a similar role to +``bugpoint -grep``, along with ``verilator`` to lint the code and make sure it +is still valid. + +.. code-block:: bash + :caption: Example test.sh for C-Reduce + :name: egtest + + #!/bin/bash + verilator --lint-only test.v &&/ + yosys -p 'logger -expect error "unsupported" 1; read_verilog test.v' + +.. code-block:: verilog + :caption: input test.v + + module top(input clk, a, b, c, output x, y, z); + always @(posedge clk) begin + if (a == 1'b1) + $stop; + end + assign x = a; + assign y = a ^ b; + assign z = c; + endmodule + +In this example ``read_verilog test.v`` is giving an error message that contains +the string "unsupported" because the ``$stop`` system task is only supported in +``initial`` blocks. By calling ``creduce ./test.sh test.v --not-c`` we can +minimize the design to just the failing code, while still being valid Verilog. + +.. code-block:: verilog + :caption: output test.v + + module a; + always begin $stop; + end endmodule + + +sv-bugpoint +~~~~~~~~~~~ + +sv-bugpoint works quite similarly to C-Reduce, except it requires an output +directory to be provided and the check script needs to accept the target file as +an input argument: ``sv-bugpoint outDir/ test.sh test.v`` + +.. code-block:: bash + :caption: Example test.sh for sv-bugpoint + + #!/bin/bash + verilator --lint-only $1 &&/ + yosys -p "logger -expect error \"unsupported\" 1; read_verilog $1" + +Notice that the commands for ``yosys -p`` are now in double quotes (``"``), and +the quotes around the error string are escaped (``\"``). This is necessary for +the ``$1`` argument subsitution to work correctly. + + +Doing it manually +~~~~~~~~~~~~~~~~~ + +If for some reason you are unable to use a tool to minimize your code, you can +still do it manually. But it can be a time consuming process and requires a lot +of iteration. At any point in the process, you can check for anything that is +unused or totally disconnected (ports, wires, etc) and remove them. If a +specific module is causing the problem, try to set that as the top module +instead. Any parameters should have their default values changed to match the +failing usage. + +As a rule of thumb, try to split things roughly in half at each step; similar to +a "binary search". If you have 10 cells (instances of modules) in your top +module, and have no idea what is causing the issue, split them into two groups +of 5 cells. For each group of cells, try remove them and see if the failure +still happens. If the error still occurs with the first group removed, but +disappears when the second group is removed, then the first group can be safely +removed. If a module has no more instances, remove it entirely. Repeat this +for each remaining group of cells until each group only has 1 cell in it and no +more cells can be removed without making the error disappear. You can also +repeat this for each module still in your design. + +After minimizing the number of cells, do the same for the process blocks in your +top module. And again for any generate blocks and combinational blocks. +Remember to check for any ports or signals which are no longer used and remove +those too. Any signals which are written but never read can also be removed. + +.. note:: + + Depending on where the design is failing, there are some commands which may + help in identifying unused objects in the design. `hierarchy` will identify + which modules are used and which are not, but check for ``$paramod`` modules + before removing unused ones. ``debug clean`` will list all unused wires in + each module, as well as unused cells which were automatically generated + (giving the line number of the source that generated them). Adding the + ``-purge`` flag will also include named wires that would normally be ignored + by `clean`. Though when there are large numbers of unused wires it is often + easier to just delete sections of the code and see what happens. + +Next, try to remove or reduce assignments (``a = b``) and operations (``a + +b``). A good place to start is by checking for any wires/registers which are +read but never written. Try removing the signal declaration and replacing +references to it with ``'0`` or ``'x``. Do this with any constants too. Try to +replace strings with numeric values, and wide signals with smaller ones, then +see if the error persists. + +Check if there are any operations that you can simplify, like replacing ``a & +'0`` with ``'0``. If you have enable or reset logic, try removing it and see if +the error still occurs. Try reducing ``if .. else`` and ``case`` blocks to a +single case. Even if that doesn't work, you may still be able to remove some +paths; start with cases that appear to be unreachable and go from there. + +.. note:: + + When sharing code on the `Yosys GitHub`_, please try to keep things in + English. Declarations and strings should stick to the letters a-z and + numbers 0-9, unless the error is arising because of the names/characters + used. + + +Identifying issues +------------------ + +When identifying issues, it is quite useful to understand the conditions under +which the issue is occurring. While there are occasionally bugs that affect a +significant number of designs, Yosys changes are tested on a variety of designs +and operating systems which typically catch any such issues before they make it +into the main branch. So what is is it about your situation that makes it +unusual? + +.. note:: + + If you have access to a different platform you could also check if your issue + is reproducible there. Some issues may be specific to the platform or build + of Yosys. + +Try to match the minimized design back to its original context. Could you +achieve the same thing a different way, and if so, does this other method have +the same issue? Try to change the design in small ways and see what happens; +while `bugpoint` can reduce and simplify a design, it doesn't *change* much. +What happens if you change operators, for example a left shift (or `$shl`) to a +right shift (or `$shr`)? Try to see if the issue is tied to specific +parameters, widths, or values. + +Search `the existing issues`_ and see if someone has already made a bug report. +This is where changing the design and finding the limits of what causes the +failure really comes in handy. If you're more familiar with how the problem can +arise, you may be able to find a related issue more easily. If an issue already +exists for one case of the problem but you've found other cases, you can comment +on the issue and help get it solved. If there are no existing or related issues +already, then check out the steps for +:ref:`yosys_internals/extending_yosys/contributing:reporting bugs`. + +.. _the existing issues: https://github.com/YosysHQ/yosys/issues + +.. warning:: + + If you are using a fuzzer to find bugs, follow the instructions for + :doc:`/yosys_internals/extending_yosys/advanced_bugpoint`. **Do not** open + more than one fuzzer generated issue at a time if you can not identify the + root cause. If you are found to be doing this, your issues may be closed + without further investigation. diff --git a/docs/source/using_yosys/index.rst b/docs/source/using_yosys/index.rst index 55bd5c291..b243d431e 100644 --- a/docs/source/using_yosys/index.rst +++ b/docs/source/using_yosys/index.rst @@ -15,3 +15,5 @@ ways Yosys can interact with designs for a deeper investigation. synthesis/index more_scripting/index + bugpoint + verilog diff --git a/docs/source/using_yosys/more_scripting/interactive_investigation.rst b/docs/source/using_yosys/more_scripting/interactive_investigation.rst index e9c9bc9ac..ca4c76ee7 100644 --- a/docs/source/using_yosys/more_scripting/interactive_investigation.rst +++ b/docs/source/using_yosys/more_scripting/interactive_investigation.rst @@ -311,8 +311,8 @@ cells, as the net-names are usually suppressed in the circuit diagram if they are auto-generated. Note that the output is in the RTLIL representation, described in :doc:`/yosys_internals/formats/rtlil_rep`. -Interactive Design Investigation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Design Investigation +~~~~~~~~~~~~~~~~~~~~ Yosys can also be used to investigate designs (or netlists created from other tools). diff --git a/docs/source/using_yosys/more_scripting/load_design.rst b/docs/source/using_yosys/more_scripting/load_design.rst index bbc55a36b..7e417eff9 100644 --- a/docs/source/using_yosys/more_scripting/load_design.rst +++ b/docs/source/using_yosys/more_scripting/load_design.rst @@ -1,11 +1,101 @@ Loading a design -~~~~~~~~~~~~~~~~ +---------------- -keyword: Frontends +.. _input files: + +Input files on the command line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- guesses frontend based on file extension + + + ``.v`` -> ``read -vlog2k`` + + ``.sv`` -> ``read -sv`` + + ``.vhd`` and ``.vhdl`` -> ``read -vhdl`` + + ``.blif`` and ``.eblif`` -> `read_blif` + + ``.json`` -> `read_json` + + ``.il`` -> `read_rtlil` (direct textual representation of Yosys internal + state) + +- command line also supports + + + ``.ys`` -> `script` + + ``.tcl`` -> `tcl` + + ``-`` -> reads stdin and treats it as a script + +The `read` command +~~~~~~~~~~~~~~~~~~ + +- standard method of loading designs +- also for defining macros and include directories +- uses `verific` command if available + + + ``-verific`` and ``-noverific`` options to enforce with/without Verific + + check ``help read`` for more about the options available and the filetypes + supported + + elaborate designs with ``verific -import [options] `` (or use + `hierarchy`) + +- fallback to `read_verilog` with ``-defer`` option + + + does not compile design until `hierarchy` command as discussed in + :doc:`/getting_started/example_synth` + + more similar to `verific` behaviour + +- ``read -define`` et al mapped to `verific` or `verilog_defines` +- similarly, ``read -incdir`` et al mapped to `verific` or `verilog_defaults` + +.. note:: + + The Verific frontend for Yosys, which provides the :cmd:ref:`verific` + command, requires Yosys to be built with Verific. For full functionality, + custom modifications to the Verific source code from YosysHQ are required, + but limited useability can be achieved with some stock Verific builds. Check + :doc:`/yosys_internals/extending_yosys/build_verific` for more. + +.. _Frontend: + +Yosys frontends +~~~~~~~~~~~~~~~ + +- typically start with ``read_`` +- built-in support for heredocs + + + in-line code with ``< hierarchy -check``. + +.. note:: + + It may also be helpful to use the `log` command to add messages which you can + then search for either in the terminal or the logfile. This can be quite + useful if your script contains script-passes, like the + :doc:`/using_yosys/synthesis/synth`, which call many sub-commands and you're + not sure exactly which script-pass is calling the failing command. + + +Minimizing scripts +------------------ + +.. warning:: + + This section is intended as **advanced usage**, and generally not necessary + for normal bug reports. + +If you're using a command line prompt, such as ``yosys -p 'synth_xilinx' -o +design.json design.v``, consider converting it to a script. It's generally much +easier to iterate over changes to a script in a file rather than one on the +command line, as well as being better for sharing with others. + +.. code-block:: yoscrypt + :caption: example script, ``script.ys``, for prompt ``yosys -p 'synth_xilinx' -o design.json design.v`` + + read_verilog design.v + synth_xilinx + write_json design.json + +Next up you want to remove everything *after* the error occurs. If your final +command calls sub-commands, replace it with its contents first. In the case of +the :doc:`/using_yosys/synthesis/synth`, as well as certain other script-passes, +you can use the ``-run`` option to simplify this. For example we can replace +``synth -top -lut`` with the :ref:`replace_synth`. The options ``-top + -lut`` can be provided to each `synth` step, or to just the step(s) where +it is relevant, as done here. + +.. code-block:: yoscrypt + :caption: example replacement script for `synth` command + :name: replace_synth + + synth -top -run :coarse + synth -lut -run coarse:fine + synth -lut -run fine:check + synth -run check: + +Say we ran :ref:`replace_synth` and were able to remove the ``synth -run +check:`` and still got our error, then we check the log and we see the last +thing before the error was ``7.2. Executing MEMORY_MAP pass (converting memories +to logic and flip-flops)``. By checking the output of ``yosys -h synth`` (or the +`synth` help page) we can see that the `memory_map` pass is called in the +``fine`` step. We can then update our script to the following: + +.. code-block:: yoscrypt + :caption: example replacement script for `synth` when `memory_map` is failing + + synth -top -run :fine + opt -fast -full + memory_map + +By giving `synth` the option ``-run :fine``, we are telling it to run from the +beginning of the script until the ``fine`` step, where we then give it the exact +commands to run. There are some cases where the commands given in the help +output are not an exact match for what is being run, but are instead a +simplification. If you find that replacing the script-pass with its contents +causes the error to disappear, or change, try calling the script-pass with +``echo on`` to see exactly what commands are being called and what options are +used. + +.. warning:: + + Before continuing further, *back up your code*. The following steps can + remove context and lead to over-minimizing scripts, hiding underlying issues. + Check out :ref:`yosys_internals/extending_yosys/advanced_bugpoint:Why + context matters` to learn more. + +When a problem is occurring many steps into a script, minimizing the design at +the start of the script isn't always enough to identify the cause of the issue. +Each extra step of the script can lead to larger sections of the input design +being needed for the specific problem to be preserved until it causes a crash. +So to find the smallest possible reproducer it can sometimes be helpful to +remove commands prior to the failure point. + +The simplest way to do this is by writing out the design, resetting the current +state, and reading back the design: + +.. code-block:: yoscrypt + + write_rtlil ; design -reset; read_rtlil ; + +In most cases, this can be inserted immediately before the failing command while +still producing the error, allowing you to :ref:`minimize your +RTLIL` with the +```` output. For our previous example with `memory_map`, if +:ref:`map_reset` still gives the same error, then we should now be able to call +``yosys design.il -p 'memory_map'`` to reproduce it. + +.. code-block:: yoscrypt + :caption: resetting the design immediately before failure + :name: map_reset + + synth -top -run :fine + opt -fast -full + write_rtlil design.il; design -reset; read_rtlil design.il; + memory_map + +If that doesn't give the error (or doesn't give the same error), then you should +try to move the write/reset/read earlier in the script until it does. If you +have no idea where exactly you should put the reset, the best way is to use a +"binary search" type approach, reducing the possible options by half after each +attempt. + +.. note:: + + By default, `write_rtlil` doesn't include platform specific IP blocks and + other primitive cell models which are typically loaded with a ``read_verilog + -lib`` command at the start of the synthesis script. You may have to + duplicate these commands *after* the call to ``design -reset``. It is also + possible to write out *everything* with ``select =*; write_rtlil -selected + ``. + +As an example, your script has 16 commands in it before failing on the 17th. If +resetting immediately before the 17th doesn't reproduce the error, try between +the 8th and 9th (8 is half of the total 16). If that produces the error then +you can remove everything before the `read_rtlil` and try reset again in the +middle of what's left, making sure to use a different name for the output file +so that you don't overwrite what you've already got. If the error isn't +produced then you need to go earlier still, so in this case you would do between +the 4th and 5th (4 is half of the previous 8). Repeat this until you can't +reduce the remaining commands any further. + +A more conservative, but more involved, method is to remove or comment out +commands prior to the failing command. Each command, or group of commands, can +be disabled one at a time while checking if the error still occurs, eventually +giving the smallest subset of commands needed to take the original input through +to the error. The difficulty with this method is that depending on your design, +some commands may be necessary even if they aren't needed to reproduce the +error. For example, if your design includes ``process`` blocks, many commands +will fail unless you run the `proc` command. While this approach can do a +better job of maintaining context, it is often easier to *recover* the context +after the design has been minimized for producing the error. For more on +recovering context, checkout +:ref:`yosys_internals/extending_yosys/advanced_bugpoint:Why context matters`. + + +Why context matters +------------------- + +Sometimes when a command is raising an error, you're seeing a symptom rather +than the underlying issue. It's possible that an earlier command may be putting +the design in an invalid state, which isn't picked up until the error is raised. +This is particularly true for the pre-packaged +:doc:`/using_yosys/synthesis/synth`, which rely on a combination of generic and +architecture specific passes. As new features are added to Yosys and more +designs are supported, the types of cells output by a pass can grow and change; +and sometimes this leads to a mismatch in what a pass is intended to handle. + +If you minimized your script, and removed commands prior to the failure to get a +smaller reproducer, try to work backwards and find which commands may have +contributed to the design failing. From the minimized design you should have +some understanding of the cell or cells which are producing the error; but where +did those cells come from? The name and/or type of the cell can often point you +in the right direction: + +.. code-block:: + + # internal cell types start with a $ + # lowercase for word-level, uppercase for bit-level + $and + $_AND_ + + # cell types with $__ are typically intermediate cells used in techmapping + $__MUL16X16 + + # cell types without a $ are either user-defined or architecture specific + my_module + SB_MAC16 + + # object names might give you the name of the pass that created them + $procdff$1204 + $memory\rom$rdmux[0][0][0]$a$1550 + + # or even the line number in the Yosys source + $auto$muxcover.cc:557:implement_best_cover$2152 + $auto$alumacc.cc:495:replace_alu$1209 + +Try running the unminimized script and search the log for the names of the +objects in your minimized design. In the case of cells you can also search for +the type of the cell. Remember that calling `stat` will list all the types of +cells currently used in the design, and ``select -list =*`` will list the names +of of all the current objects. You can add these commands to your script, or +use an interactive terminal to run each command individually. Adding them to +the script can be more repeatable, but if it takes a long time to run to the +point you're interested in then an interactive shell session can give you more +flexibility once you reach that point. You can also add a call to the `shell` +command at any point in a script to start an interactive session at a given +point; allowing you to script any preparation steps, then come back once it's +done. + +The ``--dump-design`` option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Yosys provides the ``--dump-design`` option (or ``-P`` for short) for dumping +the design at specific steps of the script based on the log header. If the last +step before an error is ``7.2. Executing MEMORY_MAP pass (converting memories to +logic and flip-flops)``, then calling Yosys with ``--dump-design 7.2:bad.il`` +will save the design *before* this command runs, in the file ``bad.il``. + +It is also possible to use this option multiple times, e.g. ``-P2:hierarchy.il +-P7 -P7.2:bad.il``, to get multiple dumps in the same run. This can make it +easier to follow the design through each step to find where certain cells or +connections are coming from. ``--dump-design ALL`` is also allowed, writing out +the design at each log header. + +A worked example +~~~~~~~~~~~~~~~~ + +Say you did all the minimization and found that an error in `synth_xilinx` +occurs when a call to ``techmap -map +/xilinx/cells_map.v`` with +``MIN_MUX_INPUTS`` defined parses a `$_MUX16_` with all inputs set to ``1'x``. +You could fix the bug in ``+/xilinx/cells_map.v``, but that might only solve +this one case while leaving other problems that haven't been found yet. So you +step through the original script, calling `stat` after each step to find when +the `$_MUX16_` is added. + +You find that the `$_MUX16_` is introduced by a call to `muxcover`, but all the +inputs are defined, so calling `techmap` now works as expected. From running +`bugpoint` with the failing techmap you know that the cell with index ``2297`` +will fail, so you call ``select top/*$2297`` to limit to just that cell. This +can then be saved with ``design -save pre_bug`` or ``write_rtlil -selected +pre_bug.il``, so that you don't have to re-run all the earlier steps to get back +here. + +Next you step through the remaining commands and call `dump` after each to find +when the inputs are disconnected. You find that ``opt -full`` has optimized +away portions of the circuit, leading to `opt_expr` setting the undriven mux +inputs to ``x``, but failing to remove the now unnecessary `$_MUX16_`. Now +you've identified a problem in `opt_expr` that affects all of the wide muxes, +and could happen in any synthesis flow, not just `synth_xilinx`. + +.. seealso:: + + This example is taken from `YosysHQ/yosys#4590 + `_ and can be reproduced with a + version of Yosys between 0.45 and 0.51. diff --git a/docs/source/yosys_internals/extending_yosys/contributing.rst b/docs/source/yosys_internals/extending_yosys/contributing.rst index 69258aa5f..70170fc48 100644 --- a/docs/source/yosys_internals/extending_yosys/contributing.rst +++ b/docs/source/yosys_internals/extending_yosys/contributing.rst @@ -7,7 +7,7 @@ Contributing to Yosys |CONTRIBUTING|_ file. .. |CONTRIBUTING| replace:: :file:`CONTRIBUTING.md` -.. _CONTRIBUTING: https://github.com/YosysHQ/yosys/CONTRIBUTING.md +.. _CONTRIBUTING: https://github.com/YosysHQ/yosys/blob/main/CONTRIBUTING.md Coding Style ------------ @@ -42,3 +42,137 @@ for implicit type casts, always use ``GetSize(foobar)`` instead of ``foobar.size()``. (``GetSize()`` is defined in :file:`kernel/yosys.h`) Use range-based for loops whenever applicable. + + +Reporting bugs +-------------- + +- use the `bug report template`_ + +.. _bug report template: https://github.com/YosysHQ/yosys/issues/new?template=bug_report.yml + +- short title briefly describing the issue, e.g. + + techmap of wide mux with undefined inputs raises error during synth_xilinx + + + tells us what's happening ("raises error") + + gives the command affected (`techmap`) + + an overview of the input design ("wide mux with undefined inputs") + + and some context where it was found ("during `synth_xilinx`") + + +Reproduction Steps +~~~~~~~~~~~~~~~~~~ + +- ideally a code-block (starting and ending with triple backquotes) containing + the minimized design (Verilog or RTLIL), followed by a code-block containing + the minimized yosys script OR a command line call to yosys with + code-formatting (starting and ending with single backquotes) + +.. code-block:: markdown + + min.v + ```verilog + // minimized Verilog design + ``` + + min.ys + ``` + read_verilog min.v + # minimum sequence of commands to reproduce error + ``` + + OR + + `yosys -p ': minimum sequence of commands;' min.v` + +- alternatively can provide a single code-block which includes the minimized + design as a "here document" followed by the sequence of commands which + reproduce the error + + + see :doc:`/using_yosys/more_scripting/load_design` for more on heredocs. + +.. code-block:: markdown + + ``` + read_rtlil </path/to/file#L139-L147`` + + clicking on "Preview" should reveal a code block containing the lines of + source specified, with a link to the source file at the given commit + + +Additional details +~~~~~~~~~~~~~~~~~~ + +- once you have created the issue, any additional details can be added as a + comment on that issue +- could include any additional context as to what you were doing when you first + encountered the bug +- was this issue discovered through the use of a fuzzer +- if you've minimized the script, consider including the `bugpoint` script you + used, or the original script, e.g. + +.. code-block:: markdown + + Minimized with + ``` + read_verilog design.v + # original sequence of commands prior to error + bugpoint -script -grep "" + write_rtlil min.il + ``` + + OR + + Minimized from + `yosys -p ': original sequence of commands to produce error;' design.v` + +- if you're able to, it may also help to share the original un-minimized design + + + if the design is too big for a comment, consider turning it into a `Gist`_ + +.. _Gist: https://gist.github.com/ diff --git a/docs/source/yosys_internals/extending_yosys/index.rst b/docs/source/yosys_internals/extending_yosys/index.rst index 4ee21517b..72843ecd6 100644 --- a/docs/source/yosys_internals/extending_yosys/index.rst +++ b/docs/source/yosys_internals/extending_yosys/index.rst @@ -11,6 +11,7 @@ of interest for developers looking to customise Yosys builds. extensions build_verific functional_ir + advanced_bugpoint contributing test_suites diff --git a/docs/source/yosys_internals/index.rst b/docs/source/yosys_internals/index.rst index 3dd4224fa..483cc2bf8 100644 --- a/docs/source/yosys_internals/index.rst +++ b/docs/source/yosys_internals/index.rst @@ -38,5 +38,4 @@ as reference to implement a similar system in any language. formats/index extending_yosys/index techmap - verilog hashing