0% found this document useful (0 votes)
255 views73 pages

Yosys

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
255 views73 pages

Yosys

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 73

1 What is Yosys 3

1.1 What you can do with Yosys........................................................................3


1.1.1 Typical applications for Yosys............................................................4
1.1.2 Things you can’t do............................................................................4
1.2 The Yosys family..........................................................................................4
1.3 The original thesis abstract............................................................................4
1.3.1 Benefits of open source HDL synthesis..............................................5
1.3.2 History of Yosys..................................................................................6

2 Getting started with Yosys 7


2.1 Installation......................................................................................................7
2.1.1 CAD suite(s).......................................................................................7
2.1.2 Building from source...........................................................................7
2.1.3 Source tree and build system.............................................................10
2.2 Synthesis starter...........................................................................................11
2.2.1 Demo design......................................................................................11
2.2.2 Loading the design............................................................................13
2.2.3 Elaboration.........................................................................................13
2.2.4 Flattening............................................................................................19
2.2.5 The coarse-grain representation.........................................................20
2.2.6 Hardware mapping.............................................................................27
2.2.7 Final steps..........................................................................................34
2.3 Scripting in Yosys.......................................................................................36
2.3.1 Script parsing.....................................................................................37
2.3.2 The synthesis starter script................................................................37

CONTENTS 1
YosysHQ Yosys, Version 0.48-dev

Note

This documentation recently went through a major restructure. If you’re looking for something from the
previous version and can’t find it here, please let us know. Documentation from before the restructure can still
be found by switching to version 0.36 or earlier. Note that the previous theme does not include a version
switcher.

Yosys is an open source framework for RTL synthesis. To learn more about Yosys, see What
is Yosys. For a quick guide on how to get started using Yosys, check out Getting started with
Yosys. For the complete list of commands available, go to commandindex.

CONTENTS 1
CHAPTER
ONE

WHAT IS YOSYS

Yosys began as a BSc thesis project by Claire Wolf intended to support synthesis for a CGRA
(coarse-grained reconfigurable architecture). It then expanded into more general infrastructure
for research on synthesis.
Modern Yosys has full support for the synthesizable subset of Verilog-2005 and has been
described as “the GCC of hardware synthesis.” Freely available and open source, Yosys finds
use across hobbyist and commercial applications as well as academic.

Note

Yosys is released under the ISC License:

A permissive license lets people do anything with your code with proper attribution and without warranty. The
ISC license is functionally equivalent to the BSD 2-Clause and MIT licenses, removing some language that is no
longer necessary.

Together with the place and route tool nextpnr, Yosys can be used to program some FPGAs
with a fully end-to-end open source flow (Lattice iCE40 and ECP5). It also does the synthesis
portion for the OpenLane flow, targeting the SkyWater 130nm open source PDK for fully open
source ASIC design. Yosys can also do formal verification with backends for solver formats like
SMT2.
Yosys, and the accompanying Open Source EDA ecosystem, is currently maintained by Yosys
Headquarters, with many of the core developers employed by YosysHQ GmbH. A commercial
extension, Tabby CAD Suite, includes the Verific frontend for industry-grade SystemVerilog
and VHDL support, formal verification with SVA, and formal apps.

CONTENTS 1
1.1 What you can do with Yosys
• Read and process (most of) modern Verilog-2005 code
• Perform all kinds of operations on netlist (RTL, Logic, Gate)
• Perform logic optimizations and gate mapping with ABC

1.1.1 Typical applications for Yosys


• Synthesis of final production designs
• Pre-production synthesis (trial runs before investing in other tools)
• Conversion of full-featured Verilog to simple Verilog
• Conversion of Verilog to other formats (BLIF, BTOR, etc)
• Demonstrating synthesis algorithms (e.g. for educational purposes)
• Framework for experimenting with new algorithms
• Framework for building custom flows (Not limited to synthesis but also formal
verification, reverse engineering, . . . )

1.1.2 Things you can’t do


• Process high-level languages such as C/C++/SystemC
• Create physical layouts (place&route)
– Check out nextpnr for that
• Rely on built-in syntax checking
– Use an external tool like verilator instead

1.2 The Yosys family


As mentioned above, YosysHQ maintains not just Yosys but an entire family of tools built
around it. In no particular order:
SBY for formal verification
Yosys provides input parsing and conversion to the formats used by the solver engines.
Yosys also provides a unified witness framework for providing cover traces and counter
examples for engines which don’t natively support this. SBY source | SBY docs
EQY for equivalence checking
In addition to input parsing and preparation, Yosys provides the plugin support enabling
EQY to operate on designs directly. EQY source | EQY docs
MCY for mutation coverage
Yosys is used to read the source design, generate a list of possible mutations to maximise
design coverage, and then perform selected mutations. MCY source | MCY docs
SCY for deep formal traces
Since SCY generates and runs SBY, Yosys provides the same utility for SCY as it does for
SBY. Yosys additionally provides the trace concatenation needed for outputting the deep
traces. SCY source
CONTENTS 1
1.3 The original thesis abstract
The first version of the Yosys documentation was published as a bachelor thesis at the Vienna
University of Technology [Wol13].
Abstract
Most of today’s digital design is done in HDL code (mostly Verilog or VHDL)
and with the help of HDL synthesis tools.

CONTENTS 1
YosysHQ Yosys, Version 0.48-dev

In special cases such as synthesis for coarse-grain cell libraries or when testing
new synthesis algorithms it might be necessary to write a custom HDL synthesis
tool or add new features to an existing one. In these cases the availability of a
Free and Open Source (FOSS) synthesis tool that can be used as basis for custom
tools would be helpful.
In the absence of such a tool, the Yosys Open SYnthesis Suite (Yosys) was
developed. This document covers the design and implementation of this tool.
At the moment the main focus of Yosys lies on the high-level aspects of
digital synthesis. The pre-existing FOSS logic-synthesis tool ABC is used by
Yosys to perform advanced gate-level optimizations.
An evaluation of Yosys based on real-world designs is included. It is shown that
Yosys can be used as-is to synthesize such designs. The results produced by
Yosys in this tests where successfully verified using formal verification and are
comparable in quality to the results produced by a commercial synthesis tool.
Yosys is a Verilog HDL synthesis tool. This means that it takes a behavioural design
description as input and generates an RTL, logical gate or physical gate level description of the
design as output. Yosys’ main strengths are behavioural and RTL synthesis. A wide range of
commands (synthesis passes) exist within Yosys that can be used to perform a wide range of
synthesis tasks within the domain of behavioural, rtl and logic synthesis. Yosys is designed to be
extensible and therefore is a good basis for implementing custom synthesis tools for specialised
tasks.

System Level

System Design
High Level
High Level Synthesis (HLS)

Behavioral Level Behavioral Synthesis

Register-Transfer Level (RTL) RTL Synthesis Yosys

Logical Gate Level Logic Synthesis

Physical Gate Level Cell Library

Switch Level

Fig. 1.1: Where Yosys exists in the layers of abstraction

1.3.1 Benefits of open source HDL synthesis


• Cost (also applies to free as in free beer solutions):

1.3. The original thesis abstract 5


Today the cost for a mask set in 180nm technology is far less than the cost for the design
tools needed to design the mask layouts. Open Source ASIC flows are an important enabler
for ASIC-level Open Source Hardware.
• Availability and Reproducibility:
If you are a researcher who is publishing, you want to use tools that everyone else can
also use. Even if most universities have access to all major commercial tools, you usually
do not have easy access to

1.3. The original thesis abstract 5


the version that was used in a research project a couple of years ago. With Open Source
tools you can even release the source code of the tool you have used alongside your data.
• Framework:
Yosys is not only a tool. It is a framework that can be used as basis for other developments,
so researchers and hackers alike do not need to re-invent the basic functionality.
Extensibility was one of Yosys’ design goals.
• All-in-one:
Because of the framework characteristics of Yosys, an increasing number of features
become available in one tool. Yosys not only can be used for circuit synthesis but also for
formal equivalence checking, SAT solving, and for circuit analysis, to name just a few other
application domains. With proprietary software one needs to learn a new tool for each of
these applications.
• Educational Tool:
Proprietary synthesis tools are at times very secretive about their inner workings. They
often are black boxes. Yosys is very open about its internals and it is easy to observe the
different steps of synthesis.

1.3.2 History of Yosys


A Hardware Description Language (HDL) is a computer language used to describe circuits. A
HDL synthesis tool is a computer program that takes a formal description of a circuit written in
an HDL as input and generates a netlist that implements the given circuit as output.
Currently the most widely used and supported HDLs for digital circuits are Verilog [A+02,
A+06] and VHDL (VHSIC HDL, where VHSIC is an acronym for Very-High-Speed
Integrated Circuits) [A+04, A+09]. Both HDLs are used for test and verification purposes as
well as logic synthesis, resulting in a set of synthesizable and a set of non-synthesizable language
features. In this document we only look at the synthesizable subset of the language features.
In recent work on heterogeneous coarse-grain reconfigurable logic [WGS+12] the need for a
custom application-specific HDL synthesis tool emerged. It was soon realised that a
synthesis tool that under- stood Verilog or VHDL would be preferred over a synthesis tool for a
custom HDL. Given an existing Verilog or VHDL front end, the work for writing the necessary
additional features and integrating them in an existing tool can be estimated to be about the
same as writing a new tool with support for a minimalistic custom HDL.
The proposed custom HDL synthesis tool should be licensed under a Free and Open Source
Software (FOSS) licence. So an existing FOSS Verilog or VHDL synthesis tool would have
been needed as basis to build upon. The main advantages of choosing Verilog or VHDL is the
ability to synthesize existing HDL code and to mitigate the requirement for circuit-designers to
learn a new language. In order to take full advantage of any existing FOSS Verilog or VHDL
tool, such a tool would have to provide a feature-complete implementation of the synthesizable
HDL subset.
Basic RTL synthesis is a well understood field [HS96]. Lexing, parsing and processing of
computer languages [ASU86] is a thoroughly researched field. All the information required to
write such tools has been openly available for a long time, and it is therefore likely that a FOSS
HDL synthesis tool with a feature-complete Verilog or VHDL front end must exist which can
1.3. The original thesis abstract 5
be used as a basis for a custom RTL synthesis tool.
Due to the author’s preference for Verilog over VHDL it was decided early on to go for
Verilog instead of VHDL1. So the existing FOSS Verilog synthesis tools were evaluated. The
results of this evaluation are utterly devastating. Therefore a completely new Verilog synthesis
tool was implemented and is recommended as basis for custom synthesis tools. This is the tool
that is discussed in this document.

1 A quick investigation into FOSS VHDL tools yielded similar grim results for FOSS VHDL
synthesis tools.

1.3. The original thesis abstract 5


CHAPTER
TWO

GETTING STARTED WITH YOSYS

This section covers how to get started with Yosys, from installation to a guided walkthrough of
synthesizing a design for hardware, and finishing with an introduction to writing re-usable
Yosys scripts.

2.1 Installation
This document will guide you through the process of installing Yosys.

2.1.1 CAD suite(s)


Yosys is part of the Tabby CAD Suite and the OSS CAD Suite! The easiest way to use
yosys is to install the binary software suite, which contains all required dependencies and
related tools.
• Contact YosysHQ for a Tabby CAD Suite Evaluation License and download link
• OR go to https://github.com/YosysHQ/oss-cad-suite-build/releases to download the free
OSS CAD Suite
• Follow the Install Instructions on GitHub
Make sure to get a Tabby CAD Suite Evaluation License if you need features such as industry-
grade Sys- temVerilog and VHDL parsers!
For more information about the difference between Tabby CAD Suite and the OSS CAD
Suite, please visit https://www.yosyshq.com/tabby-cad-datasheet
Many Linux distributions also provide Yosys binaries, some more up to date than others. Check
with your package manager!

Targeted architectures
The OSS CAD Suite releases nightly builds for the following architectures:

2.1.2 Building from source


The Yosys source files can be obtained from the YosysHQ/Yosys git repository. ABC and some
of the other libraries used are included as git submodules. To clone these submodules at the same
time, use e.g.:

7
git clone --recurse-submodules https://github.com/YosysHQ/yosys.git # ..or..
git clone https://github.com/YosysHQ/yosys.git
cd yosys

git submodule update --init --recursive

7
YosysHQ Yosys, Version 0.48-dev

Note

As of Yosys v0.47, releases include a yosys.tar.gz file which includes all source code and all sub-modules in a
single archive. This can be used as an alternative which does not rely on git.

Supported platforms
The following platforms are supported and regularly tested:
• Linux
• macOS
Other platforms which may work, but instructions may not be up to date and are not regularly
tested:
• FreeBSD
• WSL
• Windows with (e.g.) Cygwin

Build prerequisites
A C++ compiler with C++17 support is required as well as some standard tools such as
GNU Flex, GNU Bison, Make and Python. Some additional tools: readline, libffi, Tcl and zlib;
are optional but enabled by default (see ENABLE_* settings in Makefile). Graphviz and Xdot
are used by the show command to display schematics.
Installing all prerequisites for Ubuntu 20.04:
sudo apt-get install gperf build-essential bison flex \
libreadline-dev gawk tcl-dev libffi-dev git graphviz \
xdot pkg-config python3 libboost-system-dev \

libboost-python-dev libboost-filesystem-dev zlib1g-dev

Installing all prerequisites for macOS 13 (with Homebrew):


brew tap Homebrew/bundle && brew bundle

or MacPorts:
sudo port install bison flex readline gawk libffi graphviz \
pkgconfig python311 boost zlib tcl

On FreeBSD use the following command to install all prerequisites:


pkg install bison flex readline gawk libffi graphviz \
pkgconf python311 tcl-wrapper boost-libs

Note

On FreeBSD system use gmake instead of make. To run tests use: MAKE=gmake CXX=cxx CC=cc gmake 7
test
YosysHQ Yosys, Version 0.48-dev

For Cygwin use the following command to install all prerequisites, or select these additional
packages:

7
YosysHQ Yosys, Version 0.48-dev

setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-

˓→devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel

Warning
As of this writing, Cygwin only supports up to Python 3.9.16 while the minimum required
version of Python is 3.11. This means that Cygwin is not compatible with many of the
Python-based frontends. While this does not currently prevent Yosys itself from working,
no guarantees are made for contin- ued support. It is instead recommended to use Windows
Subsystem for Linux (WSL) and follow the instructions for Ubuntu.

Build configuration
The Yosys build is based solely on Makefiles, and uses a number of variables which influence
the build process. The recommended method for configuring builds is with a Makefile.conf file
in the root yosys directory. The following commands will clean the directory and provide an
initial configuration file:
make config-clang # ..or..
make config-gcc

Check the root Makefile to see what other configuration targets are available. Other variables can
then be added to the Makefile.conf as needed, for example:
echo "ENABLE_ZLIB := 0" >> Makefile.conf

Using one of these targets will set the CONFIG variable to something other than none, and will
override the environment variable for CXX. To use a different compiler than the default when
building, use:
make CXX=$CXX # ..or..
make CXX="g++-
11"

Note

Setting the compiler in this way will prevent some other options such as ENABLE_CCACHE from working as
expected.

If you have clang, and (a compatible version of) ld.lld available in PATH, it’s recommended to
speed up incremental builds with lld by enabling LTO with ENABLE_LTO=1. On macOS,
LTO requires using clang from homebrew rather than clang from xcode. For example:
make ENABLE_LTO=1 CXX=$(brew --prefix)/opt/llvm/bin/clang++

By default, building (and installing) yosys will build (and install) ABC, using yosys-abc as the
executable name. To use an existing ABC executable instead, set the ABCEXTERNAL make
2.1. Installation 9
YosysHQ Yosys, Version 0.48-dev
variable to point to the desired executable.

Running the build system


From the root yosys directory, call the following commands:
make

sudo make install

2.1. Installation 9
YosysHQ Yosys, Version 0.48-dev

To use a separate (out-of-tree) build directory, provide a path to the Makefile.


mkdir build; cd build
make -f ../Makefile

Out-of-tree builds require a clean source tree.

See also
Refer to Testing Yosys for details on testing Yosys once compiled.

2.1.3 Source tree and build system


The Yosys source tree is organized into the following top-level directories:
backends/
This directory contains a subdirectory for each of the backend modules.
docs/
Contains the source for this documentation, including images and sample code.
examples/
Contains example code for using Yosys with some other tools including a demo of the
Yosys Python api, and synthesizing for various toolchains such as Intel and Anlogic.
frontends/
This directory contains a subdirectory for each of the frontend modules.
kernel/
This directory contains all the core functionality of Yosys. This includes the functions
and definitions for working with the RTLIL data structures (rtlil.h|cc ), the main()
function (driver.cc), the internal framework for generating log messages (log.h|cc ), the
internal framework for registering and calling passes (register.h|cc ), some core
commands that are not really passes (select.cc, show.cc,
. . . ) and a couple of other small utility libraries.
libs/
Libraries packaged with Yosys builds are contained in this folder. See Auxiliary libraries.
misc/
Other miscellany which doesn’t fit anywhere else.
passes/
This directory contains a subdirectory for each pass or group of passes. For example as
of this writ- ing the directory passes/hierarchy/ contains the code for three passes:
hierarchy , submod , and uniquify .
techlibs/
This directory contains simulation models and standard implementations for the cells from
the internal cell library.
tests/
This directory contains the suite of unit tests and regression tests used by Yosys. See Testing
Yosys.
The top-level Makefile includes frontends/* /Makefile.inc, passes/* /Makefile.inc and
backends/* / Makefile.inc. So when extending Yosys it is enough to create a new directory in
frontends/, passes/ or backends/ with your sources and a Makefile.inc. The Yosys kernel
2.1. Installation 9
YosysHQ Yosys, Version 0.48-dev
automatically detects all commands linked with Yosys. So it is not needed to add additional
commands to a central list of commands.

2.1. Installation 9
YosysHQ Yosys, Version 0.48-dev

Good starting points for reading example source code to learn how to write passes are
passes/opt/opt_dff. cc and passes/opt/opt_merge.cc.
Users of the Qt Creator IDE can generate a QT Creator project file using make qtcreator.
Users of the Eclipse IDE can use the “Makefile Project with Existing Code” project type in
the Eclipse “New Project” dialog (only available after the CDT plugin has been installed) to
create an Eclipse project in order to programming extensions to Yosys or just browse the Yosys
code base.

2.2 Synthesis starter


This page will be a guided walkthrough of the prepackaged iCE40 FPGA synthesis script -
synth_ice40 . We will take a simple design through each step, looking at the commands
being called and what they do to the design. While synth_ice40 is specific to the iCE40
platform, most of the operations we will be discussing are common across the majority of
FPGA synthesis scripts. Thus, this document will provide a good foundational understanding
of how synthesis in Yosys is performed, regardless of the actual architecture being used.

See also
Advanced usage docs for Synth commands

2.1.4 Demo design


First, let’s quickly look at the design we’ll be synthesizing:

Listing 2.1: fifo.v


1 // address generator/counter
module addr_gen

2 #( parameter MAX_DATA=256,
localparam AWIDTH = $clog2(MAX_DATA)
3 ) ( input en, clk, rst,
output reg [AWIDTH-1:0] addr
4 );

initial addr = 0;
5
// async reset

6 // increment address when enabled

always @(posedge clk or posedge rst)

7 if (rst)
addr <= 0;
8 else if (en) begin
if ({'0, addr} == MAX_DATA-1)
2.2. Synthesis starter 11
YosysHQ Yosys, Version 0.48-dev
9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25
(continues on next page)

2.2. Synthesis starter 12


YosysHQ Yosys, Version 0.48-dev

(continued from previous page)


26 localparam AWIDTH = $clog2(MAX_DATA)
27 ) ( input wen, ren, clk, rst,
28 input [7:0] wdata,
29 output reg [7:0] rdata,
30 output reg [AWIDTH:0] count
31 );
32 // fifo storage
33 // sync read before write
34 wire [AWIDTH-1:0] waddr, raddr;
35 reg [7:0] data [MAX_DATA-1:0];
36 always @(posedge clk) begin
37 if (wen)
38 data[waddr] <= wdata;
39 rdata <= data[raddr];
40 end // storage
41
42 // addr_gen for both write and read addresses
43 addr_gen #(.MAX_DATA(MAX_DATA))
44 fifo_writer (
45 .en (wen),
46 .clk (clk),
47 .rst (rst),
48 .addr (waddr)
49 );
50
51 addr_gen #(.MAX_DATA(MAX_DATA))
52 fifo_reader (
53 .en (ren),
54 .clk (clk),
55 .rst (rst),
56 .addr (raddr)
57 );
58
59 // status signals

2.2. Synthesis starter 13


YosysHQ Yosys, Version 0.48-dev
60 initial count = 0;
61
62 always @(posedge clk or posedge rst) begin
63 if (rst)
64 count <= 0;
65 else if (wen && !ren)
66 count <= count + 1;
67 else if (ren && !wen)
68 count <= count - 1;
69 end
70
71 endmodule

While the open source read_verilog frontend generally does a pretty good job at processing
valid Verilog input, it does not provide very good error handling or reporting. Using an
external tool such as verilator before running Yosys is highly recommended. We can
quickly check the Verilog syntax of our design by calling verilator --lint-only fifo.v.

2.2. Synthesis starter 14


YosysHQ Yosys, Version 0.48-dev

2.1.5 Loading the design


Let’s load the design into Yosys. From the command line, we can call yosys fifo.v. This
will open an interactive Yosys shell session and immediately parse the code from fifo.v and
convert it into an Abstract Syntax Tree (AST). If you are interested in how this happens,
there is more information in the document,
The Verilog and AST frontends. For now, suffice it to say that we do this to simplify further
processing of the design. You should see something like the following:
$ yosys fifo.v

-- Parsing `fifo.v' using frontend ` -vlog2k' --

1. Executing Verilog-2005 frontend: fifo.v


Parsing Verilog input from `fifo.v' to AST representation.
Storing AST representation for module `$abstract\
addr_gen'. Storing AST representation for module
`$abstract\fifo'.

Successfully finished Verilog frontend.

See also
Advanced usage docs for Loading a design

2.1.6 Elaboration
Now that we are in the interactive shell, we can call Yosys commands directly. Our overall
goal is to call synth_ice40 -top fifo, but for now we can run each of the commands
individually for a better sense of how each part contributes to the flow. We will also start
with just a single module; addr_gen.
At the bottom of the help output for synth_ice40 is the complete list of commands called
by this script. Let’s start with the section labeled begin:

2.2. Synthesis starter 15


YosysHQ Yosys, Version 0.48-dev

Listing 2.2: begin section


read_verilog -D ICE40_HX -lib -specify +/ice40/cells_sim.v
hierarchy -check -top <top>
proc

read_verilog -D ICE40_HX -lib -specify +/ice40/cells_sim.v loads the iCE40 cell models
which al- lows us to include platform specific IP blocks in our design. PLLs are a common
example of this, where we might need to reference SB_PLL40_CORE directly rather than
being able to rely on mapping passes later. Since our simple design doesn’t use any of these IP
blocks, we can skip this command for now. Because these
cell models will also be needed once we start mapping to hardware we will still need to load them
later.

Note

+/ is a dynamic reference to the Yosys share directory. By default, this is /usr/local/share/yosys. If


using a locally built version of Yosys from the source directory, this will be the share folder in the same
directory.

The addr_gen module


Since we’re just getting started, let’s instead begin with hierarchy -top addr_gen. This
command declares that the top level module is addr_gen, and everything else can be discarded.
Listing 2.3: addr_gen module source
2 module addr_gen
#( parameter MAX_DATA=256,

3 localparam AWIDTH = $clog2(MAX_DATA)


) ( input en, clk, rst,
4 output reg [AWIDTH-1:0] addr
);
5
initial addr = 0;

// async reset
6
// increment address when enabled

7 always @(posedge clk or posedge rst)

if (rst)

8 addr <= 0;

2.2. Synthesis starter 16


YosysHQ Yosys, Version 0.48-dev
10

11

12

13

14

15

16

17

18

19

20

21

Note

hierarchy should always be the first command after the design has been read. By specifying the top
module, hierarchy will also set the (* top *) attribute on it. This is used by other commands that need
to know which module is the top.

2.2. Synthesis starter 17


YosysHQ Yosys, Version 0.48-dev

Listing 2.4: hierarchy -top addr_gen output


yosys> hierarchy -top addr_gen

2. Executing HIERARCHY pass (managing design hierarchy).

3. Executing AST frontend in derive mode using pre-parsed AST for module `\
addr_gen'. Generating RTLIL representation for module `\addr_gen'.

3.1. Analyzing design hierarchy..


Top module: \addr_gen

3.2. Analyzing design hierarchy..


Top module: \addr_gen
Removing unused module `$abstract\fifo'.
Removing unused module `$abstract\
addr_gen'. Removed 2 unused modules.

Our addr_gen circuit now looks like this:

A $2
Y
B $eq
0 -> 31:8

7:0 - 7:0

255
rst

clk

PROC $1
en
o.v:12.2-20
fif .6

PROC $4
addr
fo.v:0.0-0.
fi 0

A $3
Y 7:0 - 7:0
1
B $add

Fig. 2.1: addr_gen module after hierarchy


Simple operations like addr + 1 and addr == MAX_DATA-1 can be extracted from our always @
block in addr_gen module source. This gives us the highlighted $add and $eq cells we see.
But control logic (like the if .. else) and memory elements (like the addr <= 0) are not so
straightforward. These get put into “processes”, shown in the schematic as PROC. Note how the
2.2. Synthesis starter 18
YosysHQ Yosys, Version 0.48-dev
second line refers to the line numbers of the start/end of the corresponding always @ block. In
the case of an initial block, we instead see the PROC referring to line 0.

2.2. Synthesis starter 19


YosysHQ Yosys, Version 0.48-dev

To handle these, let us now introduce the next command: proc - translate processes to
netlists. proc is a macro command like synth_ice40 . Rather than modifying the design
directly, it instead calls a series of other commands. In the case of proc , these sub-commands
work to convert the behavioral logic of processes into multiplexers and registers. Let’s see
what happens when we run it. For now, we will call proc -noopt to prevent some automatic
optimizations which would normally happen.
clk

8'00000000 $1╲addr[7:0]
A $10 Y
rst

$0╲addr[7:0]

A
R $1
S
T 2
C
L $a
df Q
K f
A
D
A A

$3 A $2
Y Y $6 $8
B $add B $eq B Y B Y
addr $mux $mux
S S

7:0 - 7:0
1
8'00000000
0 -> 31:8

en
255

Fig. 2.2: addr_gen module after proc -noopt


There are now a few new cells from our always @, which have been highlighted. The if
statements are now modeled with $mux cells, while the register uses an $adff cell. If we
look at the terminal output we can also see all of the different proc_* commands being
called. We will look at each of these in more detail in Converting process blocks.
Notice how in the top left of addr_gen module after proc -noopt we have a floating wire,
generated from the initial assignment of 0 to the addr wire. However, this initial assignment
is not synthesizable, so this will need to be cleaned up before we can generate the physical
hardware. We can do this now by calling clean . We’re also going to call opt_expr now,
which would normally be called at the end of proc . We can call both commands at the
same time by separating them with a colon and space: opt_expr; clean.

rst

clk AR
$12
ST $ad
CL ff Q
K
D
A A
$6 Y $8 Y
B B
$mux $mux
S S
A $2 Y
B $eq

2.2. Synthesis starter 20


$add
8'00000000

8'11111111 en
YosysHQ Yosys, Version 0.48-dev

Fig. 2.3: addr_gen module after opt_expr; clean


You may also notice that the highlighted $eq cell input of 255 has changed to 8'11111111.
Constant values are presented in the format <bit_width>'<bits>, with 32-bit values instead using
the decimal number. This indicates that the constant input has been reduced from 32-bit wide
to 8-bit wide. This is a side-effect
of running opt_expr , which performs constant folding and simple expression rewriting. For
more on why this happens, refer to Optimization passes and the section on opt_expr .

Note

2.2. Synthesis starter 21


YosysHQ Yosys, Version 0.48-dev

clean - remove unused cells and wires can also be called with two semicolons after any
command, for example we could have called opt_expr;; instead of opt_expr; clean. You may notice some
scripts will end each line with ;;. It is beneficial to run clean before inspecting intermediate products to
remove disconnected parts of the circuit which have been left over, and in some cases can reduce the
processing

required in subsequent commands.

See also
Advanced usage docs for
• Converting process blocks
• Optimization passes

The full example


Let’s now go back and check on our full design by using hierarchy -check -top fifo. By
passing the
-check option there we are also telling the hierarchy command that if the design includes any
non-blackbox modules without an implementation it should return an error.
Note that if we tried to run this command now then we would get an error. This is because we
already removed all of the modules other than addr_gen. We could restart our shell session, but
instead let’s use two new commands:
• design - save, restore and reset current design, and
• read_verilog - read modules from Verilog file.

Listing 2.5: reloading fifo.v and running hierarchy -check


-top fifo
yosys> design -reset

yosys> read_verilog fifo.v

11. Executing Verilog-2005 frontend: fifo.v


Parsing Verilog input from `fifo.v' to AST representation.
Generating RTLIL representation for module `\addr_gen'.
Generating RTLIL representation for module `\fifo'.
Successfully finished Verilog frontend.

yosys> hierarchy -check -top fifo

12. Executing HIERARCHY pass (managing design hierarchy).

12.1. Analyzing design


hierarchy.. Top module: \fifo
Used module: \addr_gen
Parameter \MAX_DATA = 256

12.2. Executing AST frontend in derive mode using pre-parsed AST for module `\
addr_gen'. Parameter \MAX_DATA = 256
Generating RTLIL representation for module `$paramod\addr_gen\MAX_DATA=s32

˓→ '00000000000000000000000100000000'.

2.2. Synthesis starter 22


YosysHQ Yosys, Version 0.48-dev
(continues on next page)

2.2. Synthesis starter 23


YosysHQ Yosys, Version 0.48-dev

Parameter \MAX_DATA = 256

Found cached RTLIL representation for module `$paramod\addr_gen\MAX_DATA=s32

˓→ '00000000000000000000000100000000'.

12.3. Analyzing design


hierarchy.. Top module: \fifo
Used module: $paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000

12.4. Analyzing design


hierarchy.. Top module: \fifo
Used module: $paramod\addr_gen\MAX_DATA=s32'00000000000000000000000100000000
Removing unused module `\addr_gen'.

Removed 1 unused modules.


(continued from previous page)
Notice how this time we didn’t see any of those $abstract modules? That’s because when we ran
yosys fifo.v, the first command Yosys called was read_verilog -defer fifo.v. The -defer
option there tells read_verilog only read the abstract syntax tree and defer actual
compilation to a later hierarchy
command. This is useful in cases where the default parameters of modules yield invalid code
which is not synthesizable. This is why Yosys defers compilation automatically and is one of the
reasons why hierarchy should always be the first command after loading the design. If we know
that our design won’t run into this issue, we can skip the -defer.

Note

The number before a command’s output increments with each command run. Don’t worry if your numbers
don’t match ours! The output you are seeing comes from the same script that was used to generate the
images in this document, included in the source as fifo.ys. There are extra commands being run which
you don’t see, but feel free to try them yourself, or play around with different commands. You can always
start over with a clean slate by calling exit or hitting ctrl+d (i.e. EOF) and re-launching the Yosys interactive
terminal. ctrl+c (i.e. SIGINT) will also end the terminal session but will return an error code rather than
exiting gracefully.

We can also run proc now to finish off the full begin section. Because the design schematic is
quite large, we will be showing just the data path for the rdata output. If you would like to see
the entire design for yourself, you can do so with show - generate schematics using graphviz.
Note that the show command only works with a single module, so you may need to call it with
show fifo. Displaying schematics section in Scripting in Yosys has more on how to use show .

clk

rdata
raddr
CLK $60
clk Q
fifo_reader D $dff
en addr
rst $paramod╲addr_gen╲MAX_DATA=s32'00000000000000000000000100000000 1'x ADDR
rst $25
CLK DATA
$memrd
EN
1'x

2.2. Synthesis starter 24


YosysHQ Yosys, Version 0.48-dev

Fig. 2.4: rdata output after proc


The highlighted fifo_reader block contains an instance of the addr_gen module after proc -noopt
that we looked at earlier. Notice how the type is shown as $paramod\\addr_gen\\
MAX_DATA=s32'.... This is a “parametric module”: an instance of the addr_gen module with
the MAX_DATA parameter set to the given value.

2.2. Synthesis starter 25


YosysHQ Yosys, Version 0.48-dev

The other highlighted block is a $memrd cell. At this stage of synthesis we don’t yet know
what type of memory is going to be implemented, but we do know that rdata <= data[raddr];
could be implemented as a read from memory. Note that the $memrd cell here is
asynchronous, with both the clock and enable signal undefined; shown with the 1'x inputs.

See also
Advanced usage docs for Converting process blocks

2.1.7 Flattening
At this stage of a synthesis flow there are a few other commands we could run. In
synth_ice40 we get these:

Listing 2.6: flatten section


flatten
tribuf -logic
deminout

First off is flatten . Flattening the design like this can allow for optimizations between modules
which would otherwise be missed. Let’s run flatten;; on our design.

Listing 2.7: output of flatten;;

yosys> flatten

15. Executing FLATTEN pass (flatten design).

Deleting now unused module $paramod\addr_gen\MAX_DATA=s32

˓→ '00000000000000000000000100000000.
<suppressed ~2 debug messages>

yosys> clean

rst A
RS
T $6
C 6 Q fifo_reader.add
L $a
dff r
KD A $3 7:0 - 7:0 A
6
B $a Y
dd $55
1 A B $m Y
ux
$5 S
A$3
5 8'0000000 3 Y
B$m
clk $e Y 0 ux
8'11111111 q
B S

2.2. Synthesis starter 26


YosysHQ Yosys,
ren
Version 0.48-dev

ADDR CLK $60


$ Q
1'x $25 dff rdata
DATA D
CLK
1'x

Fig. 2.5: rdata output after flatten;;

The pieces have moved around a bit, but we can see addr_gen module after proc -noopt from
earlier has replaced the fifo_reader block in rdata output after proc. We can also see that the
addr output has been

2.2. Synthesis starter 27


YosysHQ Yosys, Version 0.48-dev

renamed to fifo_reader.addr and merged with the raddr wire feeding into the $memrd cell. This
wire merging happened during the call to clean which we can see in the output of flatten;;.

Note

flatten and clean would normally be combined into a single yosys> flatten;; output, but they
appear separately here as a side effect of using echo for generating the terminal style output.

Depending on the target architecture, this stage of synthesis might also see commands such as
tribuf with the -logic option and deminout . These remove tristate and inout constructs
respectively, replacing them with logic suitable for mapping to an FPGA. Since we do not
have any such constructs in our example running these commands does not change our
design.

2.1.8 The coarse-grain representation


At this stage, the design is in coarse-grain representation. It still looks recognizable, and
cells are word- level operators with parametrizable width. This is the stage of synthesis where
we do things like const propagation, expression rewriting, and trimming unused parts of wires.
This is also where we convert our FSMs and hard blocks like DSPs or memories. Such elements
have to be inferred from patterns in the design and there are special passes for each. Detection of
these patterns can also be affected by optimizations and other transformations done previously.

Note

While the iCE40 flow had a flatten section and put proc in the begin section, some synthesis scripts will
instead include these in this section.

Part 1
In the iCE40 flow, we start with the following commands:

Listing 2.8: coarse section (part 1)


opt_expr
opt_clean
check

opt -nodffe -nosdff


fsm

We’ve already come across opt_expr , and opt_clean is the same as clean but with more
verbose output. The check pass identifies a few obvious problems which will cause errors
later. Calling it here lets us fail faster rather than wasting time on something we know is
impossible.
Next up is opt -nodffe -nosdff performing a set of simple optimizations on the design. This
command also ensures that only a specific subset of FF types are included, in preparation for
the next command: fsm
2.2. Synthesis starter 28
YosysHQ Yosys, Version 0.48-dev
- extract and optimize finite state machines. Both opt and fsm are macro commands which are
explored in more detail in Optimization passes and FSM handling respectively.
Up until now, the data path for rdata has remained the same since rdata output after
flatten;;. However the next call to opt does cause a change. Specifically, the call to opt_dff
without the -nodffe -nosdff options is able to fold one of the $mux cells into the $adff to
form an $adffe cell; highlighted below:

2.2. Synthesis starter 29


YosysHQ Yosys, Version 0.48-dev

Listing 2.9: output of opt_dff

yosys> opt_dff

17. Executing OPT_DFF pass (perform DFF optimizations).


Adding EN signal on $procdff$59 ($adff) from module fifo (D = $0\count[8:0], Q = \count).
Adding EN signal on $flatten\fifo_writer.$procdff$66 ($adff) from module fifo (D =
˓→$flatten\fifo_writer.$procmux$53_Y, Q = \fifo_writer.addr).
Adding EN signal on $flatten\fifo_reader.$procdff$66 ($adff) from module fifo (D =

A $3
B6 Y
$a
dd
A $5
B 3
S $m Y
ux
1 7:0 - 7:0

A $3
rst B5 Y
ARST
$e
CLK
D
fifo_reader.addr q 8'00000000
$74
EN
ren Q
$adffe 8'11111111 CLK $60 Q
ADDR D $dff
clk $25 DATA
CLK
$memrd
EN
rdata
1'x

1'x

Fig. 2.6: rdata output after opt_dff

See also
Advanced usage docs for
• FSM handling
• Optimization passes

Part 2
The next group of commands performs a series of optimizations:

Listing 2.10: coarse section (part 2)


wreduce
2.2. Synthesis starter
peepopt 30
opt_clean
share
YosysHQ Yosys, Version 0.48-dev
First up is wreduce - reduce the word size of operations if possible. If we run this we get the
following:

2.2. Synthesis starter 31


YosysHQ Yosys, Version 0.48-dev

Listing 2.11: output of wreduce


yosys> wreduce
19.Executing WREDUCE pass (reducing word size of cells).
Removed top 31 bits (of 32) from port B of cell fifo.$add$fifo.v:66$29 ($add).
Removed top 23 bits (of 32) from port Y of cell fifo.$add$fifo.v:66$29 ($add).
Removed top 31 bits (of 32) from port B of cell fifo.$sub$fifo.v:68$32 ($sub).
Removed top 23 bits (of 32) from port Y of cell fifo.$sub$fifo.v:68$32 ($sub).
Removed top 1 bits (of 2) from port B of cell fifo.$auto$opt_dff.cc:195:make_patterns_
˓→logic$72 ($ne).
Removed cell fifo.$flatten\fifo_writer.$procmux$55 ($mux).
Removed top 31 bits (of 32) from port B of cell fifo.$flatten\fifo_writer.$add$fifo.v:19
˓→$36 ($add).
Removed top 24 bits (of 32) from port Y of cell fifo.$flatten\fifo_writer.$add$fifo.v:19
˓→$36 ($add).
Removed cell fifo.$flatten\fifo_reader.$procmux$55 ($mux).
Removed top 31 bits (of 32) from port B of cell fifo.$flatten\fifo_reader.$add$fifo.v:19
˓→$36 ($add).
Removed top 24 bits (of 32) from port Y of cell fifo.$flatten\fifo_reader.$add$fifo.v:19
˓→$36 ($add).
Removed top 23 bits (of 32) from wire fifo.$add$fifo.v:66$29_Y.
Removed top 24 bits (of 32) from wire fifo.$flatten\fifo_reader.$add$fifo.v:19$36_Y.
Removed top 24 bits (of 32) from wire fifo.$flatten\fifo_writer.$add$fifo.v:19$36_Y.
yosys> show -notitle -format dot -prefix rdata_wreduce o:rdata %ci*
20.Generating Graphviz representation of design.
Writing dot description to `rdata_wreduce.dot'.
Dumping selected parts of module fifo to page 1.
yosys> opt_clean
21. Executing OPT_CLEAN pass (remove unused cells and
wires). Finding unused cells or wires in module \fifo..
Removed 0 unused cells and 5 unused wires.
<suppressed ~1 debug messages>
yosys> memory_dff
22.Executing MEMORY_DFF pass (merging $dff cells to $memrd).
Checking read port `\data'[0] in module `\fifo': merging output FF to cell.
Write port 0: non-transparent.
Looking at the data path for rdata, the most relevant of these width reductions are the ones affecting
fifo.
$flatten\fifo_reader.$add$fifo.v. That is the $add cell incrementing the fifo_reader address.
We can look at the schematic and see the output of that cell has now changed.
The next two (new) commands are peepopt - collection of peephole optimizers and share -
perform sat-based resource sharing. Neither of these affect our design, and they’re explored in
more detail in Optimization passes, so let’s skip over them. techmap -map +/cmp2lut.v -D
LUT_WIDTH=4 optimizes certain comparison operators by converting them to LUTs instead.
The usage of techmap is explored more in Technology mapping.

2.2. Synthesis starter 32


YosysHQ Yosys, Version 0.48-dev

A $3
B6 Y
$a
dd
A $5
B3
S $m
ux Y

A $3
B5 Y
$e
1'1 q 7:0 - 7:0 7:0 - 7:0

rst ARS
T $74 AD $25
Q fifo_reader.addr
DR $me 8'00000000

CLK CL mrd
ren
D 8'11111111 K D
EN
clk A
T CLK
D
$60 Q rdata
1'x
A $dff

1'x

Fig. 2.7: rdata output after wreduce

Our next command to run is memory_dff - merge input/output DFFs into memory read ports.
7:0 - 7:0 7:0 - 7:0

Listing 2.12: output of memory_dff

yosys> memory_dff

22. Executing MEMORY_DFF pass (merging $dff cells to $memrd).

Checking read port `\data'[0] in module `\fifo': merging output FF to cell.

Write port 0: non-transparent.

A $3
B6 Y
$a
dd
A
$53 Y
B
$mux
A $35 S
Y
B $eq

AD
DR
AR
ST
CL $25
K
2.2. Synthesis starter 33
rst
ARST fifo_reader.addr
CLK
clk D $74
EN
Q
YosysHQ Yosys, Version 0.48-dev
$adffe 8'11111111 EN $memr D 8'00000000

SR d_v2
1'0
ST A
T rdata

1'1
A

1'0

Fig. 2.8: rdata output after memory_dff

As the title suggests, memory_dff has merged the output $dff into the $memrd cell and
converted it to a
$memrd_v2 (highlighted). This has also connected the CLK port to the clk input as it is now a
synchronous memory read with appropriate enable (EN=1'1) and reset (ARST=1'0 and SRST=1'0)
inputs.

See also
Advanced usage docs for
• Optimization passes

2.2. Synthesis starter 34


YosysHQ Yosys, Version 0.48-dev

• Technology mapping
• Memory handling

Part 3
The third part of the synth_ice40 flow is a series of commands for mapping to DSPs. By
default, the iCE40 flow will not map to the hardware DSP blocks and will only be
performed if called with the -dsp flag: synth_ice40 -dsp. While our example has nothing
that could be mapped to DSPs we can still take a quick look at the commands here and
describe what they do.

Listing 2.13: coarse section (part 3)


wreduce t:$mul

techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_


˓→MAXWIDTH=16 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 -D
select a:mul2dsp ( if -dsp)

setattr -unset mul2dsp ( if -dsp)


opt_expr -fine ( if -dsp)
wreduce ( if -dsp)
select -clear ( if -dsp)
wreduce t:$mul performs width reduction again, this time targetting only cells of type $mul .
techmap -map
+/mul2dsp.v -map + / ice40/dsp_map.v . . . -D DSP_NAME=$ MUL16X16 uses techmap to
map $mul
cells to $ MUL16X16 which are, in turn, mapped to the iCE40 SB_MAC16. Any multipliers
which aren’t compatible with conversion to $ MUL16X16 are relabelled to $ soft_mul before
chtype changes them back to $mul .
During the mul2dsp conversion, some of the intermediate signals are marked with the attribute
mul2dsp. By calling select a:mul2dsp we restrict the following commands to only operate
on the cells and wires used for these signals. setattr removes the now unnecessary mul2dsp
attribute. opt_expr we’ve already come across for const folding and simple expression rewriting,
the -fine option just enables more fine-grain optimizations. Then we perform width reduction a
final time and clear the selection.
Finally we have ice40_dsp : similar to the memory_dff command we saw in the previous
section, this merges any surrounding registers into the SB_MAC16 cell. This includes not just
the input/output registers, but also pipeline registers and even a post-adder where applicable:
turning a multiply + add into a single multiply-accumulate.

See also
Advanced usage docs for Technology mapping

Part 4
That brings us to the fourth and final part for the iCE40 synthesis
flow:
2.2. Synthesis starter 35
YosysHQ Yosys, Version 0.48-dev
Listing 2.14: coarse section (part 4)
(continues on next page)
alumacc
opt

2.2. Synthesis starter 36


YosysHQ Yosys, Version 0.48-dev

memory -nomap [-no-rw-check]


opt_clean
(continued from previous page)
Where before each type of arithmetic operation had its own cell, e.g. $add , we now want to
extract these into $alu and $macc cells which can help identify opportunities for reusing
logic. We do this by running alumacc , which we can see produce the following changes in
our example design:

Listing 2.15: output of alumacc

yosys> alumacc

24. Executing ALUMACC pass (create $alu and $macc


cells). Extracting $alu and $macc cells in module fifo:
creating $macc model for $add$fifo.v:66$29 ($add).
creating $macc model for $flatten\fifo_reader.$add$fifo.v:19$36 ($add).
creating $macc model for $flatten\fifo_writer.$add$fifo.v:19$36 ($add).
creating $macc model for $sub$fifo.v:68$32 ($sub).
creating $alu model for $macc $sub$fifo.v:68$32.
creating $alu model for $macc $flatten\fifo_writer.$add$fifo.v:19$36.
creating $alu model for $macc $flatten\fifo_reader.$add$fifo.v:19$36.
creating $alu model for $macc $add$fifo.v:66$29.
creating $alu cell for $add$fifo.v:66$29:
$auto$alumacc.cc:485:replace_alu$87 creating $alu cell for $flatten\
fifo_reader.$add$fifo.v:19$36: $auto$alumacc.
˓→ cc:485:replace_alu$90
creating $alu cell for $flatten\fifo_writer.$add$fifo.v:19$36: $auto$alumacc.

1'1

$92
A CO
$90
BI X $91
$alu
1'0 Y

rst 7:0 - 7:0


7:0 - 7:0
ARST fifo_reader.addr

clk $$74 Q
adffe
CLK A
$53
D Y
ren A $35 8'00000000
8'11111111 Y B
B
$eq

1'0 ADDR

$25
ARST DATA rdata
emrd
CLK
1'1 EN

2.2. Synthesis starter 37


YosysHQ Yosys, Version 0.48-dev

Fig. 2.9: rdata output after alumacc

Once these cells have been inserted, the call to opt can combine cells which are now identical
but may have been missed due to e.g. the difference between $add and $sub .
The other new command in this part is memory - translate memories to basic cells. memory is
another

2.2. Synthesis starter 38


YosysHQ Yosys, Version 0.48-dev

macro command which we examine in more detail in Memory handling. For this document,
let us focus just on the step most relevant to our example: memory_collect . Up until this
point, our memory reads and our memory writes have been totally disjoint cells; operating on
the same memory only in the abstract. memory_collect combines all of the reads and writes
for a memory block into a single cell.

1'1
$92
A CO
$90
BI X $91
$alu
1'0 Y

7:0 - 7:0
7:0 - 7:0
rst ARST fifo_reader.addr
$74
Q
CLK A
$53
ren D Y
8'11111111 A $35 8'00000000
Y B
B
$eq

1'0

clk
RD_ADDR

1'1
RD_ARS
T
data
1'0 RD_SRST $mem_ v2 rdata
RD_DATA
WR_ADD
R
$19 WR_CLK

WR_DATA

$20

Fig. 2.10: rdata output after memory_collect

Looking at the schematic after running memory_collect we see that our $memrd_v2 cell has
been replaced with a $mem_v2 cell named data, the same name that we used in fifo.v. Where
before we had a single set of signals for address and enable, we now have one set for reading
(RD_*) and one for writing (WR_*), as well as both WR_DATA input and RD_DATA output.

See also
Advanced usage docs for
• Optimization passes
• Memory handling

Final note
Having now reached the end of the the coarse-grain representation, we could also have gotten
here by running synth_ice40 -top fifo -run : map_ram after loading the design. The -run
<from_label>: <to_label> option with an empty <from_label> starts from the begin section,
while the <to_label> runs up to but including the map_ram section.

2.2. Synthesis starter 39


YosysHQ Yosys, Version 0.48-dev

2.1.9 Hardware mapping


The remaining sections each map a different type of hardware and are much more architecture
dependent than the previous sections. As such we will only be looking at each section very
briefly.
If you skipped calling read_verilog -D ICE40_HX -lib -specify + / ice40/cells_sim.v
earlier, do it now.

Memory blocks
Mapping to hard memory blocks uses a combination of memory_libmap and techmap .

Listing 2.16: map_ram section

memory_libmap -lib +/ice40/brams.txt -lib +/ice40/spram.txt [-no-auto-huge] [-no-auto-


˓→block] ( -no-auto-huge unless -spram, -no-auto-block if -nobram)
techmap -map +/ice40/brams_map.v -map +/ice40/spram_map.v ice40_braminit

$techmap601╲data.0.0.MASK

MASK
0 -> 10:9 14:14 - 7:7

RADDR
0:0 - 8:8 RCLK 6:6 - 6:6
RCLKE
data.0.0
RE RDATA
WADDR SB_RAM40_4K
A
$techmap601╲data.0.0.WADDR 10:10 - 5:5
B $561 Y
$552 rdata
$mux
WCLK S
clk 2:2 - 4:4
WCLKE
WDATA $559

$548 WE
rst ARST

fifo_reader.addr $techmap601╲data.0.0.WDATA
D $adffe

ren
1'1
1'1 $530

A CO
1'0 B $528 $529
X
BI $alu
Y
1'0 7:0 - 7:0 7:0 - 7:0

A
B $465 Y
$mux
8'00000000 S
A $403 Y
8'11111111 B $eq

Fig. 2.11: rdata output after map_ram section

The map_ram section converts the generic $mem_v2 into the iCE40 SB_RAM40_4K
(highlighted). We can also see the memory address has been remapped, and the data bits have
been reordered (or swizzled). There is also now a $mux cell controlling the value of rdata. In
fifo.v we wrote our memory as read-before-write, however the SB_RAM40_4K has undefined
behaviour when reading from and writing to the same address in the same cycle. As a result,
extra logic is added so that the generated circuit matches the behaviour of the
verilog. Synchronous SDP with undefined collision behavior describes how we could change our
verilog to match our hardware instead.
If we run memory_libmap under the debug command we can see candidates which were
identified for mapping, along with the costs of each and what logic requires emulation.
2.2. Synthesis starter 40
YosysHQ Yosys, Version 0.48-dev

yosys> debug memory_libmap -lib +/ice40/brams.txt -lib +/ice40/spram.txt -no-auto-huge


4. Executing MEMORY_LIBMAP pass (mapping memories to cells).
Memory fifo.data mapping candidates (post-geometry):
- logic fallback

- cost: 2048.000000

2.2. Synthesis starter 41


YosysHQ Yosys, Version 0.48-dev

(continued from previous


- $ ICE40_RAM4K_:
- option HAS_BE 0 page)
- emulation score: 7
- replicates (for ports): 1
- replicates (for data): 1
- mux score: 0
- demux score: 0
- cost: 78.000000
- abits 11 dbits 2 4 8 16
- chosen base width 8
- swizzle 0 1 2 3 4 5 6 7
- emulate read-first behavior
- write port 0: port group W
- widths 2 4 8
- read port 0: port group R
- widths 2 4 8 16
- emulate transparency with write port 0
- $ ICE40_RAM4K_:
- option HAS_BE 1
- emulation score: 7
- replicates (for ports): 1
- replicates (for data): 1
- mux score: 0
- demux score: 0
- cost: 78.000000
- abits 11 dbits 2 4 8 16
- byte width 1
- chosen base width 8
- swizzle 0 1 2 3 4 5 6 7
- emulate read-first behavior
- write port 0: port group W
- widths 16
- read port 0: port group R
- widths 2 4 8 16
- emulate transparency with write port 0
Memory fifo.data mapping candidates (after post-geometry prune):
- logic fallback
- cost: 2048.000000
- $ ICE40_RAM4K_:
- option HAS_BE 0
- emulation score: 7
- replicates (for ports): 1
- replicates (for data): 1
- mux score: 0
- demux score: 0
- cost: 78.000000
- abits 11 dbits 2 4 8 16
- chosen base width 8
- swizzle 0 1 2 3 4 5 6 7
- emulate read-first behavior
- write port 0: port group W
- widths 2 4 8

2.2. Synthesis starter 42


YosysHQ Yosys, Version 0.48-dev

(continues on next page)

2.2. Synthesis starter 43


YosysHQ Yosys, Version 0.48-dev

- read port 0: port group R


- widths 2 4 8 16
- emulate transparency with write port
0 mapping memory fifo.data via $
ICE40_RAM4K_
(continued from previous page)
The $ ICE40_RAM4K_ cell is defined in the file techlibs/ice40/brams.txt, with the mapping to
SB_RAM40_4K done by techmap using techlibs/ice40/brams_map.v. Any leftover memory
cells are then converted into flip flops (the logic fallback) with memory_map .
Listing 2.17: map_ffram section
opt -fast -mux_undef -undriven -fine
memory_map

opt -undriven -fine

$546
[6] 0:0
- 0:0 0:
00:0-
6:6 0:0 - 0:0
$546 X ->-- 6:6
2:2 5:5
4:4
[2]
X -> 3:3
$546
[4] 4:4 - 2:2
X -> 1:1
$546 0:0 - 0:0
[0]

$547 00:0
->-10:9
8:8
[0]
0 -> 7:7
$547 7:1 - 6:0
[7:1]
$548
1'1

2.2. Synthesis starter 44


YosysHQ Yosys, Version 0.48-dev

Fig. 2.12: rdata output after map_ffram section

Note

The visual clutter on the RDATA output port (highlighted) is an unfortunate side effect of opt_clean on the
swizzled data bits. In connecting the $mux input port directly to RDATA to reduce the number of wires, the
$techmap579\data.0.0.RDATA wire becomes more visually complex.

See also

2.2. Synthesis starter 45


YosysHQ Yosys, Version 0.48-dev

Advanced usage docs for


• Technology mapping
• Memory handling

Arithmetic
Uses techmap to map basic arithmetic logic to hardware. This sees somewhat of an
explosion in cells as multi-bit $mux and $adffe are replaced with single-bit $_MUX_ and
$_DFFE_PP0P_ cells, while the $alu is replaced with primitive $_OR_ and $_NOT_ gates
and a $lut cell.

Listing 2.18: map_gates section

ice40_wrapcarry
techmap -map +/techmap.v -map +/ice40/arith_map.v
opt -fast
abc -dff -D 1 ( only if -retime)
ice40_opt

See also
Advanced usage docs for Technology mapping

Flip-flops
Convert FFs to the types supported in hardware with dfflegalize , and then use techmap
to map them. In our example, this converts the $_DFFE_PP0P_ cells to SB_DFFER.
We also run simplemap here to convert any remaining cells which could not be mapped to
hardware into gate-level primitives. This includes optimizing $_MUX_ cells where one of the
inputs is a constant 1'0, replacing it instead with an $_AND_ cell.

Listing 2.19: map_ffs section


dfflegalize -cell $_DFF_? _ 0 -cell $_DFFE_? P_ 0 -cell $_DFF_? P? _ 0 -cell $_DFFE_? P? P_␣

˓→0 -cell $_SDFF_? P? _ 0 -cell $_SDFFCE_? P? P_ 0 -cell $_DLATCH_? _ x -mince - 1


techmap -map +/ice40/ff_map.v
opt_expr -mux_undef
simplemap

See also
Advanced usage docs for Technology mapping

LUTs
abc and techmap are used to map LUTs; converting primitive cell types to use $lut and
SB_CARRY cells. Note that the iCE40 flow uses abc9 rather than abc . For more on what these
2.2. Synthesis starter 46
YosysHQ Yosys, Version 0.48-dev
do, and what the difference between these two commands are, refer to The ABC toolbox.

2.2. Synthesis starter 47


YosysHQ Yosys, Version 0.48-dev

C 0:0 - 2:2
D $717
Q

rst
2:2 - 0:0
0:0 - 3:3

C
D $718
Q

3:3 - 0:0

1'0
C 0:0 - 5:5
D $720
A Q
1:1 - 0:0 B $771 E $_DFFE_PP0P_
$_MU X_
Y
S
1'0
0:0 - 1:1
0:0 - 0:0

4:4 - 0:0 A
B $774
$_MU X_
S
Y
1'0
0:0 - 4:4
A
2:2 - 0:0
$772

0:0 - 2:2

0 -> 3:3
A
$lut 5:5 - 0:0
B Y
7:1 - 6:0 6:0 - 7:1 2'10 1:0 - 1:0 $_MUX_
S 0:0 - 6:6
1'0
A $870 Y
0:0 - 0:0 $_NOT_ 0:0 - 0:0 0:0 - 0:0
A
A $791 B $773 Y 0:0 - 3:3
B Y 3:3 - 0:0 $_MUX_
$871 $_OR_
1:1 - 0:0 A Y
$_NOT_ 2:2 - 0:0 0:0 - 0:0 A $799
0:0 - 0:0
B $_OR_ Y
A $970 Y A $797
Y A 0:0 - 5:5
6:6 - 0:0 $_NOT_ 3:3 - 0:0 $_OR_ 0:0 - 1:1 1'0
B 1:1 - 0:0 B Y
A $775
$794 $_MUX_
Y S
A $972 Y 0:0 - 3:3
B
7:7 - 0:0 $_NOT_ 5:5 - 0:0
0:0 - 0:0 A $796 0:0 - 0:0
C Y 0:0 - 7:7
B $_OR_ A
D $715
Q 0:0 - 0:0 fifo_reader.addr 2:2 - 0:0 A $964 Y A $792 B $777 Y
$ _NOT _ B Y 0:0 - 1:1 1'0 $ _MUX _
E $_DFFE_PP0P_ $_OR_ 1:1 - 0:0
S

3:3 - 0:0 A $962 Y 0:0 - 0:0


$ _NOT _ 7:7 - 0:0 A
B $770
$_MU X_
$968 0:0 - 2:2 Y
4:4 - 0:0 A Y A $793 S
$_NOT_ 1'0
Y
B $_OR_

5:5 - 0:0 A $966 Y 0:0 - 0:0


$ _NOT _
4:4 - 0:0
0:0 - 4:4

6:6 - 0:0
C
D $719
Q

0:0 - 6:6

7:7 - 0:0

ren

C
D $721
Q

1:1 - 0:0

clk
0:0 - 7:7

C
D $722
Q 0:0 - 1:1

C
D $716
Q

16'x
1:1 - 0:0

0 -> 10:9 A
$552 [1]
B Y
$_MUX_
S
$559

1'1
15:15 - 15:15 0:0 - 1:1

1'1
$546 [7]
MASK
14:14 - 7:7
$546 [3]
7:7 - 7:7 7:7 - 14:14
X -> 15:15 RE
RADDR data.0.0
$546 [5]
WADDR SB_RAM40_4K 13:13 - 13:13
$techmap601╲data.0.0.RDATA

$546 [1] X -> 9:9 3:3 - 6:6 6:6 - 12:12


WCLKE

12:12 - 3:3
$546 [6]

1:1 - 8:8 5:5 - 5:5 5:5 - 10:10

11:11 - 11:11 2:2 - 0:0

$546 [4]
X -> 7:7

$552 [2] A
0 -> 10:9
$547 [0] B $812 Y
$ _MUX _
S
$559
$547 [7:1]

3:3 - 0:0 0:0 - 2:2


$548

A
$552 [3]
1'1 B Y
$_MUX_
S
$559

4:4 - 0:0 0:0 - 3:3

A
$552 [4]
B Y
$_MUX_
S
$559 0:0 - 4:4
rdata

5:5 - 0:0
A 0:0 - 5:5
B $815
$_MU X_
$552 [5]
S
Y

$559
0:0 - 6:6

6:6 - 0:0
A
B $816
$_MU X_
$552 [6] Y
S

0:0 - 7:7
$559

A
B $817
$_MU X_
Y 0:0 - 0:0
$552 [7] S

$559 A
B $810
$_MU X_
Y
$552 [0] S

Fig. 2.13: rdata output after map_gates section

2.2. Synthesis starter 48


YosysHQ Yosys, Version 0.48-dev

C 0:0 - 2:2
D $717
Q

rst
2:2 - 0:0
0:0 - 7:7

C
D $722
Q

7:7 - 0:0

A $772
2:2 $_AND_ Y 0:0 - 1:1
$964 B C
A Y - 0:0 0:0 - 2:2
2:2 - 0:0 D
$_NOT_ $716
Q
A $792 A $773 E SB_DFFER
$962 Y Y
3:3 - 0:0 A Y B $_OR_ 0:0 - 1:1 B $_AND_ 0:0 - 3:3 R
$_NOT_ 0:0 - 0:0 3:3 - 0:0
0:0 - 0:0
A $796 A
$871 $774
1:1 - 0:0 A Y Y Y
$_NOT_ 1:1 - 0:0 B $_OR_ 0:0 - 0:0 4:4 - 0:0 $_AND_ 0:0 - 4:4
B
A 0:0 - 0:0
B $791 Y A $799
$968 0:0 - 0:0 $_OR_ 0:0 - 0:0 Y
4:4 - 0:0 A Y A $775
$ _NOT _ 2:2 - 0:0 A
B $_OR_ Y 0:0 - 5:5 1:1 - 0:0
B $797 Y 0:0 - 1:1 B _AND_
A $_OR_ 1:1 - 0:0
$ $793 5:5 - 0:0
A $_OR_ Y 0:0 - 2:2
5:5 - 0:0 $ N O T __ B
3:3 - 0:0 A $776
966 Y 0:0 - 6:6
Y

C $970 A $794
6:6 - 0:0 A Y 0:0 - 3:3
D $715 $ _NOT _ B $_OR_
Y
A 0:0 - 7:7
0:0 - 0:0 $777
Q 0:0 - 0:0 fifo_reader.addr Y
E SB_DFFER 7:7 - 0:0 B $_AND_
A $972 Y
R 7:7 - 0:0 $_NOT_
0:0 - 1:1
A $771
$1076 0:0 - 0:0
0:0 - 0:0 A Y 0:0 - 0:0
$_NOT_
0:0 - 0:0
A $770
0:0 - 0:0
Y
7:1 - 6:0 6:0 - 7:1 B $_AND_
5:5 - 0:0
0:0 - 5:5

3:3 - 0:0
C
D $720
Q

0:0 - 3:3

4:4 - 0:0

ren

C
D $718
Q

0:0 - 4:4
6:6 - 0:0

clk

C
D $719 Q 0:0 - 6:6

C
D $721
Q

16'x 4:4 - 0:0

0 -> 10:9 A
$552 [4]
B Y
$_MUX_
S

$559
0:0 - 8:8

1'1 0:0 - 4:4


A
$552 [5] $815
B
$_MU X_
1'1 S
Y
$559
$546 [7]
MASK
X -> 15:15 RADDR

$546 [3] RCLK


RCLKE 15:15 - 15:15
RE 0:0 - 5:5
data.0.0
$546 [5] 7:7 - 14:14 RDATA 13:13 - 13:13
WADDR SB_RAM40_4K

$546 [1]

X -> 13:13 12:12 - 3:3

7:7 - 7:7 7:7 - 14:14

$546 [2] 3:3 - 12:12 WCLK


11:11 - 11:11 $techmap601╲data.0.0.RDATA

3:3 - 6:6 6:6 - 12:12


$546 [4]

X -> 11:11
WCLKE
10:10 - 5:5
5:5 - 5:5 5:5 - 10:10

6:6 - 0:0
0 -> 10:9

$547 [0] 0:0 - 8:8

$552 [6] A
$816
1'1 B
$_MU X_
S
Y
$559

0:0 - 6:6
7:7 - 0:0

A
$817
$552 [7] B
$_MU X_
S
Y
0:0 - 7:7
$559
rdata

0:0 - 0:0
A $810 0:0 - 0:0
B
$_MU X_
$552 [0] Y
S

0:0 - 1:1
1:1 - 0:0
A $811
B
$_MU X_
$552 [1] Y
S

0:0 - 2:2
$559

A $812
B
$_MU X_
$552 [2] Y
S

0:0 - 3:3
3:3 - 0:0
A $813
B
$_MU X_
$552 [3] Y
S

Fig. 2.14: rdata output after map_ffs section

2.2. Synthesis starter 49


YosysHQ Yosys, Version 0.48-dev

Listing 2.20: map_luts section


abc ( only if -abc2)
ice40_opt ( only if -abc2)
techmap -map +/ice40/latches_map.v
simplemap ( if -noabc or -flowmap)
( only if -noabc)
techmap -map +/gate2lut.v -D LUT_WIDTH=4
flowmap -maxlut 4 ( only if -flowmap)
read_verilog -D ICE40_HX -icells -lib -specify +/ice40/abc9_model.v
abc9 -W 250
ice40_wrapcarry -unwrap
techmap -map +/ice40/ff_map.v
clean

opt_lut -tech ice40

C
D $720
Q

5:5 - 0:0

0:0 - 5:5
0:0 - 1:1
$2202
0:0 - 3:3 A Y
$lut 0:0 - 6:6
$2210
A Y
0:0 - 3:3

1'0 CI
$528.slice[5].carry
I0 CO
SB_CARRY A $2200 Y
I1 $lut
$80
A Y 0:0 - 0:0
CI 0:0 - 3:3 0:0 - 2:2 CI
1'0 A $2208 Y
I0 $528.slice[1].carry CO $lut 1'0 I0 $528.slice[4].carry CO
SB_CARRY SB_CARRY
1:1 - 0:0 I1 I1

CI
$528.slice[2].carry CI
D 1'0 I0 CO 1'0
$716 SB_CARRY I0 CO
E Q SB_CARRY 0:0 - 3:3 0:0 - 7:7
SB_DFFER I1

3:3 - 0:0
$2168
0:0 - 4:4 A Y
0:0 - 3:3 $2204 $lut
0:0 - 0:0 A Y
$lut

rst C
D $715
0:0 - 3:3 $2206 0:0 - 3:3
A Y

CI
C $528.slice[6].carry
1'0 I0 CO 0:0 - 3:3
$717 SB_CARRY
Q
E SB_DFFER

C
D $718 16'0000000000000000
Q
4:4 - 0:0 E SB_DFFER

0 -> 10:9
ren

C
D $719
Q
0:0 - 8:8

6:6 - 0:0 0 -> 7:7

clk

C
D $721
Q

C
D $722
Q

15:15 - 15:15

1'1

MASK
7:7 - 7:7 7:7 - 14:14
1'1 14:14 - 7:7

$1276
$techmap2134╲data.0.0.RDATA
0 -> 15:15 RE data.0.0
$1268 RDATA 3:3 - 6:6 6:6 - 12:12
WADDR SB_RAM40_4K 13:13 - 13:13

$1272 0:0 - 14:14

WCLK 12:12 - 3:3


WCLKE

0 -> 13:13

$559 5:5 - 2:2


0:0 - 12:12

$1270 $lut╲rdata[5]
$552 [5] A Y

$1262
$559 6:6 - 2:2 0:0 - 5:5

$lut╲rdata[6]
A Y
$552 [6] $lut
$1376
0:0 - 6:6
0 -> 10:9
$559 7:7 - 2:2
$1380 $lut╲rdata[7]
A Y
$552 [7]
0:0 - 7:7
$1382 0:0 - 8:8
0:0 - 2:2
$559
$lut╲rdata[0]
$1384 A Y
$lut 0:0 - 0:0
$552 [0] rdata
0 -> 7:7
$1386
1:1 - 2:2 $lut╲rdata[1]
$559 A Y 0:0 - 1:1
$lut
$1388 $techmap2134╲data.0.0.WCLKE
$552 [1] 0:0 - 2:2
$1390 $lut╲rdata[2]
1'1 2:2 - 2:2 A Y
$lut
$559
$1392

$552 [2] 0:0 - 3:3


$lut╲rdata[3]
3:3 - 2:2 A Y
$lut
$559

$lut╲rdata[4] 0:0 - 4:4


A Y
$552 [3] $lut
4:4 - 2:2

$559

Fig. 2.15: rdata output after map_luts section

Finally we use techmap to map the generic $lut cells to iCE40 SB_LUT4 cells.

2.2. Synthesis starter 50


YosysHQ Yosys, Version 0.48-dev

CI
1'0 0:0 - I0 data.0.0_RADDR_7
data.0.0_RADDR_7_S 2:2 _SB_CARRY_I1
SB_CARRY
B_CARRY_I1_CO I0
0:0 - 1'0 I1 CO
1'0 I1
2:2 data.0.0_RADDR_6_SB_LUT4
I2
CI
1'0 I0 data.0.0_RAD SB_LUT4
I1 CI 0.0_RADDR_2_S 0:0 - 2:2 -
1'0 I0 B_CARRY_I1 2:2 0:0
SB_CA
data.0.0_RADDR_2_S 2:2 - 0:0 -
RRY
B_CARRY_I1 0:0 1'0 1:1
CO 2:2 -
1'0 I0 data.0.0_RADDR I0
3:3 2:2 - 0:0 1'0 I1
I1
data.0.0_RADDR_1_
I2 SB_LUT4 0:0 - data.0.0_RADDR_7_SB
I2
1'0 2:2
O SB_LUT4
I3 C 0:0 - 2:2 - 1'0
D ata.0.0_R ata.0.0_R 2:2 -
ADD 2:2 3:3 ADDR 0:0 I0
data.0.0_RADDR_6_S
E rdata_SB_L
2:2 - SB_DFFER 16'000000000 UT4_O
0:0 0:0 - 0000000 O
2:2 I2
C
D
0:0 - 0:0data.0.0_RADDR_S 2:2 -
E 3:3 2:2 -
data.0.0_R 0:0 0 -> 1'0 0:0 -
0:0 - Q ADDR 7:7
7:7 SB_DFFER 0:0 - 10:9
2:2
D
R 0:0 - 0:0
data.0.0_RADDR_7_S 2:2 - I0 I1
E 0:0
SB_DFFER ta.0.0_RD rdata_SB_LUT
15:15 - ATA_1 4_O_4
15:15 2:2 - O
7:7 - 0:0 D 0:0
0:0 -
data.0.0_RADDR_1_SB_DFFER
E 0:0 MA
SB_DFFER SK 0:0 -
1'1 3:3
ren D RA
RE 8:8 - 1'0
data.0.0_RADDR_ data.0.0_RADDR_2_SB_DFFER_Q
E data.0.0_RA 1'1 data.0.0SB_RAM40_4K 2:2
WADDR
SB_LUT4_I3_O Q DDR_2 RDATA
SB_DFFER 2:2 - 7:7 - 7:7 6:6 - I0
WC I1
3:3 1'1
I0 LK 2:2 SB_LU
rdata_SB_LUT4_
1' I2 T4
3:3 - 0:0 D 0 I2 SB_LUT4 0:0 - WC 1:1 - 0:0
E O
SB_DFFER I3 3:3 0:0 -
1'0 I0 0:0 - 1:1
I1 1:1
data.0.0_RADDR_5_ data.0.0_RADDR_SB_LUT data.0.0_
1'0 1'0 WDATA 0 ->
Q 4_I3 15:15
E data.0.0_W
SB_DFFER_Q 1'0 DATA_4 1:1 - 0:0
SB_DFFER Q 0:0 - 1:1
4:4 - 2:2 - data.0.0_
0:0 0:0 data.0.0_W RDATA
C 0:0 - DATA_2 1:1 - 7:7 -
2:2 0:0
data.0.0_RA data.0.0_W 14:14
E DDR_5 DATA_6
SB_DFFER
2:2 - data.0.0_W 1:1 - 0:0
DATA_1 0:0 - 0:0 - 1:1
3:3
data.0.0_W 14:14
DATA_5 1:1 -
0:0
1'0 data.0.0_W
data.0.0_RADDR_6_S DATA_3
B_CARRY_I1_CO 0:0 - 1'0
0.0_RADDR_3_S 2:2 1'0 data.0.0_W 0:0 -
B_CARRY_I1 DATA_7 I0 0:0
0:0 - 0:0 - 1'0
2:2 rdat
2:2 2:2 - I2 a
2:2 - 0:0 ata.0.0_RDATA_ I0
data.0.0_R I0 0:0 - SB_LUT 0:0 -
CI ADDR 6:6 1:1 - 0:0 O 5:5
3:3 2:2 - 0:0 I1
1'0 I0 SB_CA data.0.0_RADDR_2_SB_LUT4_I2
I2 SB_LUT4 2:2 - I3
data.0.0_RADDR_3_SB_ 0:0 - 0:0 - ta.0.0_RDATA_2
I1 RRY 2:2 0:0 2:2 - 0:0
O 1:1
I3 1:1 - 0:0 -
0:0 2:2
1:1 -
1'0 0:0 1'0
0:0 -
I0 5:5 I0 rdata_SB_LUT4
1'0 I1 1:1 - 0:0
0:0 - 1:1
0:0 - data.0.0_RADDR_3_SB_LUT4
I2 I2 _O_5 O
2:2 SB_LUT4 2:2 - SB_LUT
.0.0_RADDR_4_S 0:0 0:0 -
B_CARRY_I1 1:1 - 6:6
CI 0:0
SB_CA 1:1 -
I1 RRY 0:0 1'0
CI 0:0 -
1:1 I0
SB_CA .0.0_RADDR_5_ 0:0 - 2:2 - data.0.0_RADDR_4
I1 RRY SB_CARRY_I 2:2 - 0:0 SB_LUT4
2:2 3:3 0:0 - 1:1 - I2
0:0 O
1'0 4:4
I0
1'0 I1 0:0 -
1:1
data.0.0_RADDR_4_SB_LUT4
_I2 1'0 0:0 -
O 4:4
ta.0.0_RD I0
ATA_6 0:0 - 0:0 I1
rdata_SB_LUT
4_O_3
1:1 - O
0:0

data.0.0_WADDR_3 [0]

0 -> 10:9

Fig. 2.16: rdata output after map_cells section

Listing 2.21: map_cells section


techmap -map +/ice40/cells_map.v ( skip if -vpr)
clean

See also
Advanced usage docs for
• Technology mapping
• The ABC toolbox

Other cells
The following commands may also be used for mapping other cells:
hilomap
Some architectures require special driver cells for driving a constant hi or lo value. This
command replaces simple constants with instances of such driver cells.
iopadmap
Top-level input/outputs must usually be implemented using special I/O-pad cells. This
command inserts such cells to the design.
These commands tend to either be in the map_cells section or after the check section depending on
the flow.

2.1.10 Final steps


The next section of the iCE40 synth flow performs some sanity checking and final tidy up:

Listing 2.22: check section


autoname
hierarchy -check
stat
2.2. Synthesis starter 51
check -noinit

blackbox =A:whitebox
YosysHQ Yosys, Version 0.48-dev
The new commands here are:

2.2. Synthesis starter 52


YosysHQ Yosys, Version 0.48-dev

• autoname - automatically assign names to objects,


• stat - print some statistics, and
• blackbox - convert modules into blackbox modules.
The output from stat is useful for checking resource utilization; providing a list of cells used in
the design and the number of each, as well as the number of other resources used such as wires
and processes. For this design, the final call to stat should look something like the following:
yosys> stat -top fifo

17. Printing statistics.

=== fifo ===

Number of wires: 95
Number of wire bits: 262
Number of public wires: 95
Number of public wire bits: 262
Number of ports: 7
Number of port bits: 29
Number of memories: 0
Number of memory bits: 0
Number of processes: 0
Number of cells: 138
$scopeinfo 2
SB_CARRY 26
SB_DFF 26
SB_DFFER 25
SB_LUT4 58
SB_RAM40_4K 1

Note that the -top fifo here is optional. stat will automatically use the module with the
top attribute set, which fifo was when we called hierarchy . If no module is marked top,
then stats will be shown for each module selected.
The stat output is also useful as a kind of sanity-check: Since we have already run proc ,
we wouldn’t expect there to be any processes. We also expect data to use hard memory; if
instead of an SB_RAM40_4K saw a high number of flip-flops being used we might suspect
something was wrong.
If we instead called stat immediately after read_verilog fifo.v we would see something very
different:

Number of wires: 28
Number of wire bits: 219
Number of public wires: 9
Number of public wire bits: 45
2.2. Synthesis starter 53
YosysHQ Yosys, Version 0.48-dev
Number of ports: 7
Number of port bits: 29
Number of memories: 1
(continues on next page)

2.2. Synthesis starter 54


YosysHQ Yosys, Version 0.48-dev

(continued from previous page)


Number of memory bits: 2048
Number of processes: 3
Number of cells: 9
$add 1
$logic_and 2
$logic_not 2
$memrd 1
$sub 1
addr_gen 2
=== addr_gen
===

Number of wires: 8
Number of wire bits: 60
Number of public wires: 4
Number of public wire bits: 11
Number of ports: 4
Number of port bits: 11
Number of memories: 0
Number of memory bits: 0
Number of processes: 2
Number of cells: 2
$add 1
$eq 1

Notice how fifo and addr_gen are listed separately, and the statistics for fifo show 2 addr_gen
modules. Because this is before the memory has been mapped, we also see that there is 1
memory with 2048 memory bits; matching our 8-bit wide data memory with 256 values (8 *
256 = 2048).

Synthesis output
The iCE40 synthesis flow has the following output modes available:
• write_blif - write design to BLIF file,
• write_edif - write design to EDIF netlist file, and
• write_json - write design to a JSON file.
As an example, if we called synth_ice40 -top fifo -json fifo.json, our synthesized fifo
design will be output as fifo.json. We can then read the design back into Yosys with
read_json , but make sure you use design -reset or open a new interactive terminal first.
The JSON output we get can also be loaded into nextpnr to do place and route; but that is
beyond the scope of this documentation.

See also
synth_ice40 - synthesis for iCE40 FPGAs

2.2 Scripting in Yosys


2.2. Synthesis starter 55
YosysHQ Yosys, Version 0.48-dev
On the previous page we went through a synthesis script, running each command in the
interactive Yosys shell. On this page, we will be introducing the script file format and how you
can make your own synthesis scripts.

2.2. Synthesis starter 56


YosysHQ Yosys, Version 0.48-dev

Yosys script files typically use the .ys extension and contain a set of commands for Yosys to run
sequentially. These commands are the same ones we were using on the previous page like
read_verilog and hierarchy .

2.2.1 Script parsing


As with the interactive shell, each command consists of the command name, and an optional
whitespace separated list of arguments. Commands are terminated with the newline character,
and anything after a hash sign # is a comment (i.e. it is ignored).
It is also possible to terminate commands with a semicolon ;. This is particularly useful in
conjunction with the -p <command> command line option, where <command> can be a string
with multiple commands separated by semicolon. In-line comments can also be made with the
colon :, where the end of the comment is a semicolon ; or a new line.
Listing 2.23: Using the -p option
$ yosys -p "read_verilog fifo.v; :this is a comment; prep"

Warning
The space after the semicolon is required for correct parsing. log a;log b; for example will
display
a;log b instead of a and b as might be expected.

Another special character that can be used in Yosys scripts is the bang !. Anything after the bang
will be executed as a shell command. This can only be terminated with a new line. Any
semicolons, hashes, or other special characters will be passed to the shell. If an error code is
returned from the shell it will be raised by
Yosys. exec provides a much more flexible way of executing commands, allowing the output
to be logged and more control over when to generate errors.

2.2.2 The synthesis starter script


All of the images and console output used in Synthesis starter were generated by Yosys, using
Yosys script files found in docs/source/code_examples/fifo. If you haven’t already, let’s take a
look at some of those script files now.

12

13

14
1
0
15

1
1 16

2.3. Scripting in Yosys 37


YosysHQ Yosys, Version 0.48-dev
1 Listing 2.24: A section of fifo.ys, generating the images used for
7 The addr_gen module

1
8
echo on
1 hierarchy -top addr_gen
select -module addr_gen
9 select -list
select t:*
2 select -list
0 select -set new_cells %
select -clear
show -format dot -prefix addr_gen_show addr_gen
show -format dot -prefix new_cells_show -notitle @new_cells
21 show -color maroon3 @new_cells -color cornflowerblue p:* -notitle -format dot -prefix␣
˓→ addr_gen_hier
22

23
(continues on next page)

2.3. Scripting in Yosys 38


YosysHQ Yosys, Version 0.48-dev

(continued from previous page)


select -set new_cells t:$mux t:* dff
24
show -color maroon3 @new_cells -notitle -format dot -prefix addr_gen_proc

# ========================================================
25
opt_expr; clean

26 select -set new_cells t:$eq


show -color cornflowerblue @new_cells -notitle -format dot -prefix addr_gen_clean
27 # ========================================================

28

29

30

31

32

The first command there, echo on, uses echo to enable command echoes on. This is how we
generated the code listing for hierarchy -top addr_gen output. Turning command echoes on prints
the yosys> hierarchy
-top addr_gen line, making the output look the same as if it were an interactive terminal.
hierarchy -top addr_gen is of course the command we were demonstrating, including the output
text and an image of the design schematic after running it.
We briefly touched on select when it came up in synth_ice40 , but let’s look at it more now.

Selections intro
The select command is used to modify and view the list of selected objects:
yosys> select -module addr_gen
yosys [addr_gen]> select -list
addr_gen
addr_gen/$1\addr[7:0]
addr_gen/$add$fifo.v:19$3_Y
addr_gen/$eq$fifo.v:16$2_Y
addr_gen/$0\addr[7:0]
addr_gen/addr
addr_gen/rst
addr_gen/clk
2.3. Scripting in Yosys 39
YosysHQ Yosys, Version 0.48-dev
addr_gen/en
addr_gen/$add$fifo.v:19$3
addr_gen/$eq$fifo.v:16$2
addr_gen/$proc$fifo.v:0$4
addr_gen/$proc$fifo.v:12$1
yosys [addr_gen]> select t:*
yosys [addr_gen]*> select -
list addr_gen/$add$fifo.v:19$3
addr_gen/$eq$fifo.v:16$2
yosys [addr_gen]*> select -set new_cells %
yosys [addr_gen]*> select -clear

When we call select -module addr_gen we are changing the currently active selection from the
whole design, to just the addr_gen module. Notice how this changes the yosys at the start of
each command to yosys [addr_gen]? This indicates that any commands we run at this point will
only operate on the addr_gen module. When we then call select -list we get a list of all objects
in the addr_gen module, including the module itself, as well as all of the wires, inputs,
outputs, processes, and cells.

2.3. Scripting in Yosys 40


YosysHQ Yosys, Version 0.48-dev

Next we perform another selection, select t:* . The t: part signifies we are matching on
the cell type, and the * means to match anything. For this (very simple) selection, we are
trying to find all of the cells, regardless of their type. The active selection is now shown as
[addr_gen]*, indicating some sub-selection of the addr_gen module. This gives us the $add
and $eq cells, which we want to highlight for the addr_gen module after hierarchy image.
We can assign a name to a selection with select -set. In our case we are using the name
new_cells, and telling it to use the current selection, indicated by the % symbol. We can then
use this named selection by referring to it as @new_cells, which we will see later. Then we
clear the selection so that the following commands can operate on the full design. While we
split that out for this document, we could have done the same thing in a single line by
calling select -set new_cells addr_gen/t:* . If we know we only have the one module in our
design, we can even skip the addr_gen/ part. Looking further down the fifo.ys code we can see
this with select -set new_cells t:$mux t:* dff. We can also see in that command that
selections don’t have to be limited to a single statement.
Many commands also support an optional [selection] argument which can be used to override the
currently selected objects. We could, for example, call clean addr_gen to have clean operate on
just the addr_gen module.
Detailed documentation of the select framework can be found under Selections or in the
command reference at select - modify and view the list of selected objects.

Displaying schematics
While the select command is very useful, sometimes nothing beats being able to see a design for
yourself. This is where show comes in. Note that this document is just an introduction to the
show command, only covering the basics. For more information, including a guide on what the
different symbols represent, see A look at the show command and the Interactive design
investigation page.

Note

The show command requires a working installation of GraphViz and xdot for displaying the actual circuit
diagrams.

This is the first show command we called in fifo.ys, as we saw above. If we look at the log
output for this image we see the following:
yosys> show -format dot -prefix addr_gen_show addr_gen

4. Generating Graphviz representation of design.


Writing dot description to `addr_gen_show.dot'.
Dumping module addr_gen to page 1.

Calling show with -format dot tells it we want to output a .dot file rather than opening it for
display. The
-prefix addr_gen_show option indicates we want the file to be called addr_gen_show.* .
Remember, we do this in fifo.ys because we need to store the image for displaying in the
documentation you’re reading. But if you just want to display the images locally you can
skip these two options. The -format option internally calls the dot command line program
from GraphViz to convert to formats other than .dot. Check GraphViz output docs for more
on available formats.
2.3. Scripting in Yosys 41
YosysHQ Yosys, Version 0.48-dev

Note

If you are using a POSIX based version of Yosys (such as for Mac or Linux), xdot will be opened in the
background and Yosys can continue to be used. If it it still open, future calls to show will use the same

2.3. Scripting in Yosys 42


YosysHQ Yosys, Version 0.48-dev

A $2
Y
0 -> 31:8
B $eq

7:0 - 7:0

255
rst

clk

PROC $1
en
o.v:12.2-20
fif .6

PROC $4
addr
fo.v:0.0-0.
fi 0

A $3 7:0 - 7:0
Y
1 B $add
addr_gen

Fig. 2.17: Calling show addr_gen after hierarchy

2.3. Scripting in Yosys 43


YosysHQ Yosys, Version 0.48-dev

xdot instance.

The addr_gen at the end tells it we only want the addr_gen module, just like when we called
select
-module addr_gen in Selections intro. That last parameter doesn’t have to be a module name, it
can be any valid selection string. Remember when we assigned a name to a selection and called
it new_cells? We saw in the select -list output that it contained two cells, an $add and an $eq .
We can call show on that selection just as easily:

0 -> 31:8
addr 7:0 - 7:0
$2_Y
255 A $2 Y
B $eq

addr
A $3 Y
B $add $3_Y
1

Fig. 2.18: Calling show -notitle @new_cells


We could have gotten the same output with show -notitle t:$add t:$eq if we didn’t have the
named selection. By adding the -notitle flag there we can also get rid of the addr_gen title that
would have been automatically added. The last two images were both added for this
introduction. The next image is the first one we saw in Synthesis starter : showing the full
addr_gen module while also highlighting @new_cells and the two PROC blocks. To achieve
this highlight, we make use of the -color option:
As described in the the help output for show (or by clicking on the show link), colors are
specified as
-color <color> <object>. Color names for the <color> portion can be found on the GraphViz
color docs. Unlike the final show parameter which can have be any selection string, the <object>
part must be a single selection expression or named selection. That means while we can use
@new_cells, we couldn’t use t:$eq t:$add. In general, if a command lists [selection] as its
final parameter it can be any selection string. Any selections that are not the final parameter,
such as those used in options, must be a single expression
instead.
For all of the options available to show , check the command reference at show - generate
schematics using graphviz.

2.3. Scripting in Yosys 44


YosysHQ Yosys, Version 0.48-dev

See also
A look at the show command on the Interactive design investigation page.

2.3. Scripting in Yosys 45


YosysHQ Yosys, Version 0.48-dev

A $2
Y
B $eq
0 -> 31:8

7:0 - 7:0

255
rst

clk

PROC $1
en
o.v:12.2-20
fif .6

PROC $4
addr
fo.v:0.0-0.
fi 0

A $3
Y 7:0 - 7:0
1
B $add

Fig. 2.19: Calling show -color maroon3 @new_cells -color cornflowerblue


p:* -notitle

2.3. Scripting in Yosys 46

You might also like