mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-27 10:55:51 +00:00
parent
853f4bb3c6
commit
a14dec79eb
57 changed files with 7792 additions and 2 deletions
410
docs/source/appendix/CHAPTER_StateOfTheArt.rst
Normal file
410
docs/source/appendix/CHAPTER_StateOfTheArt.rst
Normal file
|
@ -0,0 +1,410 @@
|
|||
.. _chapter:sota:
|
||||
|
||||
Evaluation of other OSS Verilog Synthesis Tools
|
||||
===============================================
|
||||
|
||||
In this appendix [1]_ the existing FOSS Verilog synthesis tools [2]_ 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:
|
||||
|
||||
- Icarus Verilog [3]_
|
||||
|
||||
- Verilog-to-Routing (VTR) / Odin-II
|
||||
:cite:p:`vtr2012}`:raw-latex:`\cite{Odin`
|
||||
|
||||
- HDL Analyzer and Netlist Architect (HANA)
|
||||
|
||||
- Verilog front-end to VIS (vl2mv) :cite:p:`Cheng93vl2mv:a`
|
||||
|
||||
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 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 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.
|
||||
|
||||
.. code:: verilog
|
||||
:number-lines:
|
||||
|
||||
module uut_always01(clock,
|
||||
reset, count);
|
||||
|
||||
input clock, reset;
|
||||
output [3:0] count;
|
||||
reg [3:0] count;
|
||||
|
||||
always @(posedge clock)
|
||||
count <= reset ?
|
||||
0 : count + 1;
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
.. code:: verilog
|
||||
|
||||
module uut_always02(clock,
|
||||
reset, count);
|
||||
|
||||
input clock, reset;
|
||||
output [3:0] count;
|
||||
reg [3:0] count;
|
||||
|
||||
always @(posedge clock) begin
|
||||
count <= count + 1;
|
||||
if (reset)
|
||||
count <= 0;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
[fig:StateOfTheArt_always12]
|
||||
|
||||
.. code:: verilog
|
||||
:number-lines:
|
||||
|
||||
module uut_always03(clock, in1, in2, in3, in4, in5, in6, in7,
|
||||
out1, out2, out3);
|
||||
|
||||
input clock, in1, in2, in3, in4, in5, in6, in7;
|
||||
output out1, out2, out3;
|
||||
reg out1, out2, out3;
|
||||
|
||||
always @(posedge clock) begin
|
||||
out1 = in1;
|
||||
if (in2)
|
||||
out1 = !out1;
|
||||
out2 <= out1;
|
||||
if (in3)
|
||||
out2 <= out2;
|
||||
if (in4)
|
||||
if (in5)
|
||||
out3 <= in6;
|
||||
else
|
||||
out3 <= in7;
|
||||
out1 = out1 ^ out2;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
[fig:StateOfTheArt_always3]
|
||||
|
||||
.. _sec:blocking_nonblocking:
|
||||
|
||||
Always blocks and blocking vs. nonblocking assignments
|
||||
------------------------------------------------------
|
||||
|
||||
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 (:math:`=`) and nonblocking
|
||||
assignments (:math:`<=`) 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 (:math:`<=`) 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
|
||||
:numref:`Fig. %s <fig:StateOfTheArt_always12>`
|
||||
and :numref:`Fig. %s <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.
|
||||
|
||||
.. code:: verilog
|
||||
:number-lines:
|
||||
|
||||
module uut_arrays01(clock, we, addr, wr_data, rd_data);
|
||||
|
||||
input clock, we;
|
||||
input [3:0] addr, wr_data;
|
||||
output [3:0] rd_data;
|
||||
reg [3:0] rd_data;
|
||||
|
||||
reg [3:0] memory [15:0];
|
||||
|
||||
always @(posedge clock) begin
|
||||
if (we)
|
||||
memory[addr] <= wr_data;
|
||||
rd_data <= memory[addr];
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
[fig:StateOfTheArt_arrays]
|
||||
|
||||
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:
|
||||
|
||||
::
|
||||
|
||||
ERROR: (File: always02.v) (Line number: 13)
|
||||
You've defined the driver "count~0" twice
|
||||
|
||||
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:
|
||||
|
||||
::
|
||||
|
||||
ERROR: (File: always03.v) (Line number: 8)
|
||||
ODIN doesn't handle blocking statements in Sequential blocks
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
:numref:`Fig. %s <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.
|
||||
|
||||
.. code:: verilog
|
||||
:number-lines:
|
||||
|
||||
module uut_forgen01(a, y);
|
||||
|
||||
input [4:0] a;
|
||||
output y;
|
||||
|
||||
integer i, j;
|
||||
reg [31:0] lut;
|
||||
|
||||
initial begin
|
||||
for (i = 0; i < 32; i = i+1) begin
|
||||
lut[i] = i > 1;
|
||||
for (j = 2; j*j <= i; j = j+1)
|
||||
if (i % j == 0)
|
||||
lut[i] = 0;
|
||||
end
|
||||
end
|
||||
|
||||
assign y = lut[a];
|
||||
|
||||
endmodule
|
||||
|
||||
[fig:StateOfTheArt_for]
|
||||
|
||||
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.
|
||||
|
||||
.. code:: verilog
|
||||
:number-lines:
|
||||
|
||||
module uut_forgen02(a, b, cin, y, cout);
|
||||
|
||||
parameter WIDTH = 8;
|
||||
|
||||
input [WIDTH-1:0] a, b;
|
||||
input cin;
|
||||
|
||||
output [WIDTH-1:0] y;
|
||||
output cout;
|
||||
|
||||
genvar i;
|
||||
wire [WIDTH-1:0] carry;
|
||||
|
||||
generate
|
||||
for (i = 0; i < WIDTH; i=i+1) begin:adder
|
||||
wire [2:0] D;
|
||||
assign D[1:0] = { a[i], b[i] };
|
||||
if (i == 0) begin:chain
|
||||
assign D[2] = cin;
|
||||
end else begin:chain
|
||||
assign D[2] = carry[i-1];
|
||||
end
|
||||
assign y[i] = ^D;
|
||||
assign carry[i] = &D[1:0] | (^D[1:0] & D[2]);
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign cout = carry[WIDTH-1];
|
||||
|
||||
endmodule
|
||||
|
||||
[fig:StateOfTheArt_gen]
|
||||
|
||||
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
|
||||
:numref:`Fig. %s <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
|
||||
:numref:`Fig. %s <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.
|
||||
|
||||
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.
|
||||
|
||||
Summary and Outlook
|
||||
-------------------
|
||||
|
||||
Table \ :numref:`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 \ :numref:`<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.
|
||||
|
||||
…passed 2em …produced error 2em :math:`\skull` …incorrect output
|
||||
|
||||
[tab:StateOfTheArt_sum]
|
||||
|
||||
.. [1]
|
||||
This appendix is an updated version of an unpublished student
|
||||
research paper. :cite:p:`VerilogFossEval`
|
||||
|
||||
.. [2]
|
||||
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.
|
||||
|
||||
.. [3]
|
||||
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.)
|
Loading…
Add table
Add a link
Reference in a new issue