Revert "Merge pull request #1917 from YosysHQ/eddie/abc9_delay_check"
[yosys.git] / CodingReadme
index 88f16ff0aa03825670df63fd2972fdec2dfd9418..7d4ded93d2ffb12e88b81d0a254f6b804c6e1127 100644 (file)
 
 
+This file contains some very brief documentation on things like programming APIs.
+Also consult the Yosys manual and the section about programming in the presentation.
+(Both can be downloaded as PDF from the yosys webpage.)
 
 
+
+--snip-- only the lines below this mark are included in the yosys manual --snip--
 Getting Started
 ===============
 
 
 Getting Started
 ===============
 
 
-Reading List
-------------
+Outline of a Yosys command
+--------------------------
+
+Here is a the C++ code for a "hello_world" Yosys command (hello.cc):
+
+       #include "kernel/yosys.h"
+
+       USING_YOSYS_NAMESPACE
+       PRIVATE_NAMESPACE_BEGIN
+
+       struct HelloWorldPass : public Pass {
+               HelloWorldPass() : Pass("hello_world") { }
+               void execute(vector<string>, Design*) override {
+                       log("Hello World!\n");
+               }
+       } HelloWorldPass;
+
+       PRIVATE_NAMESPACE_END
+
+This can be built into a Yosys module using the following command:
+
+       yosys-config --exec --cxx --cxxflags --ldflags -o hello.so -shared hello.cc --ldlibs
+
+Or short:
+
+       yosys-config --build hello.so hello.cc
+
+And then executed using the following command:
+
+       yosys -m hello.so -p hello_world
+
+
+Yosys Data Structures
+---------------------
+
+Here is a short list of data structures that you should make yourself familiar
+with before you write C++ code for Yosys. The following data structures are all
+defined when "kernel/yosys.h" is included and USING_YOSYS_NAMESPACE is used.
+
+  1. Yosys Container Classes
+
+Yosys uses dict<K, T> and pool<T> as main container classes. dict<K, T> is
+essentially a replacement for std::unordered_map<K, T> and pool<T> is a
+replacement for std::unordered_set<T>. The main characteristics are:
+
+       - dict<K, T> and pool<T> are about 2x faster than the std containers
+
+       - references to elements in a dict<K, T> or pool<T> are invalidated by
+         insert and remove operations (similar to std::vector<T> on push_back()).
+
+       - some iterators are invalidated by erase(). specifically, iterators
+         that have not passed the erased element yet are invalidated. (erase()
+         itself returns valid iterator to the next element.)
+
+       - no iterators are invalidated by insert(). elements are inserted at
+         begin(). i.e. only a new iterator that starts at begin() will see the
+         inserted elements.
+
+       - the method .count(key, iterator) is like .count(key) but only
+         considers elements that can be reached via the iterator.
+
+       - iterators can be compared. it1 < it2 means that the position of t2
+         can be reached via t1 but not vice versa.
+
+       - the method .sort() can be used to sort the elements in the container
+         the container stays sorted until elements are added or removed.
+
+       - dict<K, T> and pool<T> will have the same order of iteration across
+         all compilers, standard libraries and architectures.
+
+In addition to dict<K, T> and pool<T> there is also an idict<K> that
+creates a bijective map from K to the integers. For example:
+
+       idict<string, 42> si;
+       log("%d\n", si("hello"));      // will print 42
+       log("%d\n", si("world"));      // will print 43
+       log("%d\n", si.at("world"));   // will print 43
+       log("%d\n", si.at("dummy"));   // will throw exception
+       log("%s\n", si[42].c_str()));  // will print hello
+       log("%s\n", si[43].c_str()));  // will print world
+       log("%s\n", si[44].c_str()));  // will throw exception
+
+It is not possible to remove elements from an idict.
+
+Finally mfp<K> implements a merge-find set data structure (aka. disjoint-set or
+union-find) over the type K ("mfp" = merge-find-promote).
+
+  2. Standard STL data types
+
+In Yosys we use std::vector<T> and std::string whenever applicable. When
+dict<K, T> and pool<T> are not suitable then std::map<K, T> and std::set<T>
+are used instead.
+
+The types std::vector<T> and std::string are also available as vector<T>
+and string in the Yosys namespace.
+
+  3. RTLIL objects
 
 
-To write Yosys C++ code you need to know at least the following classes in kernel/rtlil.h:
+The current design (essentially a collection of modules, each defined by a
+netlist) is stored in memory using RTLIL object (declared in kernel/rtlil.h,
+automatically included by kernel/yosys.h). You should glance over at least
+the declarations for the following types in kernel/rtlil.h:
+
+       RTLIL::IdString
+               This is a handle for an identifier (e.g. cell or wire name).
+               It feels a lot like a std::string, but is only a single int
+               in size. (The actual string is stored in a global lookup
+               table.)
+
+       RTLIL::SigBit
+               A single signal bit. I.e. either a constant state (0, 1,
+               x, z) or a single bit from a wire.
+
+       RTLIL::SigSpec
+               Essentially a vector of SigBits.
 
        RTLIL::Wire
        RTLIL::Cell
 
        RTLIL::Wire
        RTLIL::Cell
+               The building blocks of the netlist in a module.
+
        RTLIL::Module
        RTLIL::Module
-       RTLIL::SigSpec
+       RTLIL::Design
+               The module is a container with connected cells and wires
+               in it. The design is a container with modules in it.
+
+All this types are also available without the RTLIL:: prefix in the Yosys
+namespace.
+
+  4. SigMap and other Helper Classes
+
+There are a couple of additional helper classes that are in wide use
+in Yosys. Most importantly there is SigMap (declared in kernel/sigtools.h).
+
+When a design has many wires in it that are connected to each other, then a
+single signal bit can have multiple valid names. The SigMap object can be used
+to map SigSpecs or SigBits to unique SigSpecs and SigBits that consistently
+only use one wire from such a group of connected wires. For example:
+
+       SigBit a = module->addWire(NEW_ID);
+       SigBit b = module->addWire(NEW_ID);
+       module->connect(a, b);
+
+       log("%d\n", a == b); // will print 0
+
+       SigMap sigmap(module);
+       log("%d\n", sigmap(a) == sigmap(b)); // will print 1
+
+
+Using the RTLIL Netlist Format
+------------------------------
+
+In the RTLIL netlist format the cell ports contain SigSpecs that point to the
+Wires. There are no references in the other direction. This has two direct
+consequences:
+
+(1) It is very easy to go from cells to wires but hard to go in the other way.
+
+(2) There is no danger in removing cells from the netlists, but removing wires
+can break the netlist format when there are still references to the wire
+somewhere in the netlist.
+
+The solution to (1) is easy: Create custom indexes that allow you to make fast
+lookups for the wire-to-cell direction. You can either use existing generic
+index structures to do that (such as the ModIndex class) or write your own
+index. For many application it is simplest to construct a custom index. For
+example:
+
+       SigMap sigmap(module);
+       dict<SigBit, Cell*> sigbit_to_driver_index;
+
+       for (auto cell : module->cells())
+               for (auto &conn : cell->connections())
+                       if (cell->output(conn.first))
+                               for (auto bit : sigmap(conn.second))
+                                       sigbit_to_driver_index[bit] = cell;
+
+Regarding (2): There is a general theme in Yosys that you don't remove wires
+from the design. You can rename them, unconnect them, but you do not actually remove
+the Wire object from the module. Instead you let the "clean" command take care
+of the dangling wires. On the other hand it is safe to remove cells (as long as
+you make sure this does not invalidate a custom index you are using in your code).
+
+
+Example Code
+------------
 
 The following yosys commands are a good starting point if you are looking for examples
 of how to use the Yosys API:
 
 
 The following yosys commands are a good starting point if you are looking for examples
 of how to use the Yosys API:
 
-       passes/opt/wreduce.cc
-       passes/techmap/maccmap.cc
+       manual/CHAPTER_Prog/stubnets.cc
+       manual/PRESENTATION_Prog/my_cmd.cc
+
+
+Script Passes
+-------------
+
+The ScriptPass base class can be used to implement passes that just call other passes,
+like a script. Examples for such passes are:
+
+       techlibs/common/prep.cc
+       techlibs/common/synth.cc
+
+In some cases it is easier to implement such a pass as regular pass, for example when
+ScriptPass doesn't provide the type of flow control desired. (But many of the
+script passes in Yosys that don't use ScriptPass simply predate the ScriptPass base
+class.) Examples for such passes are:
+
+       passes/opt/opt.cc
+       passes/proc/proc.cc
+
+Whether they use the ScriptPass base-class or not, a pass should always either
+call other passes without doing any non-trivial work itself, or should implement
+a non-trivial algorithm but not call any other passes. The reason for this is that
+this helps containing complexity in individual passes and simplifies debugging the
+entire system.
+
+Exceptions to this rule should be rare and limited to cases where calling other
+passes is optional and only happens when requested by the user (such as for
+example `techmap -autoproc`), or where it is about commands that are "top-level
+commands" in their own right, not components to be used in regular synthesis
+flows (such as the `bugpoint` command).
+
+A pass that would "naturally" call other passes and also do some work itself
+should be re-written in one of two ways:
+
+1) It could be re-written as script pass with the parts that are not calls
+to other passes factored out into individual new passes. Usually in those
+cases the new sub passes share the same prefix as the top-level script pass.
+
+2) It could be re-written so that it already expects the design in a certain
+state, expecting the calling script to set up this state before calling the
+pass in questions.
+
+Many back-ends are examples for the 2nd approach. For example, `write_aiger`
+does not convert the design into AIG representation, but expects the design
+to be already in this form, and prints an `Unsupported cell type` error
+message otherwise.
 
 
 Notes on the existing codebase
 ------------------------------
 
 For historical reasons not all parts of Yosys adhere to the current coding
 
 
 Notes on the existing codebase
 ------------------------------
 
 For historical reasons not all parts of Yosys adhere to the current coding
-styles.  When adding code to existing parts of the system, adhere to this guide
+style. When adding code to existing parts of the system, adhere to this guide
 for the new code instead of trying to mimic the style of the surrounding code.
 
 
 for the new code instead of trying to mimic the style of the surrounding code.
 
 
@@ -50,23 +277,25 @@ Formatting of code
   on its own line for larger blocks, especially blocks that contains
   blank lines.
 
   on its own line for larger blocks, especially blocks that contains
   blank lines.
 
-- Otherwise stick to the Linux Kernel Coding Stlye:
+- Otherwise stick to the Linux Kernel Coding Style:
     https://www.kernel.org/doc/Documentation/CodingStyle
 
 
     https://www.kernel.org/doc/Documentation/CodingStyle
 
 
-C++ Langugage
+C++ Language
 -------------
 
 Yosys is written in C++11. At the moment only constructs supported by
 -------------
 
 Yosys is written in C++11. At the moment only constructs supported by
-gcc 4.6 is allowed in Yosys code. This will change in future releases.
+gcc 4.8 are allowed in Yosys code. This will change in future releases.
 
 In general Yosys uses "int" instead of "size_t". To avoid compiler
 warnings for implicit type casts, always use "GetSize(foobar)" instead
 
 In general Yosys uses "int" instead of "size_t". To avoid compiler
 warnings for implicit type casts, always use "GetSize(foobar)" instead
-of "foobar.size()". (GetSize() is defined by kernel/yosys.h)
+of "foobar.size()". (GetSize() is defined in kernel/yosys.h)
 
 Use range-based for loops whenever applicable.
 
 
 
 Use range-based for loops whenever applicable.
 
 
+--snap-- only the lines above this mark are included in the yosys manual --snap--
+
 
 Creating the Visual Studio Template Project
 ===========================================
 
 Creating the Visual Studio Template Project
 ===========================================
@@ -82,7 +311,7 @@ Creating the Visual Studio Template Project
        [ ] Add to source control
 
        [X] Console applications
        [ ] Add to source control
 
        [X] Console applications
-       [X] Empty Projcect
+       [X] Empty Project
        [ ] SDL checks
 
 2. Open YosysVS Project Properties
        [ ] SDL checks
 
 2. Open YosysVS Project Properties
@@ -123,7 +352,7 @@ Things to do after finalizing the cell interface:
 
        - Add support to kernel/satgen.h for the new cell type
        - Add to manual/CHAPTER_CellLib.tex (or just add a fixme to the bottom)
 
        - Add support to kernel/satgen.h for the new cell type
        - Add to manual/CHAPTER_CellLib.tex (or just add a fixme to the bottom)
-       - Maybe add support to the verilog backend for dumping such cells as expression
+       - Maybe add support to the Verilog backend for dumping such cells as expression
 
 
 
 
 
 
@@ -137,49 +366,45 @@ Update the CHANGELOG file:
        vi CHANGELOG
 
 
        vi CHANGELOG
 
 
-Run all tests with "make config-{clang,gcc,gcc-4.6}":
+Update and check documentation:
 
        cd ~yosys
 
        cd ~yosys
-       make clean
-       make test vloghtb
-       make install
-
-       cd ~yosys-bigsim
-       make clean
-       make full
+       make update-manual
+       make manual
+       - sanity check the figures in the appnotes and presentation
+           - if there are any odd things -> investigate
+           - make cosmetic changes to the .tex files if necessary
 
 
-       cd ~vloghammer
-       make purge gen_issues gen_samples
-       make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world
-       chromium-browser report.html
+       cd ~yosys
+       vi README CodingReadme
+       - is the information provided in those file still up to date
 
 
 Then with default config setting:
 
        cd ~yosys
 
 
 Then with default config setting:
 
        cd ~yosys
-       ./yosys -p 'proc; show' tests/simple/fiedler-cooley.v
-       ./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v
+       make vgtest
 
        cd ~yosys
 
        cd ~yosys
-       make manual
-       - sanity check the figures in the appnotes and presentation
-           - if there are any odd things -> investigate
-           - make cosmetic changes to the .tex files if necessary
+       ./yosys -p 'proc; show' tests/simple/fiedler-cooley.v
+       ./yosys -p 'proc; opt; show' tests/simple/fiedler-cooley.v
+       ./yosys -p 'synth; show' tests/simple/fiedler-cooley.v
+       ./yosys -p 'synth_xilinx -top up3down5; show' tests/simple/fiedler-cooley.v
 
 
+       cd ~yosys/examples/cmos
+       bash testbench.sh
 
 
-Also with default config setting:
+       cd ~yosys/examples/basys3
+       bash run.sh
 
 
-       cd ~yosys/techlibs/cmos
-       bash testbench.sh
 
 
-       cd ~yosys/techlibs/xilinx/example_sim_counter
-       bash run_sim.sh
+Test building plugins with various of the standard passes:
 
 
-       cd ~yosys/techlibs/xilinx/example_mojo_counter
-       bash example.sh
+       yosys-config --build test.so equiv_simple.cc
+       - also check the code examples in CodingReadme
 
 
 
 
-Finally if a current verific library is available:
+And if a version of the verific library is currently available:
 
        cd ~yosys
        cat frontends/verific/build_amd64.txt
 
        cd ~yosys
        cat frontends/verific/build_amd64.txt
@@ -189,24 +414,35 @@ Finally if a current verific library is available:
        ../../yosys test_navre.ys
 
 
        ../../yosys test_navre.ys
 
 
-Release candiate:
+Finally run all tests with "make config-{clang,gcc,gcc-4.8}":
 
 
-       - create branch yosys-x.y.z-rc and push to github
-       - contact the usual suspects per mail and ask them to test
-       - post on the reddit and ask people to test
-       - commit KISS fixes to the -rc branch if necessary
+       cd ~yosys
+       make clean
+       make test
+       make ystests
+       make vloghtb
+       make install
+
+       cd ~yosys-bigsim
+       make clean
+       make full
+
+       cd ~vloghammer
+       make purge gen_issues gen_samples
+       make SYN_LIST="yosys" SIM_LIST="icarus yosim verilator" REPORT_FULL=1 world
+       chromium-browser report.html
 
 
 Release:
 
        - set YOSYS_VER to x.y.z in Makefile
 
 
 Release:
 
        - set YOSYS_VER to x.y.z in Makefile
+       - remove "bumpversion" target from Makefile
        - update version string in CHANGELOG
        git commit -am "Yosys x.y.z"
 
        - push tag to github
        - post changelog on github
        - post short release note on reddit
        - update version string in CHANGELOG
        git commit -am "Yosys x.y.z"
 
        - push tag to github
        - post changelog on github
        - post short release note on reddit
-       - delete -rc branch from github
 
 
 Updating the website:
 
 
 Updating the website:
@@ -224,11 +460,97 @@ Updating the website:
        make push
 
 
        make push
 
 
-In master branch:
 
 
-       git merge {release-tag}
-       - set version to x.y.z+ in Makefile
-       - add section "Yosys x.y.z .. x.y.z+" to CHANGELOG
-       git commit --amend -am "Yosys x.y.z+"
+Cross-Building for Windows with MXE
+===================================
+
+Check http://mxe.cc/#requirements and install all missing requirements.
+
+As root (or other user with write access to /usr/local/src):
+
+       cd /usr/local/src
+       git clone https://github.com/mxe/mxe.git
+       cd mxe
+
+       make -j$(nproc) MXE_PLUGIN_DIRS="plugins/tcl.tk" \
+                       MXE_TARGETS="i686-w64-mingw32.static" \
+                       gcc tcl readline
+
+Then as regular user in some directory where you build stuff:
+
+       git clone https://github.com/cliffordwolf/yosys.git yosys-win32
+       cd yosys-win32
+       make config-mxe
+       make -j$(nproc) mxebin
+
+
+
+How to add unit test
+====================
+
+Unit test brings some advantages, briefly, we can list some of them (reference
+[1](https://en.wikipedia.org/wiki/Unit_testing)):
+
+* Tests reduce bugs in new features;
+* Tests reduce bugs in existing features;
+* Tests are good documentation;
+* Tests reduce the cost of change;
+* Tests allow refactoring;
+
+With those advantages in mind, it was required to choose a framework which fits
+well with C/C++ code.  Hence, it was chosen (google test)
+[https://github.com/google/googletest], because it is largely used and it is
+relatively easy learn.
+
+Install and configure google test (manually)
+--------------------------------------------
+
+In this section, you will see a brief description of how to install google
+test. However, it is strongly recommended that you take a look to the official
+repository (https://github.com/google/googletest) and refers to that if you
+have any problem to install it. Follow the steps below:
+
+* Install: cmake and pthread
+* Clone google test project from: https://github.com/google/googletest and
+  enter in the project directory
+* Inside project directory, type:
+
+```
+cmake -DBUILD_SHARED_LIBS=ON .
+make
+```
+
+* After compilation, copy all "*.so" inside directory "googlemock" and
+  "googlemock/gtest" to "/usr/lib/"
+* Done! Now you can compile your tests.
+
+If you have any problem, go to the official repository to find help.
+
+Ps.: Some distros already have googletest packed. If your distro supports it,
+you can use it instead of compile.
+
+Create new unit test
+--------------------
+
+If you want to add new unit tests for Yosys, just follow the steps below:
+
+* Go to directory "yosys/test/unit/"
+* In this directory you can find something similar Yosys's directory structure.
+  To create your unit test file you have to follow this pattern:
+  fileNameToImplementUnitTest + Test.cc. E.g.: if you want to implement the
+  unit test for kernel/celledges.cc, you will need to create a file like this:
+  tests/unit/kernel/celledgesTest.cc;
+* Implement your unit test
+
+Run unit test
+-------------
 
 
+To compile and run all unit tests, just go to yosys root directory and type:
+```
+make unit-test
+```
 
 
+If you want to remove all unit test files, type:
+```
+make clean-unit-test
+```