mirror of https://github.com/YosysHQ/yosys.git
290 lines
13 KiB
TeX
290 lines
13 KiB
TeX
|
|
\chapter{Evaluation of other OSS Verilog Synthesis Tools}
|
|
\label{chapter:sota}
|
|
|
|
In this appendix\footnote{This appendix is an updated version of an
|
|
unpublished student research paper. \cite{VerilogFossEval}}
|
|
the existing FOSS Verilog synthesis tools\footnote{To the
|
|
author's best knowledge, all relevant tools that existed at the time of this
|
|
writing are included. But as there is no formal channel through which such
|
|
tools are published it is hard to give any guarantees in that matter.} are
|
|
evaluated. Extremely limited or application specific tools (e.g.~pure Verilog
|
|
Netlist parsers) as well as Verilog simulators are not included. These existing
|
|
solutions are tested using a set of representative Verilog code snippets. It is
|
|
shown that no existing FOSS tool implements even close to a sufficient subset
|
|
of Verilog to be usable as synthesis tool for a wide range existing Verilog code.
|
|
|
|
The packages evaluated are:
|
|
|
|
\begin{itemize}
|
|
\item Icarus Verilog \citeweblink{Icarus}\footnote{Icarus Verilog is mainly a simulation
|
|
tool but also supported synthesis up to version 0.8. Therefore version 0.8.7 is used
|
|
for this evaluation.)}
|
|
\item Verilog-to-Routing (VTR) / Odin-II \cite{vtr2012}\cite{Odin}\citeweblink{VTR}
|
|
\item HDL Analyzer and Netlist Architect (HANA) \citeweblink{HANA}
|
|
\item Verilog front-end to VIS (vl2mv) \cite{Cheng93vl2mv:a}\citeweblink{VIS}
|
|
\end{itemize}
|
|
|
|
In each of the following sections Verilog modules that test a certain Verilog
|
|
language feature are presented and the support for these features is tested in all
|
|
the tools mentioned above. It is evaluated whether the tools under test
|
|
successfully generate netlists for the Verilog input and whether these netlists
|
|
match the simulation behavior of the designs using testbenches.
|
|
|
|
All test cases are verified to be synthesizeable using Xilinx XST from the Xilinx
|
|
WebPACK \citeweblink{XilinxWebPACK} suite.
|
|
|
|
Trivial features such as support for simple structural Verilog are not explicitly tested.
|
|
|
|
Vl2mv and Odin-II generate output in the BLIF (Berkeley Logic Interchange
|
|
Format) and BLIF-MV (an extended version of BLIF) formats respectively.
|
|
ABC \citeweblink{ABC} is used to convert this output to Verilog for verification
|
|
using testbenches.
|
|
|
|
Icarus Verilog generates EDIF (Electronic Design Interchange Format) output
|
|
utilizing LPM (Library of Parameterized Modules) cells. The EDIF files are
|
|
converted to Verilog using edif2ngd and netgen from Xilinx WebPACK. A
|
|
hand-written implementation of the LPM cells utilized by the generated netlists
|
|
is used for verification.
|
|
|
|
Following these functional tests, a quick analysis of the extensibility of the tools
|
|
under test is provided in a separate section.
|
|
|
|
The last section of this chapter finally concludes these series of evaluations
|
|
with a summary of the results.
|
|
|
|
\begin{figure}[t!]
|
|
\begin{minipage}{7.7cm}
|
|
\lstinputlisting[numbers=left,frame=single,language=Verilog]{CHAPTER_StateOfTheArt/always01_pub.v}
|
|
\end{minipage}
|
|
\hfill
|
|
\begin{minipage}{7.7cm}
|
|
\lstinputlisting[frame=single,language=Verilog]{CHAPTER_StateOfTheArt/always02_pub.v}
|
|
\end{minipage}
|
|
\caption{1st and 2nd Verilog always examples}
|
|
\label{fig:StateOfTheArt_always12}
|
|
\end{figure}
|
|
|
|
\begin{figure}[!]
|
|
\lstinputlisting[numbers=left,frame=single,language=Verilog]{CHAPTER_StateOfTheArt/always03.v}
|
|
\caption{3rd Verilog always example}
|
|
\label{fig:StateOfTheArt_always3}
|
|
\end{figure}
|
|
|
|
\section{Always blocks and blocking vs.~nonblocking assignments}
|
|
\label{sec:blocking_nonblocking}
|
|
|
|
The ``always''-block is one of the most fundamental non-trivial Verilog
|
|
language features. It can be used to model a combinatorial path (with optional
|
|
registers on the outputs) in a way that mimics a regular programming language.
|
|
|
|
Within an always block, if- and case-statements can be used to model multiplexers.
|
|
Blocking assignments ($=$) and nonblocking assignments ($<=$) are used to populate the
|
|
leaf-nodes of these multiplexer trees. Unassigned leaf-nodes default to feedback
|
|
paths that cause the output register to hold the previous value. More advanced
|
|
synthesis tools often convert these feedback paths to register enable signals or
|
|
even generate circuits with clock gating.
|
|
|
|
Registers assigned with nonblocking assignments ($<=$) behave differently from
|
|
variables in regular programming languages: In a simulation they are not
|
|
updated immediately after being assigned. Instead the right-hand sides are
|
|
evaluated and the results stored in temporary memory locations. After all
|
|
pending updates have been prepared in this way they are executed, thus yielding
|
|
semi-parallel execution of all nonblocking assignments.
|
|
|
|
For synthesis this means that every occurrence of that register in an expression
|
|
addresses the output port of the corresponding register regardless of the question whether the register
|
|
has been assigned a new value in an earlier command in the same always block.
|
|
Therefore with nonblocking assignments the order of the assignments has no effect
|
|
on the resulting circuit as long as the left-hand sides of the assignments are
|
|
unique.
|
|
|
|
The three example codes in Fig.~\ref{fig:StateOfTheArt_always12} and
|
|
Fig.~\ref{fig:StateOfTheArt_always3} use all these features and can thus be used
|
|
to test the synthesis tools capabilities to synthesize always blocks correctly.
|
|
|
|
The first example is only using the most fundamental Verilog features. All
|
|
tools under test were able to successfully synthesize this design.
|
|
|
|
\begin{figure}[b!]
|
|
\lstinputlisting[numbers=left,frame=single,language=Verilog]{CHAPTER_StateOfTheArt/arrays01.v}
|
|
\caption{Verilog array example}
|
|
\label{fig:StateOfTheArt_arrays}
|
|
\end{figure}
|
|
|
|
The 2nd example is functionally identical to the 1st one but is using an
|
|
if-statement inside the always block. Odin-II fails to synthesize it and
|
|
instead produces the following error message:
|
|
|
|
\begin{verbatim}
|
|
ERROR: (File: always02.v) (Line number: 13)
|
|
You've defined the driver "count~0" twice
|
|
\end{verbatim}
|
|
|
|
Vl2mv does not produce an error message but outputs an invalid synthesis result
|
|
that is not using the reset input at all.
|
|
|
|
Icarus Verilog also doesn't produce an error message but generates an invalid output
|
|
for this 2nd example. The code generated by Icarus Verilog only implements the reset
|
|
path for the count register, effectively setting the output to constant 0.
|
|
|
|
So of all tools under test only HANA was able to create correct synthesis results
|
|
for the 2nd example.
|
|
|
|
The 3rd example is using blocking and nonblocking assignments and many if statements.
|
|
Odin also fails to synthesize this example:
|
|
|
|
\begin{verbatim}
|
|
ERROR: (File: always03.v) (Line number: 8)
|
|
ODIN doesn't handle blocking statements in Sequential blocks
|
|
\end{verbatim}
|
|
|
|
HANA, Icarus Verilog and vl2mv create invalid synthesis results for the 3rd example.
|
|
|
|
So unfortunately none of the tools under test provide a complete and correct
|
|
implementation of blocking and nonblocking assignments.
|
|
|
|
\section{Arrays for memory modelling}
|
|
|
|
Verilog arrays are part of the synthesizeable subset of Verilog and are
|
|
commonly used to model addressable memory. The Verilog code in
|
|
Fig.~\ref{fig:StateOfTheArt_arrays} demonstrates this by implementing a single
|
|
port memory.
|
|
|
|
For this design HANA, vl2m and ODIN-II generate error messages indicating that
|
|
arrays are not supported.
|
|
|
|
\begin{figure}[t!]
|
|
\lstinputlisting[numbers=left,frame=single,language=Verilog]{CHAPTER_StateOfTheArt/forgen01.v}
|
|
\caption{Verilog for loop example}
|
|
\label{fig:StateOfTheArt_for}
|
|
\end{figure}
|
|
|
|
Icarus Verilog produces an invalid output that is using the address only for
|
|
reads. Instead of using the address input for writes, the generated design
|
|
simply loads the data to all memory locations whenever the write-enable input
|
|
is active, effectively turning the design into a single 4-bit D-Flip-Flop with
|
|
enable input.
|
|
|
|
As all tools under test already fail this simple test, there is nothing to gain
|
|
by continuing tests on this aspect of Verilog synthesis such as synthesis of dual port
|
|
memories, correct handling of write collisions, and so forth.
|
|
|
|
\begin{figure}[t!]
|
|
\lstinputlisting[numbers=left,frame=single,language=Verilog]{CHAPTER_StateOfTheArt/forgen02.v}
|
|
\caption{Verilog generate example}
|
|
\label{fig:StateOfTheArt_gen}
|
|
\end{figure}
|
|
|
|
\section{For-loops and generate blocks}
|
|
|
|
For-loops and generate blocks are more advanced Verilog features. These features
|
|
allow the circuit designer to add program code to her design that is evaluated
|
|
during synthesis to generate (parts of) the circuits description; something that
|
|
could only be done using a code generator otherwise.
|
|
|
|
For-loops are only allowed in synthesizeable Verilog if they can be completely
|
|
unrolled. Then they can be a powerful tool to generate array logic or static
|
|
lookup tables. The code in Fig.~\ref{fig:StateOfTheArt_for} generates a circuit that
|
|
tests a 5 bit value for being a prime number using a static lookup table.
|
|
|
|
Generate blocks can be used to model array logic in complex parametric designs. The
|
|
code in Fig.~\ref{fig:StateOfTheArt_gen} implements a ripple-carry adder with
|
|
parametric width from simple assign-statements and logic operations using a Verilog
|
|
generate block.
|
|
|
|
All tools under test failed to synthesize both test cases. HANA creates invalid
|
|
output in both cases. Icarus Verilog creates invalid output for the first
|
|
test and fails with an error for the second case. The other two tools fail with
|
|
error messages for both tests.
|
|
|
|
\section{Extensibility}
|
|
|
|
This section briefly discusses the extensibility of the tools under test and
|
|
their internal data- and control-flow. As all tools under test already failed
|
|
to synthesize simple Verilog always-blocks correctly, not much resources have
|
|
been spent on evaluating the extensibility of these tools and therefore only a
|
|
very brief discussion of the topic is provided here.
|
|
|
|
HANA synthesizes for a built-in library of standard cells using two passes over
|
|
an AST representation of the Verilog input. This approach executes fast but
|
|
limits the extensibility as everything happens in only two comparable complex
|
|
AST walks and there is no universal intermediate representation that is flexible
|
|
enough to be used in arbitrary optimizations.
|
|
|
|
Odin-II and vl2m are both front ends to existing synthesis flows. As such they
|
|
only try to quickly convert the Verilog input into the internal representation
|
|
of their respective flows (BLIF). So extensibility is less of an issue here as
|
|
potential extensions would likely be implemented in other components of the
|
|
flow.
|
|
|
|
Icarus Verilog is clearly designed to be a simulation tool rather than a
|
|
synthesis tool. The synthesis part of Icarus Verilog is an ad-hoc add-on to
|
|
Icarus Verilog that aims at converting an internal representation that is meant
|
|
for generation of a virtual machine based simulation code to netlists.
|
|
|
|
\section{Summary and Outlook}
|
|
|
|
Table~\ref{tab:StateOfTheArt_sum} summarizes the tests performed. Clearly none
|
|
of the tools under test make a serious attempt at providing a feature-complete
|
|
implementation of Verilog. It can be argued that Odin-II performed best in the
|
|
test as it never generated incorrect code but instead produced error messages
|
|
indicating that unsupported Verilog features where used in the Verilog input.
|
|
|
|
In conclusion, to the best knowledge of the author, there is no FOSS Verilog
|
|
synthesis tool other than Yosys that is anywhere near feature completeness and
|
|
therefore there is no other candidate for a generic Verilog front end and/or
|
|
synthesis framework to be used as a basis for custom synthesis tools.
|
|
|
|
Yosys could also replace vl2m and/or Odin-II in their respective flows or
|
|
function as a pre-compiler that can translate full-featured Verilog code to the
|
|
simple subset of Verilog that is understood by vl2m and Odin-II.
|
|
|
|
Yosys is designed for extensibility. It can be used as-is to synthesize Verilog
|
|
code to netlists, but its main purpose is to be used as basis for custom tools.
|
|
Yosys is structured in a language dependent Verilog front end and language
|
|
independent synthesis code (which is in itself structured in independent
|
|
passes). This architecture will simplify implementing additional HDL front
|
|
ends and/or additional synthesis passes.
|
|
|
|
Chapter~\ref{chapter:eval} contains a more detailed evaluation of Yosys using real-world
|
|
designs that are far out of reach for any of the other tools discussed in this appendix.
|
|
|
|
\vskip2cm
|
|
\begin{table}[h]
|
|
% yosys hana vis icarus odin
|
|
% always01 ok ok ok ok ok
|
|
% always02 ok ok failed failed error
|
|
% always03 ok failed failed missing error
|
|
% arrays01 ok error error failed error
|
|
% forgen01 ok failed error failed error
|
|
% forgen02 ok failed error error error
|
|
\def\ok{\ding{52}}
|
|
\def\error{\ding{56}}
|
|
\def\failed{$\skull$}
|
|
\def\missing{$\skull$}
|
|
\rowcolors{2}{gray!25}{white}
|
|
\centerline{
|
|
\begin{tabular}{|l|cccc|c|}
|
|
\hline
|
|
& \bf HANA & \bf VIS / vl2m & \bf Icarus Verilog & \bf Odin-II & \bf Yosys \\
|
|
\hline
|
|
\tt always01 & \ok & \ok & \ok & \ok & \ok \\
|
|
\tt always02 & \ok & \failed & \failed & \error & \ok \\
|
|
\tt always03 & \failed & \failed & \missing & \error & \ok \\
|
|
\tt arrays01 & \error & \error & \failed & \error & \ok \\
|
|
\tt forgen01 & \failed & \error & \failed & \error & \ok \\
|
|
\tt forgen02 & \failed & \error & \error & \error & \ok \\
|
|
\hline
|
|
\end{tabular}
|
|
}
|
|
\centerline{
|
|
\ding{52} \dots passed \hskip2em
|
|
\ding{56} \dots produced error \hskip2em
|
|
$\skull$ \dots incorrect output
|
|
}
|
|
\caption{Summary of all test results}
|
|
\label{tab:StateOfTheArt_sum}
|
|
\end{table}
|
|
|