mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Moved presentation_prog
This commit is contained in:
		
							parent
							
								
									045c04096e
								
							
						
					
					
						commit
						cd6e63e1a9
					
				
					 11 changed files with 257 additions and 621 deletions
				
			
		
							
								
								
									
										20
									
								
								docs/images/simplified_rtlil.tex
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								docs/images/simplified_rtlil.tex
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
\documentclass[12pt,tikz]{standalone}
 | 
			
		||||
\pdfinfoomitdate 1
 | 
			
		||||
\pdfsuppressptexinfo 1
 | 
			
		||||
\pdftrailerid{}
 | 
			
		||||
\usepackage[utf8]{inputenc}
 | 
			
		||||
\usepackage{amsmath}
 | 
			
		||||
\usepackage{pgfplots}
 | 
			
		||||
\usepackage{tikz}
 | 
			
		||||
\pagestyle{empty}
 | 
			
		||||
 | 
			
		||||
\begin{document}
 | 
			
		||||
\begin{tikzpicture}[every node/.style={transform shape}]
 | 
			
		||||
	\tikzstyle{entity} = [draw, fill=gray!10, rectangle, minimum height=3em, minimum width=7em, node distance=5em, font={\ttfamily}]
 | 
			
		||||
	\node[entity] (design) {RTLIL::Design};
 | 
			
		||||
	\node[entity] (module) [right of=design, node distance=11em] {RTLIL::Module} edge [-latex] node[above] {\tiny 1 \hskip3em N} (design);
 | 
			
		||||
 | 
			
		||||
	\node[entity] (wire) [fill=blue!10, right of=module, node distance=10em] {RTLIL::Wire} (wire.west) edge [-latex] (module);
 | 
			
		||||
	\node[entity] (cell) [fill=blue!10, above of=wire] {RTLIL::Cell} (cell.west) edge [-latex] (module);
 | 
			
		||||
\end{tikzpicture}
 | 
			
		||||
\end{document}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,4 +3,4 @@ Selections
 | 
			
		|||
 | 
			
		||||
See :doc:`/cmd/select`
 | 
			
		||||
 | 
			
		||||
Also :doc:`/cmd/show`
 | 
			
		||||
Also :doc:`/cmd/show` and :doc:`/cmd/dump`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,44 +5,256 @@ Writing extensions
 | 
			
		|||
 | 
			
		||||
.. TODO: copypaste
 | 
			
		||||
 | 
			
		||||
This chapter contains some bits and pieces of information about
 | 
			
		||||
programming yosys extensions. Also consult the section on programming in
 | 
			
		||||
the "Yosys Presentation" (can be downloaded from the Yosys website as
 | 
			
		||||
PDF) and don't be afraid to ask questions on the YosysHQ Slack.
 | 
			
		||||
This chapter contains some bits and pieces of information about programming
 | 
			
		||||
yosys extensions. Don't be afraid to ask questions on the YosysHQ Slack.
 | 
			
		||||
 | 
			
		||||
Guidelines
 | 
			
		||||
----------
 | 
			
		||||
 | 
			
		||||
The guidelines directory contains notes on various aspects of Yosys
 | 
			
		||||
development. The files GettingStarted and CodingStyle may be of
 | 
			
		||||
particular interest, and are reproduced here.
 | 
			
		||||
The guidelines directory contains notes on various aspects of Yosys development.
 | 
			
		||||
The files GettingStarted and CodingStyle may be of particular interest, and are
 | 
			
		||||
reproduced here.
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../temp/GettingStarted
 | 
			
		||||
	:language: none
 | 
			
		||||
	:caption: guidelines/GettingStarted
 | 
			
		||||
    :language: none
 | 
			
		||||
    :caption: guidelines/GettingStarted
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../temp/CodingStyle
 | 
			
		||||
	:language: none
 | 
			
		||||
	:caption: guidelines/CodingStyle
 | 
			
		||||
    :language: none
 | 
			
		||||
    :caption: guidelines/CodingStyle
 | 
			
		||||
 | 
			
		||||
The "stubsnets" example module
 | 
			
		||||
------------------------------
 | 
			
		||||
 | 
			
		||||
The following is the complete code of the "stubsnets" example module. It
 | 
			
		||||
is included in the Yosys source distribution as
 | 
			
		||||
docs/source/CHAPTER_Prog/stubnets.cc.
 | 
			
		||||
The following is the complete code of the "stubsnets" example module. It is
 | 
			
		||||
included in the Yosys source distribution as
 | 
			
		||||
``docs/source/CHAPTER_Prog/stubnets.cc``.
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../CHAPTER_Prog/stubnets.cc
 | 
			
		||||
	:language: c++
 | 
			
		||||
	:linenos:
 | 
			
		||||
	:caption: docs/source/CHAPTER_Prog/stubnets.cc
 | 
			
		||||
    :language: c++
 | 
			
		||||
    :linenos:
 | 
			
		||||
    :caption: docs/source/CHAPTER_Prog/stubnets.cc
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../CHAPTER_Prog/Makefile
 | 
			
		||||
	:language: makefile
 | 
			
		||||
	:linenos:
 | 
			
		||||
	:caption: docs/source/CHAPTER_Prog/Makefile
 | 
			
		||||
    :language: makefile
 | 
			
		||||
    :linenos:
 | 
			
		||||
    :caption: docs/source/CHAPTER_Prog/Makefile
 | 
			
		||||
 | 
			
		||||
.. literalinclude:: ../CHAPTER_Prog/test.v
 | 
			
		||||
	:language: verilog
 | 
			
		||||
	:linenos:
 | 
			
		||||
	:caption: docs/source/CHAPTER_Prog/test.v
 | 
			
		||||
    :language: verilog
 | 
			
		||||
    :linenos:
 | 
			
		||||
    :caption: docs/source/CHAPTER_Prog/test.v
 | 
			
		||||
 | 
			
		||||
Quick guide
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
See also: ``docs/resources/PRESENTATION_Prog/*``.
 | 
			
		||||
 | 
			
		||||
Program components and data formats
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
See :doc:`/yosys_internals/formats/rtlil_rep` document for more information
 | 
			
		||||
about the internal data storage format used in Yosys and the classes that it
 | 
			
		||||
provides.
 | 
			
		||||
 | 
			
		||||
This document will focus on the much simpler version of RTLIL left after the
 | 
			
		||||
commands ``proc`` and ``memory`` (or ``memory -nomap``):
 | 
			
		||||
 | 
			
		||||
.. figure:: ../../images/simplified_rtlil.*
 | 
			
		||||
    :class: width-helper
 | 
			
		||||
    :name: fig:Simplified_RTLIL
 | 
			
		||||
 | 
			
		||||
    Simplified RTLIL entity-relationship diagram without memories and processes
 | 
			
		||||
 | 
			
		||||
It is possible to only work on this simpler version:
 | 
			
		||||
 | 
			
		||||
.. code:: c++
 | 
			
		||||
 | 
			
		||||
    for (RTLIL::Module *module : design->selected_modules() {
 | 
			
		||||
        if (module->has_memories_warn() || module->has_processes_warn())
 | 
			
		||||
            continue;
 | 
			
		||||
        ....
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
When trying to understand what a command does, creating a small test case to
 | 
			
		||||
look at the output of ``dump`` and ``show`` before and after the command has
 | 
			
		||||
been executed can be helpful.  The :doc:`/using_yosys/selections` document has
 | 
			
		||||
more information on using these commands.
 | 
			
		||||
 | 
			
		||||
.. TODO: copypaste
 | 
			
		||||
 | 
			
		||||
Creating modules from scratch
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Let's create the following module using the RTLIL API:
 | 
			
		||||
 | 
			
		||||
.. code:: Verilog
 | 
			
		||||
 | 
			
		||||
    module absval(input signed [3:0] a, output [3:0] y);
 | 
			
		||||
        assign y = a[3] ? -a : a;
 | 
			
		||||
    endmodule
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    RTLIL::Module *module = new RTLIL::Module;
 | 
			
		||||
    module->name = "\\absval";
 | 
			
		||||
 | 
			
		||||
    RTLIL::Wire *a = module->addWire("\\a", 4);
 | 
			
		||||
    a->port_input = true;
 | 
			
		||||
    a->port_id = 1;
 | 
			
		||||
 | 
			
		||||
    RTLIL::Wire *y = module->addWire("\\y", 4);
 | 
			
		||||
    y->port_output = true;
 | 
			
		||||
    y->port_id = 2;
 | 
			
		||||
 | 
			
		||||
    RTLIL::Wire *a_inv = module->addWire(NEW_ID, 4);
 | 
			
		||||
    module->addNeg(NEW_ID, a, a_inv, true);
 | 
			
		||||
    module->addMux(NEW_ID, a, a_inv, RTLIL::SigSpec(a, 1, 3), y);
 | 
			
		||||
 | 
			
		||||
    module->fixup_ports();
 | 
			
		||||
 | 
			
		||||
Modifying modules
 | 
			
		||||
~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Most commands modify existing modules, not create new ones.
 | 
			
		||||
 | 
			
		||||
When modifying existing modules, stick to the following DOs and DON'Ts:
 | 
			
		||||
 | 
			
		||||
- Do not remove wires. Simply disconnect them and let a successive ``clean``
 | 
			
		||||
  command worry about removing it.
 | 
			
		||||
- Use ``module->fixup_ports()`` after changing the ``port_*`` properties of
 | 
			
		||||
  wires.
 | 
			
		||||
- You can safely remove cells or change the ``connections`` property of a cell,
 | 
			
		||||
  but be careful when changing the size of the ``SigSpec`` connected to a cell
 | 
			
		||||
  port.
 | 
			
		||||
 | 
			
		||||
- Use the ``SigMap`` helper class (see next slide) when you need a unique handle for each signal bit.
 | 
			
		||||
 | 
			
		||||
Using the SigMap helper class
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Consider the following module:
 | 
			
		||||
 | 
			
		||||
.. code:: Verilog
 | 
			
		||||
 | 
			
		||||
    module test(input a, output x, y);
 | 
			
		||||
        assign x = a, y = a;
 | 
			
		||||
    endmodule
 | 
			
		||||
 | 
			
		||||
In this case ``a``, ``x``, and ``y`` are all different names for the same signal. However:
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    RTLIL::SigSpec a(module->wire("\\a")), x(module->wire("\\x")),
 | 
			
		||||
                                           y(module->wire("\\y"));
 | 
			
		||||
    log("%d %d %d\n", a == x, x == y, y == a); // will print "0 0 0"
 | 
			
		||||
 | 
			
		||||
The ``SigMap`` helper class can be used to map all such aliasing signals to a
 | 
			
		||||
unique signal from the group (usually the wire that is directly driven by a cell or port).
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    SigMap sigmap(module);
 | 
			
		||||
    log("%d %d %d\n", sigmap(a) == sigmap(x), sigmap(x) == sigmap(y),
 | 
			
		||||
                      sigmap(y) == sigmap(a)); // will print "1 1 1"
 | 
			
		||||
 | 
			
		||||
Printing log messages
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
The ``log()`` function is a ``printf()``-like function that can be used to create log messages.
 | 
			
		||||
 | 
			
		||||
Use ``log_signal()`` to create a C-string for a SigSpec object:
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    log("Mapped signal x: %s\n", log_signal(sigmap(x)));
 | 
			
		||||
 | 
			
		||||
The pointer returned by ``log_signal()`` is automatically freed by the log
 | 
			
		||||
framework at a later time.
 | 
			
		||||
 | 
			
		||||
Use ``log_id()`` to create a C-string for an ``RTLIL::IdString``:
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    log("Name of this module: %s\n", log_id(module->name));
 | 
			
		||||
 | 
			
		||||
Use ``log_header()`` and ``log_push()``/``log_pop()`` to structure log messages:
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    log_header(design, "Doing important stuff!\n");
 | 
			
		||||
    log_push();
 | 
			
		||||
    for (int i = 0; i < 10; i++)
 | 
			
		||||
        log("Log message #%d.\n", i);
 | 
			
		||||
    log_pop();
 | 
			
		||||
 | 
			
		||||
Error handling
 | 
			
		||||
~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Use ``log_error()`` to report a non-recoverable error:
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    if (design->modules.count(module->name) != 0)
 | 
			
		||||
        log_error("A module with the name %s already exists!\n",
 | 
			
		||||
                   RTLIL::id2cstr(module->name));
 | 
			
		||||
 | 
			
		||||
Use ``log_cmd_error()`` to report a recoverable error:
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    if (design->selection_stack.back().empty())
 | 
			
		||||
        log_cmd_error("This command can't operator on an empty selection!\n");
 | 
			
		||||
 | 
			
		||||
Use ``log_assert()`` and ``log_abort()`` instead of ``assert()`` and ``abort()``.
 | 
			
		||||
 | 
			
		||||
Creating a command
 | 
			
		||||
~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Simply create a global instance of a class derived from ``Pass`` to create
 | 
			
		||||
a new yosys command:
 | 
			
		||||
 | 
			
		||||
.. code:: C++
 | 
			
		||||
 | 
			
		||||
    #include "kernel/yosys.h"
 | 
			
		||||
    USING_YOSYS_NAMESPACE
 | 
			
		||||
 | 
			
		||||
    struct MyPass : public Pass {
 | 
			
		||||
        MyPass() : Pass("my_cmd", "just a simple test") { }
 | 
			
		||||
        virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
 | 
			
		||||
        {
 | 
			
		||||
            log("Arguments to my_cmd:\n");
 | 
			
		||||
            for (auto &arg : args)
 | 
			
		||||
            log("  %s\n", arg.c_str());
 | 
			
		||||
 | 
			
		||||
            log("Modules in current design:\n");
 | 
			
		||||
            for (auto mod : design->modules())
 | 
			
		||||
            log("  %s (%d wires, %d cells)\n", log_id(mod),
 | 
			
		||||
                GetSize(mod->wires()), GetSize(mod->cells()));
 | 
			
		||||
        }
 | 
			
		||||
    } MyPass;
 | 
			
		||||
 | 
			
		||||
Creating a plugin
 | 
			
		||||
~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Yosys can be extended by adding additional C++ code to the Yosys code base, or
 | 
			
		||||
by loading plugins into Yosys.
 | 
			
		||||
 | 
			
		||||
Use the following command to compile a Yosys plugin:
 | 
			
		||||
 | 
			
		||||
.. code::
 | 
			
		||||
 | 
			
		||||
    yosys-config --exec --cxx --cxxflags --ldflags \
 | 
			
		||||
             -o my_cmd.so -shared my_cmd.cc --ldlibs
 | 
			
		||||
 | 
			
		||||
Or shorter:
 | 
			
		||||
 | 
			
		||||
.. code::
 | 
			
		||||
 | 
			
		||||
    yosys-config --build my_cmd.so my_cmd.cc
 | 
			
		||||
 | 
			
		||||
Load the plugin using the yosys ``-m`` option:
 | 
			
		||||
 | 
			
		||||
.. code::
 | 
			
		||||
 | 
			
		||||
    yosys -m ./my_cmd.so -p 'my_cmd foo bar'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ Internal formats
 | 
			
		|||
	:maxdepth: 2
 | 
			
		||||
 | 
			
		||||
	overview
 | 
			
		||||
	rtlil
 | 
			
		||||
	rtlil_rep
 | 
			
		||||
	rtlil_text
 | 
			
		||||
	cell_library
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,596 +0,0 @@
 | 
			
		|||
 | 
			
		||||
\section{Writing Yosys extensions in C++}
 | 
			
		||||
 | 
			
		||||
\begin{frame}
 | 
			
		||||
\sectionpage
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Program Components and Data Formats}
 | 
			
		||||
 | 
			
		||||
\begin{frame}{\subsecname}
 | 
			
		||||
\begin{center}
 | 
			
		||||
\begin{tikzpicture}[scale=0.6, every node/.style={transform shape}]
 | 
			
		||||
	\tikzstyle{process} = [draw, fill=green!10, rectangle, minimum height=3em, minimum width=10em, node distance=15em]
 | 
			
		||||
	\tikzstyle{data} = [draw, fill=blue!10, ellipse, minimum height=3em, minimum width=7em, node distance=15em]
 | 
			
		||||
	\node[process] (vlog) {Verilog Frontend};
 | 
			
		||||
	\node[process, dashed, fill=green!5] (vhdl) [right of=vlog] {VHDL Frontend};
 | 
			
		||||
	\node[process] (ilang) [right of=vhdl] {Other Frontends};
 | 
			
		||||
	\node[data] (ast) [below of=vlog, node distance=5em, xshift=7.5em] {AST};
 | 
			
		||||
	\node[process] (astfe) [below of=ast, node distance=5em] {AST Frontend};
 | 
			
		||||
	\node[data] (rtlil) [below of=astfe, node distance=5em, xshift=7.5em] {RTLIL};
 | 
			
		||||
	\node[process] (pass) [right of=rtlil, node distance=5em, xshift=7.5em] {Passes};
 | 
			
		||||
	\node[process] (vlbe) [below of=rtlil, node distance=7em, xshift=-13em] {Verilog Backend};
 | 
			
		||||
	\node[process] (ilangbe) [below of=rtlil, node distance=7em, xshift=0em] {RTLIL Backend};
 | 
			
		||||
	\node[process, fill=green!5] (otherbe) [below of=rtlil, node distance=7em, xshift=+13em] {Other Backends};
 | 
			
		||||
 | 
			
		||||
	\draw[-latex] (vlog) -- (ast);
 | 
			
		||||
	\draw[-latex] (vhdl) -- (ast);
 | 
			
		||||
	\draw[-latex] (ast) -- (astfe);
 | 
			
		||||
	\draw[-latex] (astfe) -- (rtlil);
 | 
			
		||||
	\draw[-latex] (ilang) -- (rtlil);
 | 
			
		||||
	\draw[latex-latex] (rtlil) -- (pass);
 | 
			
		||||
	\draw[-latex] (rtlil) -- (vlbe);
 | 
			
		||||
	\draw[-latex] (rtlil) -- (ilangbe);
 | 
			
		||||
	\draw[-latex] (rtlil) -- (otherbe);
 | 
			
		||||
\end{tikzpicture}
 | 
			
		||||
\end{center}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Simplified RTLIL Entity-Relationship Diagram}
 | 
			
		||||
 | 
			
		||||
\begin{frame}{\subsecname}
 | 
			
		||||
Between passses and frontends/backends the design is stored in Yosys' internal
 | 
			
		||||
RTLIL (RTL Intermediate Language) format. For writing Yosys extensions it is
 | 
			
		||||
key to understand this format.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{center}
 | 
			
		||||
\begin{tikzpicture}[scale=0.6, every node/.style={transform shape}]
 | 
			
		||||
	\tikzstyle{entity} = [draw, fill=gray!10, rectangle, minimum height=3em, minimum width=7em, node distance=5em, font={\ttfamily}]
 | 
			
		||||
	\node[entity] (design) {RTLIL::Design};
 | 
			
		||||
	\node[entity] (module) [right of=design, node distance=11em] {RTLIL::Module} edge [-latex] node[above] {\tiny 1 \hskip3em N} (design);
 | 
			
		||||
 | 
			
		||||
	\node[entity] (process) [fill=green!10, right of=module, node distance=10em] {RTLIL::Process} (process.west) edge [-latex] (module);
 | 
			
		||||
	\node[entity] (memory) [fill=red!10, below of=process] {RTLIL::Memory} edge [-latex] (module);
 | 
			
		||||
	\node[entity] (wire) [fill=blue!10, above of=process] {RTLIL::Wire} (wire.west) edge [-latex] (module);
 | 
			
		||||
	\node[entity] (cell) [fill=blue!10, above of=wire] {RTLIL::Cell} (cell.west) edge [-latex] (module);
 | 
			
		||||
 | 
			
		||||
	\node[entity] (case) [fill=green!10, right of=process, node distance=10em] {RTLIL::CaseRule} edge [latex-latex] (process);
 | 
			
		||||
	\node[entity] (sync) [fill=green!10, above of=case] {RTLIL::SyncRule} edge [-latex] (process);
 | 
			
		||||
	\node[entity] (switch) [fill=green!10, below of=case] {RTLIL::SwitchRule} edge [-latex] (case);
 | 
			
		||||
	\draw[latex-] (switch.east) -- ++(1em,0) |- (case.east);
 | 
			
		||||
\end{tikzpicture}
 | 
			
		||||
\end{center}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{RTLIL without memories and processes}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[fragile]{\subsecname}
 | 
			
		||||
After the commands {\tt proc} and {\tt memory} (or {\tt memory -nomap}), we are
 | 
			
		||||
left with a much simpler version of RTLIL:
 | 
			
		||||
 | 
			
		||||
\begin{center}
 | 
			
		||||
\begin{tikzpicture}[scale=0.6, every node/.style={transform shape}]
 | 
			
		||||
	\tikzstyle{entity} = [draw, fill=gray!10, rectangle, minimum height=3em, minimum width=7em, node distance=5em, font={\ttfamily}]
 | 
			
		||||
	\node[entity] (design) {RTLIL::Design};
 | 
			
		||||
	\node[entity] (module) [right of=design, node distance=11em] {RTLIL::Module} edge [-latex] node[above] {\tiny 1 \hskip3em N} (design);
 | 
			
		||||
 | 
			
		||||
	\node[entity] (wire) [fill=blue!10, right of=module, node distance=10em] {RTLIL::Wire} (wire.west) edge [-latex] (module);
 | 
			
		||||
	\node[entity] (cell) [fill=blue!10, above of=wire] {RTLIL::Cell} (cell.west) edge [-latex] (module);
 | 
			
		||||
\end{tikzpicture}
 | 
			
		||||
\end{center}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Many commands simply choose to only work on this simpler version:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=0.5cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont]
 | 
			
		||||
for (RTLIL::Module *module : design->selected_modules() {
 | 
			
		||||
    if (module->has_memories_warn() || module->has_processes_warn())
 | 
			
		||||
        continue;
 | 
			
		||||
    ....
 | 
			
		||||
}
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
For simplicity we only discuss this version of RTLIL in this presentation.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Using dump and show commands}
 | 
			
		||||
 | 
			
		||||
\begin{frame}{\subsecname}
 | 
			
		||||
\begin{itemize}
 | 
			
		||||
\item The {\tt dump} command prints the design (or parts of it) in the text representation of RTLIL.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\item The {\tt show} command visualizes how the components in the design are connected.
 | 
			
		||||
\end{itemize}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
When trying to understand what a command does, create a small test case and
 | 
			
		||||
look at the output of {\tt dump} and {\tt show} before and after the command
 | 
			
		||||
has been executed.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{The RTLIL Data Structures}
 | 
			
		||||
 | 
			
		||||
\begin{frame}{\subsecname}
 | 
			
		||||
The RTLIL data structures are simple structs utilizing {\tt pool<>} and
 | 
			
		||||
{\tt dict<>} containers (drop-in replacements for {\tt
 | 
			
		||||
std::unordered\_set<>} and {\tt std::unordered\_map<>}).
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{itemize}
 | 
			
		||||
\item Most operations are performed directly on the RTLIL structs without
 | 
			
		||||
setter or getter functions.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\item In debug builds a consistency checker is run over the in-memory design
 | 
			
		||||
between commands to make sure that the RTLIL representation is intact.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\item Most RTLIL structs have helper methods that perform the most common operations.
 | 
			
		||||
\end{itemize}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
See {\tt yosys/kernel/rtlil.h} for details.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\subsubsection{RTLIL::IdString}
 | 
			
		||||
 | 
			
		||||
\begin{frame}{\subsubsecname}{}
 | 
			
		||||
{\tt RTLIL::IdString} in many ways behave like a {\tt std::string}. It is used
 | 
			
		||||
for names of RTLIL objects. Internally a RTLIL::IdString object is only a
 | 
			
		||||
single integer.
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
The first character of a {\tt RTLIL::IdString} specifies if the name is {\it public\/} or {\it private\/}:
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
\begin{itemize}
 | 
			
		||||
\item {\tt RTLIL::IdString[0] == '\textbackslash\textbackslash'}: \\
 | 
			
		||||
This is a public name. Usually this means it is a name that was declared in a Verilog file.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\item {\tt RTLIL::IdString[0] == '\$'}: \\
 | 
			
		||||
This is a private name. It was assigned by Yosys.
 | 
			
		||||
\end{itemize}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Use the {\tt NEW\_ID} macro to create a new unique private name.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\subsubsection{RTLIL::Design and RTLIL::Module}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsubsecname}
 | 
			
		||||
The {\tt RTLIL::Design} and {\tt RTLIL::Module} structs are the top-level RTLIL
 | 
			
		||||
data structures. Yosys always operates on one active design, but can hold many designs in memory.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
struct RTLIL::Design {
 | 
			
		||||
    dict<RTLIL::IdString, RTLIL::Module*> modules_;
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct RTLIL::Module {
 | 
			
		||||
    RTLIL::IdString name;
 | 
			
		||||
    dict<RTLIL::IdString, RTLIL::Wire*> wires_;
 | 
			
		||||
    dict<RTLIL::IdString, RTLIL::Cell*> cells_;
 | 
			
		||||
    std::vector<RTLIL::SigSig> connections_;
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
(Use the various accessor functions instead of directly working with the {\tt *\_} members.)
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\subsubsection{The RTLIL::Wire Structure}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsubsecname}
 | 
			
		||||
Each wire in the design is represented by a {\tt RTLIL::Wire} struct:
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
struct RTLIL::Wire {
 | 
			
		||||
    RTLIL::IdString name;
 | 
			
		||||
    int width, start_offset, port_id;
 | 
			
		||||
    bool port_input, port_output;
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
\hfil\begin{tabular}{p{3cm}l}
 | 
			
		||||
{\tt width} \dotfill & The total number of bits. E.g. 10 for {\tt [9:0]}. \\
 | 
			
		||||
{\tt start\_offset} \dotfill & The lowest bit index. E.g. 3 for {\tt [5:3]}. \\
 | 
			
		||||
{\tt port\_id} \dotfill & Zero for non-ports. Positive index for ports. \\
 | 
			
		||||
{\tt port\_input} \dotfill & True for {\tt input} and {\tt inout} ports. \\
 | 
			
		||||
{\tt port\_output} \dotfill & True for {\tt output} and {\tt inout} ports. \\
 | 
			
		||||
\end{tabular}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\subsubsection{RTLIL::State and RTLIL::Const}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsubsecname}
 | 
			
		||||
The {\tt RTLIL::State} enum represents a simple 1-bit logic level:
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
enum RTLIL::State {
 | 
			
		||||
    S0 = 0,
 | 
			
		||||
    S1 = 1,
 | 
			
		||||
    Sx = 2, // undefined value or conflict
 | 
			
		||||
    Sz = 3, // high-impedance / not-connected
 | 
			
		||||
    Sa = 4, // don't care (used only in cases)
 | 
			
		||||
    Sm = 5  // marker (used internally by some passes)
 | 
			
		||||
};
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
The {\tt RTLIL::Const} struct represents a constant multi-bit value:
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
struct RTLIL::Const {
 | 
			
		||||
    std::vector<RTLIL::State> bits;
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Notice that Yosys is not using special {\tt VCC} or {\tt GND} driver cells to represent constants. Instead
 | 
			
		||||
constants are part of the RTLIL representation itself.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\subsubsection{The RTLIL::SigSpec Structure}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsubsecname}
 | 
			
		||||
The {\tt RTLIL::SigSpec} struct represents a signal vector. Each bit can either be a bit from a wire
 | 
			
		||||
or a constant value.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
struct RTLIL::SigBit
 | 
			
		||||
{
 | 
			
		||||
    RTLIL::Wire *wire;
 | 
			
		||||
    union {
 | 
			
		||||
        RTLIL::State data; // used if wire == NULL
 | 
			
		||||
        int offset;        // used if wire != NULL
 | 
			
		||||
    };
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct RTLIL::SigSpec {
 | 
			
		||||
    std::vector<RTLIL::SigBit> bits_; // LSB at index 0
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
The {\tt RTLIL::SigSpec} struct has a ton of additional helper methods to compare, analyze, and
 | 
			
		||||
manipulate instances of {\tt RTLIL::SigSpec}.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\subsubsection{The RTLIL::Cell Structure}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsubsecname (1/2)}
 | 
			
		||||
The {\tt RTLIL::Cell} struct represents an instance of a module or library cell.
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
The ports of the cell
 | 
			
		||||
are associated with {\tt RTLIL::SigSpec} instances and the parameters are associated with {\tt RTLIL::Const}
 | 
			
		||||
instances:
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
struct RTLIL::Cell {
 | 
			
		||||
    RTLIL::IdString name, type;
 | 
			
		||||
    dict<RTLIL::IdString, RTLIL::SigSpec> connections_;
 | 
			
		||||
    dict<RTLIL::IdString, RTLIL::Const> parameters;
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
The {\tt type} may refer to another module in the same design, a cell name from a cell library, or a
 | 
			
		||||
cell name from the internal cell library:
 | 
			
		||||
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{6pt}{7pt}\selectfont]
 | 
			
		||||
$not $pos $neg $and $or $xor $xnor $reduce_and $reduce_or $reduce_xor $reduce_xnor
 | 
			
		||||
$reduce_bool $shl $shr $sshl $sshr $lt $le $eq $ne $eqx $nex $ge $gt $add $sub $mul $div $mod
 | 
			
		||||
$divfloor $modfloor $pow $logic_not $logic_and $logic_or $mux $pmux $slice $concat $lut $assert $sr $dff
 | 
			
		||||
$dffsr $adff $dlatch $dlatchsr $memrd $memwr $mem $fsm $_NOT_ $_AND_ $_OR_ $_XOR_ $_MUX_ $_SR_NN_
 | 
			
		||||
$_SR_NP_ $_SR_PN_ $_SR_PP_ $_DFF_N_ $_DFF_P_ $_DFF_NN0_ $_DFF_NN1_ $_DFF_NP0_ $_DFF_NP1_ $_DFF_PN0_
 | 
			
		||||
$_DFF_PN1_ $_DFF_PP0_ $_DFF_PP1_ $_DFFSR_NNN_ $_DFFSR_NNP_ $_DFFSR_NPN_ $_DFFSR_NPP_ $_DFFSR_PNN_
 | 
			
		||||
$_DFFSR_PNP_ $_DFFSR_PPN_ $_DFFSR_PPP_ $_DLATCH_N_ $_DLATCH_P_ $_DLATCHSR_NNN_ $_DLATCHSR_NNP_
 | 
			
		||||
$_DLATCHSR_NPN_ $_DLATCHSR_NPP_ $_DLATCHSR_PNN_ $_DLATCHSR_PNP_ $_DLATCHSR_PPN_ $_DLATCHSR_PPP_
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsubsecname (2/2)}
 | 
			
		||||
Simulation models (i.e. {\it documentation\/} :-) for the internal cell library:
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\hskip2em {\tt yosys/techlibs/common/simlib.v} and \\
 | 
			
		||||
\hskip2em {\tt yosys/techlibs/common/simcells.v}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
The lower-case cell types (such as {\tt \$and}) are parameterized cells of variable
 | 
			
		||||
width. This so-called {\it RTL Cells\/} are the cells described in {\tt simlib.v}.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
The upper-case cell types (such as {\tt \$\_AND\_}) are single-bit cells that are not
 | 
			
		||||
parameterized. This so-called {\it Internal Logic Gates} are the cells described
 | 
			
		||||
in {\tt simcells.v}.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
The consistency checker also checks the interfaces to the internal cell library.
 | 
			
		||||
If you want to use private cell types for your own purposes, use the {\tt \$\_\_}-prefix
 | 
			
		||||
to avoid name collisions.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
\subsubsection{Connecting wires or constant drivers}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsubsecname}
 | 
			
		||||
Additional connections between wires or between wires and constants are modelled using
 | 
			
		||||
{\tt RTLIL::Module::connections}:
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
typedef std::pair<RTLIL::SigSpec, RTLIL::SigSpec> RTLIL::SigSig;
 | 
			
		||||
 | 
			
		||||
struct RTLIL::Module {
 | 
			
		||||
    ...
 | 
			
		||||
    std::vector<RTLIL::SigSig> connections_;
 | 
			
		||||
    ...
 | 
			
		||||
};
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
{\tt RTLIL::SigSig::first} is the driven signal and {\tt RTLIL::SigSig::second} is the driving signal.
 | 
			
		||||
Example usage (setting wire {\tt foo} to value {\tt 42}):
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
module->connect(module->wire("\\foo"),
 | 
			
		||||
                RTLIL::SigSpec(42, module->wire("\\foo")->width));
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Creating modules from scratch}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsecname}
 | 
			
		||||
Let's create the following module using the RTLIL API:
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=Verilog]
 | 
			
		||||
module absval(input signed [3:0] a, output [3:0] y);
 | 
			
		||||
    assign y = a[3] ? -a : a;
 | 
			
		||||
endmodule
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
RTLIL::Module *module = new RTLIL::Module;
 | 
			
		||||
module->name = "\\absval";
 | 
			
		||||
 | 
			
		||||
RTLIL::Wire *a = module->addWire("\\a", 4);
 | 
			
		||||
a->port_input = true;
 | 
			
		||||
a->port_id = 1;
 | 
			
		||||
 | 
			
		||||
RTLIL::Wire *y = module->addWire("\\y", 4);
 | 
			
		||||
y->port_output = true;
 | 
			
		||||
y->port_id = 2;
 | 
			
		||||
 | 
			
		||||
RTLIL::Wire *a_inv = module->addWire(NEW_ID, 4);
 | 
			
		||||
module->addNeg(NEW_ID, a, a_inv, true);
 | 
			
		||||
module->addMux(NEW_ID, a, a_inv, RTLIL::SigSpec(a, 1, 3), y);
 | 
			
		||||
 | 
			
		||||
module->fixup_ports();
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Modifying modules}
 | 
			
		||||
 | 
			
		||||
\begin{frame}{\subsecname}
 | 
			
		||||
Most commands modify existing modules, not create new ones.
 | 
			
		||||
 | 
			
		||||
When modifying existing modules, stick to the following DOs and DON'Ts:
 | 
			
		||||
 | 
			
		||||
\begin{itemize}
 | 
			
		||||
\item Do not remove wires. Simply disconnect them and let a successive {\tt clean} command worry about removing it.
 | 
			
		||||
 | 
			
		||||
\item Use {\tt module->fixup\_ports()} after changing the {\tt port\_*} properties of wires.
 | 
			
		||||
 | 
			
		||||
\item You can safely remove cells or change the {\tt connections} property of a cell, but be careful when
 | 
			
		||||
changing the size of the {\tt SigSpec} connected to a cell port.
 | 
			
		||||
 | 
			
		||||
\item Use the {\tt SigMap} helper class (see next slide) when you need a unique handle for each signal bit.
 | 
			
		||||
\end{itemize}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Using the SigMap helper class}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsecname}
 | 
			
		||||
Consider the following module:
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=Verilog]
 | 
			
		||||
module test(input a, output x, y);
 | 
			
		||||
    assign x = a, y = a;
 | 
			
		||||
endmodule
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
In this case {\tt a}, {\tt x}, and {\tt y} are all different names for the same signal. However:
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
RTLIL::SigSpec a(module->wire("\\a")), x(module->wire("\\x")),
 | 
			
		||||
                                       y(module->wire("\\y"));
 | 
			
		||||
log("%d %d %d\n", a == x, x == y, y == a); // will print "0 0 0"
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
The {\tt SigMap} helper class can be used to map all such aliasing signals to a
 | 
			
		||||
unique signal from the group (usually the wire that is directly driven by a cell or port).
 | 
			
		||||
 | 
			
		||||
\smallskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
SigMap sigmap(module);
 | 
			
		||||
log("%d %d %d\n", sigmap(a) == sigmap(x), sigmap(x) == sigmap(y),
 | 
			
		||||
                  sigmap(y) == sigmap(a)); // will print "1 1 1"
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Printing log messages}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsecname}
 | 
			
		||||
The {\tt log()} function is a {\tt printf()}-like function that can be used to create log messages.
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
Use {\tt log\_signal()} to create a C-string for a SigSpec object\footnote[frame]{The pointer returned
 | 
			
		||||
by {\tt log\_signal()} is automatically freed by the log framework at a later time.}:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
log("Mapped signal x: %s\n", log_signal(sigmap(x)));
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
Use {\tt log\_id()} to create a C-string for an {\tt RTLIL::IdString}:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
log("Name of this module: %s\n", log_id(module->name));
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
Use {\tt log\_header()} and {\tt log\_push()}/{\tt log\_pop()} to structure log messages:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
log_header(design, "Doing important stuff!\n");
 | 
			
		||||
log_push();
 | 
			
		||||
for (int i = 0; i < 10; i++)
 | 
			
		||||
    log("Log message #%d.\n", i);
 | 
			
		||||
log_pop();
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Error handling}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsecname}
 | 
			
		||||
Use {\tt log\_error()} to report a non-recoverable error:
 | 
			
		||||
 | 
			
		||||
\medskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
if (design->modules.count(module->name) != 0)
 | 
			
		||||
    log_error("A module with the name %s already exists!\n",
 | 
			
		||||
            RTLIL::id2cstr(module->name));
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Use {\tt log\_cmd\_error()} to report a recoverable error:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
if (design->selection_stack.back().empty())
 | 
			
		||||
    log_cmd_error("This command can't operator on an empty selection!\n");
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Use {\tt log\_assert()} and {\tt log\_abort()} instead of {\tt assert()} and {\tt abort()}.
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Creating a command}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[t, fragile]{\subsecname}
 | 
			
		||||
Simply create a global instance of a class derived from {\tt Pass} to create
 | 
			
		||||
a new yosys command:
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont, language=C++]
 | 
			
		||||
#include "kernel/yosys.h"
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
 | 
			
		||||
struct MyPass : public Pass {
 | 
			
		||||
    MyPass() : Pass("my_cmd", "just a simple test") { }
 | 
			
		||||
    virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
 | 
			
		||||
    {
 | 
			
		||||
        log("Arguments to my_cmd:\n");
 | 
			
		||||
        for (auto &arg : args)
 | 
			
		||||
            log("  %s\n", arg.c_str());
 | 
			
		||||
 | 
			
		||||
        log("Modules in current design:\n");
 | 
			
		||||
        for (auto mod : design->modules())
 | 
			
		||||
            log("  %s (%d wires, %d cells)\n", log_id(mod),
 | 
			
		||||
                    GetSize(mod->wires()), GetSize(mod->cells()));
 | 
			
		||||
    }
 | 
			
		||||
} MyPass;
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Creating a plugin}
 | 
			
		||||
 | 
			
		||||
\begin{frame}[fragile]{\subsecname}
 | 
			
		||||
Yosys can be extended by adding additional C++ code to the Yosys code base, or
 | 
			
		||||
by loading plugins into Yosys.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Use the following command to compile a Yosys plugin:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont]
 | 
			
		||||
yosys-config --exec --cxx --cxxflags --ldflags \
 | 
			
		||||
             -o my_cmd.so -shared my_cmd.cc --ldlibs
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Or shorter:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont]
 | 
			
		||||
yosys-config --build my_cmd.so my_cmd.cc
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
Load the plugin using the yosys {\tt -m} option:
 | 
			
		||||
\begin{lstlisting}[xleftmargin=1cm, basicstyle=\ttfamily\fontsize{8pt}{10pt}\selectfont]
 | 
			
		||||
yosys -m ./my_cmd.so -p 'my_cmd foo bar'
 | 
			
		||||
\end{lstlisting}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 | 
			
		||||
 | 
			
		||||
\subsection{Summary}
 | 
			
		||||
 | 
			
		||||
\begin{frame}{\subsecname}
 | 
			
		||||
\begin{itemize}
 | 
			
		||||
\item Writing Yosys extensions is very straight-forward.
 | 
			
		||||
\item \dots and even simpler if you don't need RTLIL::Memory or RTLIL::Process objects.
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\item Writing synthesis software? Consider learning the Yosys API and make your work
 | 
			
		||||
part of the Yosys framework.
 | 
			
		||||
\end{itemize}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{center}
 | 
			
		||||
Questions?
 | 
			
		||||
\end{center}
 | 
			
		||||
 | 
			
		||||
\bigskip
 | 
			
		||||
\bigskip
 | 
			
		||||
\begin{center}
 | 
			
		||||
\url{https://yosyshq.net/yosys/}
 | 
			
		||||
\end{center}
 | 
			
		||||
\end{frame}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue