3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-07 01:54:10 +00:00
yosys/manual/PRESENTATION_Prog.tex
whitequark 00e7dec7f5 Replace "ILANG" with "RTLIL" everywhere.
The only difference between "RTLIL" and "ILANG" is that the latter is
the text representation of the former, as opposed to the in-memory
graph representation. This distinction serves no purpose but confuses
people: it is not obvious that the ILANG backend writes RTLIL graphs.

Passes `write_ilang` and `read_ilang` are provided as aliases to
`write_rtlil` and `read_rtlil` for compatibility.
2020-08-26 17:29:32 +00:00

597 lines
21 KiB
TeX

\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{http://www.clifford.at/yosys/}
\end{center}
\end{frame}