summaryrefslogtreecommitdiff log msg author committer range
blob: 2d0c77a01a5f8e6dbb3cb06f4d1b10c3c4815a35 (plain)
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289  .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */\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}