Yosys Manual

User Manual:

Open the PDF directly: View PDF PDF.
Page Count: 174

DownloadYosys Manual
Open PDF In BrowserView PDF
Yosys Manual
Clifford Wolf

Abstract
Most of today’s digital design is done in HDL code (mostly Verilog or VHDL) and with the help of HDL
synthesis tools.
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. It
this 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.
This document was originally published as bachelor thesis at the Vienna University of Technology [Wol13].

2

Abbreviations
AIG
ASIC
AST
BDD
BLIF
EDA
EDIF
ER Diagram
FOSS
FPGA
FSM
HDL
LPM
RTLIL
RTL
SAT
VHDL
VHSIC
YOSYS

And-Inverter-Graph
Application-Specific Integrated Circuit
Abstract Syntax Tree
Binary Decision Diagram
Berkeley Logic Interchange Format
Electronic Design Automation
Electronic Design Interchange Format
Entity-Relationship Diagram
Free and Open-Source Software
Field-Programmable Gate Array
Finite-state machine
Hardware Description Language
Library of Parameterized Modules
RTL Intermediate Language
Register Transfer Level
Satisfiability Problem
VHSIC Hardware Description Language
Very-High-Speed Integrated Circuit
Yosys Open SYnthesis Suite

3

Contents
1 Introduction

12

1.1

History of Yosys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

1.2

Structure of this Document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13

2 Basic Principles
2.1

14

Levels of Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

14

2.1.1

System Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

2.1.2

High Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

2.1.3

Behavioural Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

15

2.1.4

Register-Transfer Level (RTL) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

2.1.5

Logical Gate Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

2.1.6

Physical Gate Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

2.1.7

Switch Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

2.1.8

Yosys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

Features of Synthesizable Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17

2.2.1

Structural Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

2.2.2

Expressions in Verilog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

2.2.3

Behavioural Modelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

18

2.2.4

Functions and Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

19

2.2.5

Conditionals, Loops and Generate-Statements . . . . . . . . . . . . . . . . . . . . . .

19

2.2.6

Arrays and Memories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20

Challenges in Digital Circuit Synthesis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20

2.3.1

Standards Compliance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20

2.3.2

Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21

2.3.3

Technology Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21

2.4

Script-Based Synthesis Flows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21

2.5

Methods from Compiler Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

2.5.1

Lexing and Parsing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

22

2.5.2

Multi-Pass Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

24

2.2

2.3

4

CONTENTS
3 Approach

25

3.1

Data- and Control-Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

25

3.2

Internal Formats in Yosys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

3.3

Typical Use Case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

26

4 Implementation Overview

28

4.1

Simplified Data Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

28

4.2

The RTL Intermediate Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

29

4.2.1

RTLIL Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

30

4.2.2

RTLIL::Design and RTLIL::Module

. . . . . . . . . . . . . . . . . . . . . . . . . . .

31

4.2.3

RTLIL::Cell and RTLIL::Wire

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

31

4.2.4

RTLIL::SigSpec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

4.2.5

RTLIL::Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

32

4.2.6

RTLIL::Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

4.3

Command Interface and Synthesis Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

4.4

Source Tree and Build System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

35

5 Internal Cell Library
5.1

5.2

37

RTL Cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

5.1.1

Unary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

5.1.2

Binary Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

5.1.3

Multiplexers

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

5.1.4

Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

5.1.5

Memories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39

5.1.6

Finite State Machines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

42

Gates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

42

6 Programming Yosys Extensions

44

6.1

The “CodingReadme” File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

44

6.2

The “stubsnets” Example Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

49

5

CONTENTS
7 The Verilog and AST Frontends
7.1

52

Transforming Verilog to AST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

52

7.1.1

The Verilog Preprocessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

7.1.2

The Verilog Lexer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

7.1.3

The Verilog Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

Transforming AST to RTLIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

54

7.2.1

AST Simplification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

54

7.2.2

Generating RTLIL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

Synthesizing Verilog always Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

7.3.1

The ProcessGenerator Algorithm . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

58

7.3.2

The proc pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

7.4

Synthesizing Verilog Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

7.5

Synthesizing Parametric Designs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

7.2

7.3

8 Optimizations
8.1

8.2

8.3

Simple Optimizations

62
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

62

8.1.1

The opt_expr pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

62

8.1.2

The opt_muxtree pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

63

8.1.3

The opt_reduce pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

63

8.1.4

The opt_rmdff pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

8.1.5

The opt_clean pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

8.1.6

The opt_merge pass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

FSM Extraction and Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

64

8.2.1

FSM Detection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

65

8.2.2

FSM Extraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

65

8.2.3

FSM Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

66

8.2.4

FSM Recoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

67

Logic Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

67

9 Technology Mapping

68

9.1

Cell Substitution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68

9.2

Subcircuit Substitution

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

68

9.3

Gate-Level Technology Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

69

A Auxiliary Libraries

70

A.1 SHA1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

70

A.2 BigInt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

70

A.3 SubCircuit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

70

A.4 ezSAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

70

6

CONTENTS
B Auxiliary Programs

71

B.1 yosys-config . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

71

B.2 yosys-filterlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

71

B.3 yosys-abc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

71

C Command Reference Manual

72

C.1 abc – use ABC for technology mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

72

C.2 add – add objects to the design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

75

C.3 aigmap – map logic to and-inverter-graph circuit . . . . . . . . . . . . . . . . . . . . . . . .

75

C.4 alumacc – extract ALU and MACC cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

75

C.5 assertpmux – convert internal signals to module ports . . . . . . . . . . . . . . . . . . . . .

75

C.6 attrmap – renaming attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

76

C.7 attrmvcp – move or copy attributes from wires to driving cells

. . . . . . . . . . . . . . . .

76

C.8 cd – a shortcut for ’select -module ’ . . . . . . . . . . . . . . . . . . . . . . . . . . .

77

C.9 check – check for obvious problems in the design . . . . . . . . . . . . . . . . . . . . . . . .

77

C.10 chparam – re-evaluate modules with new parameters . . . . . . . . . . . . . . . . . . . . . .

78

C.11 clean – remove unused cells and wires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

78

C.12 clk2fflogic – convert clocked FFs to generic $ff cells . . . . . . . . . . . . . . . . . . . . . . .

78

C.13 connect – create or remove connections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

78

C.14 connwrappers – replace undef values with defined constants . . . . . . . . . . . . . . . . . .

79

C.15 copy – copy modules in the design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

C.16 cover – print code coverage counters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

79

C.17 delete – delete objects in the design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

80

C.18 deminout – demote inout ports to input or output . . . . . . . . . . . . . . . . . . . . . . .

81

C.19 design – save, restore and reset current design . . . . . . . . . . . . . . . . . . . . . . . . . .

81

C.20 dff2dffe – transform $dff cells to $dffe cells . . . . . . . . . . . . . . . . . . . . . . . . . . . .

81

C.21 dffinit – set INIT param on FF cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

82

C.22 dfflibmap – technology mapping of flip-flops . . . . . . . . . . . . . . . . . . . . . . . . . . .

82

C.23 dffsr2dff – convert DFFSR cells to simpler FF cell types . . . . . . . . . . . . . . . . . . . .

83

C.24 dump – print parts of the design in ilang format . . . . . . . . . . . . . . . . . . . . . . . .

83

C.25 echo – turning echoing back of commands on and off . . . . . . . . . . . . . . . . . . . . . .

83

C.26 edgetypes – list all types of edges in selection . . . . . . . . . . . . . . . . . . . . . . . . . .

83

C.27 equiv_add – add a $equiv cell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

84

C.28 equiv_induct – proving $equiv cells using temporal induction . . . . . . . . . . . . . . . . .

84

C.29 equiv_make – prepare a circuit for equivalence checking . . . . . . . . . . . . . . . . . . . .

84

C.30 equiv_mark – mark equivalence checking regions . . . . . . . . . . . . . . . . . . . . . . . .

85

C.31 equiv_miter – extract miter from equiv circuit . . . . . . . . . . . . . . . . . . . . . . . . .

85

7

CONTENTS
C.32 equiv_purge – purge equivalence checking module . . . . . . . . . . . . . . . . . . . . . . .

85

C.33 equiv_remove – remove $equiv cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

86

C.34 equiv_simple – try proving simple $equiv instances . . . . . . . . . . . . . . . . . . . . . . .

86

C.35 equiv_status – print status of equivalent checking module . . . . . . . . . . . . . . . . . . .

86

C.36 equiv_struct – structural equivalence checking . . . . . . . . . . . . . . . . . . . . . . . . .

86

C.37 eval – evaluate the circuit given an input . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

87

C.38 expose – convert internal signals to module ports . . . . . . . . . . . . . . . . . . . . . . . .

87

C.39 extract – find subcircuits and replace them with cells . . . . . . . . . . . . . . . . . . . . . .

88

C.40 flatten – flatten design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

C.41 freduce – perform functional reduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

90

C.42 fsm – extract and optimize finite state machines

. . . . . . . . . . . . . . . . . . . . . . . .

90

C.43 fsm_detect – finding FSMs in design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91

C.44 fsm_expand – expand FSM cells by merging logic into it . . . . . . . . . . . . . . . . . . . .

91

C.45 fsm_export – exporting FSMs to KISS2 files . . . . . . . . . . . . . . . . . . . . . . . . . .

92

C.46 fsm_extract – extracting FSMs in design . . . . . . . . . . . . . . . . . . . . . . . . . . . .

92

C.47 fsm_info – print information on finite state machines . . . . . . . . . . . . . . . . . . . . . .

92

C.48 fsm_map – mapping FSMs to basic logic . . . . . . . . . . . . . . . . . . . . . . . . . . . .

93

C.49 fsm_opt – optimize finite state machines . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

93

C.50 fsm_recode – recoding finite state machines . . . . . . . . . . . . . . . . . . . . . . . . . . .

93

C.51 greenpak4_counters – Extract GreenPak4 counter cells . . . . . . . . . . . . . . . . . . . . .

93

C.52 greenpak4_dffinv – merge greenpak4 inverters and DFFs . . . . . . . . . . . . . . . . . . . .

94

C.53 help – display help messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

94

C.54 hierarchy – check, expand and clean up design hierarchy . . . . . . . . . . . . . . . . . . . .

94

C.55 hilomap – technology mapping of constant hi- and/or lo-drivers . . . . . . . . . . . . . . . .

95

C.56 history – show last interactive commands . . . . . . . . . . . . . . . . . . . . . . . . . . . .

95

C.57 ice40_ffinit – iCE40: handle FF init values . . . . . . . . . . . . . . . . . . . . . . . . . . .

96

C.58 ice40_ffssr – iCE40: merge synchronous set/reset into FF cells . . . . . . . . . . . . . . . .

96

C.59 ice40_opt – iCE40: perform simple optimizations . . . . . . . . . . . . . . . . . . . . . . . .

96

C.60 insbuf – insert buffer cells for connected wires . . . . . . . . . . . . . . . . . . . . . . . . . .

96

C.61 iopadmap – technology mapping of i/o pads (or buffers) . . . . . . . . . . . . . . . . . . . .

97

C.62 json – write design in JSON format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

97

C.63 log – print text and log files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

C.64 ls – list modules or objects in modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

C.65 lut2mux – convert $lut to $_MUX_ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

C.66 maccmap – mapping macc cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

98

C.67 memory – translate memories to basic cells . . . . . . . . . . . . . . . . . . . . . . . . . . .

99

8

CONTENTS
C.68 memory_bram – map memories to block rams . . . . . . . . . . . . . . . . . . . . . . . . .

99

C.69 memory_collect – creating multi-port memory cells . . . . . . . . . . . . . . . . . . . . . . . 101
C.70 memory_dff – merge input/output DFFs into memories . . . . . . . . . . . . . . . . . . . . 101
C.71 memory_map – translate multiport memories to basic cells . . . . . . . . . . . . . . . . . . 101
C.72 memory_memx – emulate vlog sim behavior for mem ports . . . . . . . . . . . . . . . . . . 101
C.73 memory_share – consolidate memory ports . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
C.74 memory_unpack – unpack multi-port memory cells . . . . . . . . . . . . . . . . . . . . . . . 102
C.75 miter – automatically create a miter circuit . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
C.76 muxcover – cover trees of MUX cells with wider MUXes . . . . . . . . . . . . . . . . . . . . 103
C.77 nlutmap – map to LUTs of different sizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
C.78 opt – perform simple optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
C.79 opt_clean – remove unused cells and wires . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
C.80 opt_expr – perform const folding and simple expression rewriting . . . . . . . . . . . . . . . 104
C.81 opt_merge – consolidate identical cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
C.82 opt_muxtree – eliminate dead trees in multiplexer trees . . . . . . . . . . . . . . . . . . . . 105
C.83 opt_reduce – simplify large MUXes and AND/OR gates . . . . . . . . . . . . . . . . . . . . 105
C.84 opt_rmdff – remove DFFs with constant inputs . . . . . . . . . . . . . . . . . . . . . . . . . 106
C.85 plugin – load and list loaded plugins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
C.86 pmuxtree – transform $pmux cells to trees of $mux cells . . . . . . . . . . . . . . . . . . . . 106
C.87 prep – generic synthesis script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
C.88 proc – translate processes to netlists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
C.89 proc_arst – detect asynchronous resets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
C.90 proc_clean – remove empty parts of processes . . . . . . . . . . . . . . . . . . . . . . . . . . 109
C.91 proc_dff – extract flip-flops from processes . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
C.92 proc_dlatch – extract latches from processes . . . . . . . . . . . . . . . . . . . . . . . . . . 109
C.93 proc_init – convert initial block to init attributes . . . . . . . . . . . . . . . . . . . . . . . . 109
C.94 proc_mux – convert decision trees to multiplexers . . . . . . . . . . . . . . . . . . . . . . . 109
C.95 proc_rmdead – eliminate dead trees in decision trees . . . . . . . . . . . . . . . . . . . . . . 110
C.96 qwp – quadratic wirelength placer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
C.97 read_blif – read BLIF file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
C.98 read_ilang – read modules from ilang file . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
C.99 read_liberty – read cells from liberty file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
C.100read_verilog – read modules from Verilog file . . . . . . . . . . . . . . . . . . . . . . . . . . 111
C.101rename – rename object in the design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
C.102sat – solve a SAT problem in the circuit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
C.103scatter – add additional intermediate nets . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
9

CONTENTS
C.104scc – detect strongly connected components (logic loops) . . . . . . . . . . . . . . . . . . . . 117
C.105script – execute commands from script file . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
C.106select – modify and view the list of selected objects . . . . . . . . . . . . . . . . . . . . . . . 118
C.107setattr – set/unset attributes on objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
C.108setparam – set/unset parameters on objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
C.109setundef – replace undef values with defined constants . . . . . . . . . . . . . . . . . . . . . 122
C.110share – perform sat-based resource sharing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
C.111shell – enter interactive command mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
C.112show – generate schematics using graphviz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
C.113shregmap – map shift registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
C.114simplemap – mapping simple coarse-grain cells . . . . . . . . . . . . . . . . . . . . . . . . . 127
C.115singleton – create singleton modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
C.116splice – create explicit splicing cells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
C.117splitnets – split up multi-bit nets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
C.118stat – print some statistics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
C.119submod – moving part of a module to a new submodule . . . . . . . . . . . . . . . . . . . . 129
C.120synth – generic synthesis script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
C.121synth_gowin – synthesis for Gowin FPGAs . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
C.122synth_greenpak4 – synthesis for GreenPAK4 FPGAs . . . . . . . . . . . . . . . . . . . . . . 132
C.123synth_ice40 – synthesis for iCE40 FPGAs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
C.124synth_xilinx – synthesis for Xilinx FPGAs . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
C.125tcl – execute a TCL script file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
C.126techmap – generic technology mapper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
C.127tee – redirect command output to file

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

C.128test_abcloop – automatically test handling of loops in abc command . . . . . . . . . . . . . 140
C.129test_autotb – generate simple test benches . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
C.130test_cell – automatically test the implementation of a cell type . . . . . . . . . . . . . . . . 141
C.131torder – print cells in topological order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
C.132trace – redirect command output to file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
C.133tribuf – infer tri-state buffers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
C.134verific – load Verilog and VHDL designs using Verific . . . . . . . . . . . . . . . . . . . . . . 142
C.135verilog_defaults – set default options for read_verilog . . . . . . . . . . . . . . . . . . . . . 143
C.136vhdl2verilog – importing VHDL designs using vhdl2verilog . . . . . . . . . . . . . . . . . . . 143
C.137wreduce – reduce the word size of operations if possible . . . . . . . . . . . . . . . . . . . . 144
C.138write_blif – write design to BLIF file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
C.139write_btor – write design to BTOR file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
10

CONTENTS
C.140write_edif – write design to EDIF netlist file . . . . . . . . . . . . . . . . . . . . . . . . . . 146
C.141write_file – write a text to a file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
C.142write_ilang – write design to ilang file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
C.143write_intersynth – write design to InterSynth netlist file . . . . . . . . . . . . . . . . . . . . 146
C.144write_json – write design to a JSON file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
C.145write_smt2 – write design to SMT-LIBv2 file . . . . . . . . . . . . . . . . . . . . . . . . . . 151
C.146write_smv – write design to SMV file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
C.147write_spice – write design to SPICE netlist file . . . . . . . . . . . . . . . . . . . . . . . . . 153
C.148write_verilog – write design to Verilog file . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
C.149zinit – add inverters so all FF are zero-initialized . . . . . . . . . . . . . . . . . . . . . . . . 155
D Application Notes

156

11

Chapter 1

Introduction
This document presents the Free and Open Source (FOSS) Verilog HDL synthesis tool “Yosys”. Its design
and implementation as well as its performance on real-world designs is discussed in this document.

1.1

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 [Ver06][Ver02] and
VHDL1 [VHD09][VHD04]. 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 applicationspecific HDL synthesis tool emerged. It was soon realised that a synthesis tool that understood 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 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
VHDL2 . So the existing FOSS Verilog synthesis tools were evaluated (see App. ??). 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 VHDL is an acronym for “VHSIC hardware description language” and VHSIC is an acronym for “Very-High-Speed
Integrated Circuits”.
2 A quick investigation into FOSS VHDL tools yielded similar grim results for FOSS VHDL synthesis tools.

12

CHAPTER 1. INTRODUCTION

1.2

Structure of this Document

The structure of this document is as follows:
Chapter 1 is this introduction.
Chapter 2 covers a short introduction to the world of HDL synthesis. Basic principles and the terminology
are outlined in this chapter.
Chapter 3 gives the quickest possible outline to how the problem of implementing a HDL synthesis tool is
approached in the case of Yosys.
Chapter 4 contains a more detailed overview of the implementation of Yosys. This chapter covers the data
structures used in Yosys to represent a design in detail and is therefore recommended reading for everyone
who is interested in understanding the Yosys internals.
Chapter 5 covers the internal cell library used by Yosys. This is especially important knowledge for anyone
who wants to understand the intermediate netlists used internally by Yosys.
Chapter 6 gives a tour to the internal APIs of Yosys. This is recommended reading for everyone who
actually wants to read or write Yosys source code. The chapter concludes with an example loadable module
for Yosys.
Chapters 7, 8, and 9 cover three important pieces of the synthesis pipeline: The Verilog frontend, the
optimization passes and the technology mapping to the target architecture, respectively.
Chapter ?? covers the evaluation of the performance (correctness and quality) of Yosys on real-world input
data. The chapter concludes the main part of this document with conclusions and outlook to future work.
Various appendices, including a command reference manual (App. C) and an evaluation of pre-existing
FOSS Verilog synthesis tools (App. ??) complete this document.

13

Chapter 2

Basic Principles
This chapter contains a short introduction to the basic principles of digital circuit synthesis.

2.1

Levels of Abstraction

Digital circuits can be represented at different levels of abstraction. During the design process a circuit is
usually first specified using a higher level abstraction. Implementation can then be understood as finding a
functionally equivalent representation at a lower abstraction level. When this is done automatically using
software, the term synthesis is used.
So synthesis is the automatic conversion of a high-level representation of a circuit to a functionally equivalent low-level representation of a circuit. Figure 2.1 lists the different levels of abstraction and how they
relate to different kinds of synthesis.
Regardless of the way a lower level representation of a circuit is obtained (synthesis or manual design),
the lower level representation is usually verified by comparing simulation results of the lower level and
the higher level representation 1 . Therefore even if no synthesis is used, there must still be a simulatable
representation of the circuit in all levels to allow for verification of the design.
1 In recent years formal equivalence checking also became an important verification method for validating RTL and lower
abstraction representation of the design.

System Level
System Design
High Level
High Level Synthesis (HLS)
Behavioral Level
Behavioral Synthesis
Register-Transfer Level (RTL)
RTL Synthesis
Logical Gate Level
Logic Synthesis
Physical Gate Level
Cell Library
Switch Level
Figure 2.1: Different levels of abstraction and synthesis.

14

Yosys

CHAPTER 2. BASIC PRINCIPLES
Note: The exact meaning of terminology such as “High-Level” is of course not fixed over time. For example
the HDL “ABEL” was first introduced in 1985 as “A High-Level Design Language for Programmable Logic
Devices” [LHBB85], but would not be considered a “High-Level Language” today.

2.1.1

System Level

The System Level abstraction of a system only looks at its biggest building blocks like CPUs and computing
cores. At this level the circuit is usually described using traditional programming languages like C/C++ or
Matlab. Sometimes special software libraries are used that are aimed at simulation circuits on the system
level, such as SystemC.
Usually no synthesis tools are used to automatically transform a system level representation of a circuit to
a lower-level representation. But system level design tools exist that can be used to connect system level
building blocks.
The IEEE 1685-2009 standard defines the IP-XACT file format that can be used to represent designs on
the system level and building blocks that can be used in such system level designs. [IP-10]

2.1.2

High Level

The high-level abstraction of a system (sometimes referred to as algorithmic level) is also often represented
using traditional programming languages, but with a reduced feature set. For example when representing
a design at the high level abstraction in C, pointers can only be used to mimic concepts that can be found
in hardware, such as memory interfaces. Full featured dynamic memory management is not allowed as it
has no corresponding concept in digital circuits.
Tools exist to synthesize high level code (usually in the form of C/C++/SystemC code with additional
metadata) to behavioural HDL code (usually in the form of Verilog or VHDL code). Aside from the many
commercial tools for high level synthesis there are also a number of FOSS tools for high level synthesis
[16] [19].

2.1.3

Behavioural Level

At the behavioural abstraction level a language aimed at hardware description such as Verilog or VHDL
is used to describe the circuit, but so-called behavioural modelling is used in at least part of the circuit
description. In behavioural modelling there must be a language feature that allows for imperative programming to be used to describe data paths and registers. This is the always-block in Verilog and the
process-block in VHDL.
In behavioural modelling, code fragments are provided together with a sensitivity list; a list of signals and
conditions. In simulation, the code fragment is executed whenever a signal in the sensitivity list changes
its value or a condition in the sensitivity list is triggered. A synthesis tool must be able to transfer this
representation into an appropriate datapath followed by the appropriate types of register.
For example consider the following Verilog code fragment:
1
2

always @(posedge clk)
y <= a + b;

In simulation the statement y <= a + b is executed whenever a positive edge on the signal clk is detected.
The synthesis result however will contain an adder that calculates the sum a + b all the time, followed by
a d-type flip-flop with the adder output on its D-input and the signal y on its Q-output.

15

CHAPTER 2. BASIC PRINCIPLES
Usually the imperative code fragments used in behavioural modelling can contain statements for conditional
execution (if- and case-statements in Verilog) as well as loops, as long as those loops can be completely
unrolled.
Interestingly there seems to be no other FOSS Tool that is capable of performing Verilog or VHDL
behavioural syntheses besides Yosys (see App. ??).

2.1.4

Register-Transfer Level (RTL)

On the Register-Transfer Level the design is represented by combinatorial data paths and registers (usually
d-type flip flops). The following Verilog code fragment is equivalent to the previous Verilog example, but
is in RTL representation:
1
2
3
4

assign tmp = a + b;

// combinatorial data path

always @(posedge clk)

// register

y <= tmp;

A design in RTL representation is usually stored using HDLs like Verilog and VHDL. But only a very
limited subset of features is used, namely minimalistic always-blocks (Verilog) or process-blocks (VHDL)
that model the register type used and unconditional assignments for the datapath logic. The use of
HDLs on this level simplifies simulation as no additional tools are required to simulate a design in RTL
representation.
Many optimizations and analyses can be performed best at the RTL level. Examples include FSM detection
and optimization, identification of memories or other larger building blocks and identification of shareable
resources.
Note that RTL is the first abstraction level in which the circuit is represented as a graph of circuit elements
(registers and combinatorial cells) and signals. Such a graph, when encoded as list of cells and connections,
is called a netlist.
RTL synthesis is easy as each circuit node element in the netlist can simply be replaced with an equivalent
gate-level circuit. However, usually the term RTL synthesis does not only refer to synthesizing an RTL
netlist to a gate level netlist but also to performing a number of highly sophisticated optimizations within
the RTL representation, such as the examples listed above.
A number of FOSS tools exist that can perform isolated tasks within the domain of RTL synthesis steps.
But there seems to be no FOSS tool that covers a wide range of RTL synthesis operations.

2.1.5

Logical Gate Level

At the logical gate level the design is represented by a netlist that uses only cells from a small number
of single-bit cells, such as basic logic gates (AND, OR, NOT, XOR, etc.) and registers (usually D-Type
Flip-flops).
A number of netlist formats exists that can be used on this level, e.g. the Electronic Design Interchange
Format (EDIF), but for ease of simulation often a HDL netlist is used. The latter is a HDL file (Verilog
or VHDL) that only uses the most basic language constructs for instantiation and connecting of cells.
There are two challenges in logic synthesis: First finding opportunities for optimizations within the gate
level netlist and second the optimal (or at least good) mapping of the logic gate netlist to an equivalent
netlist of physically available gate types.
The simplest approach to logic synthesis is two-level logic synthesis, where a logic function is converted
into a sum-of-products representation, e.g. using a Karnaugh map. This is a simple approach, but has
16

CHAPTER 2. BASIC PRINCIPLES
exponential worst-case effort and cannot make efficient use of physical gates other than AND/NAND-,
OR/NOR- and NOT-Gates.
Therefore modern logic synthesis tools utilize much more complicated multi-level logic synthesis algorithms
[BHSV90]. Most of these algorithms convert the logic function to a Binary-Decision-Diagram (BDD) or
And-Inverter-Graph (AIG) and work from that representation. The former has the advantage that it has a
unique normalized form. The latter has much better worst case performance and is therefore better suited
for the synthesis of large logic functions.
Good FOSS tools exists for multi-level logic synthesis [27] [26] [28].
Yosys contains basic logic synthesis functionality but can also use ABC [27] for the logic synthesis step.
Using ABC is recommended.

2.1.6

Physical Gate Level

On the physical gate level only gates are used that are physically available on the target architecture. In
some cases this may only be NAND, NOR and NOT gates as well as D-Type registers. In other cases
this might include cells that are more complex than the cells used at the logical gate level (e.g. complete
half-adders). In the case of an FPGA-based design the physical gate level representation is a netlist of
LUTs with optional output registers, as these are the basic building blocks of FPGA logic cells.
For the synthesis tool chain this abstraction is usually the lowest level. In case of an ASIC-based design
the cell library might contain further information on how the physical cells map to individual switches
(transistors).

2.1.7

Switch Level

A switch level representation of a circuit is a netlist utilizing single transistors as cells. Switch level
modelling is possible in Verilog and VHDL, but is seldom used in modern designs, as in modern digital
ASIC or FPGA flows the physical gates are considered the atomic build blocks of the logic circuit.

2.1.8

Yosys

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.

2.2

Features of Synthesizable Verilog

The subset of Verilog [Ver06] that is synthesizable is specified in a separate IEEE standards document,
the IEEE standard 1364.1-2002 [Ver02]. This standard also describes how certain language constructs are
to be interpreted in the scope of synthesis.
This section provides a quick overview of the most important features of synthesizable Verilog, structured
in order of increasing complexity.

17

CHAPTER 2. BASIC PRINCIPLES

2.2.1

Structural Verilog

Structural Verilog (also known as Verilog Netlists) is a Netlist in Verilog syntax. Only the following
language constructs are used in this case:
• Constant values
• Wire and port declarations
• Static assignments of signals to other signals
• Cell instantiations
Many tools (especially at the back end of the synthesis chain) only support structural Verilog as input.
ABC is an example of such a tool. Unfortunately there is no standard specifying what Structural Verilog
actually is, leading to some confusion about what syntax constructs are supported in structural Verilog
when it comes to features such as attributes or multi-bit signals.

2.2.2

Expressions in Verilog

In all situations where Verilog accepts a constant value or signal name, expressions using arithmetic
operations such as +, - and *, boolean operations such as & (AND), | (OR) and ^ (XOR) and many others
(comparison operations, unary operator, etc.) can also be used.
During synthesis these operators are replaced by cells that implement the respective function.
Many FOSS tools that claim to be able to process Verilog in fact only support basic structural Verilog and
simple expressions. Yosys can be used to convert full featured synthesizable Verilog to this simpler subset,
thus enabling such applications to be used with a richer set of Verilog features.

2.2.3

Behavioural Modelling

Code that utilizes the Verilog always statement is using Behavioural Modelling. In behavioural modelling,
a circuit is described by means of imperative program code that is executed on certain events, namely any
change, a rising edge, or a falling edge of a signal. This is a very flexible construct during simulation but
is only synthesizable when one of the following is modelled:
• Asynchronous or latched logic
In this case the sensitivity list must contain all expressions that are used within the always block.
The syntax @* can be used for these cases. Examples of this kind include:
1
2
3
4
5
6
7
8
9
10
11
12
13

// asynchronous
always @* begin
if (add_mode)
y <= a + b;
else
y <= a - b;
end
// latched
always @* begin
if (!hold)
y <= a + b;
end

18

CHAPTER 2. BASIC PRINCIPLES
Note that latched logic is often considered bad style and in many cases just the result of sloppy HDL
design. Therefore many synthesis tools generate warnings whenever latched logic is generated.
• Synchronous logic (with optional synchronous reset)
This is logic with d-type flip-flops on the output. In this case the sensitivity list must only contain
the respective clock edge. Example:
1
2
3
4
5
6
7

// counter with synchronous reset
always @(posedge clk) begin
if (reset)
y <= 0;
else
y <= y + 1;
end

• Synchronous logic with asynchronous reset
This is logic with d-type flip-flops with asynchronous resets on the output. In this case the sensitivity
list must only contain the respective clock and reset edges. The values assigned in the reset branch
must be constant. Example:
1
2
3
4
5
6
7

// counter with asynchronous reset
always @(posedge clk, posedge reset) begin
if (reset)
y <= 0;
else
y <= y + 1;
end

Many synthesis tools support a wider subset of flip-flops that can be modelled using always-statements
(including Yosys). But only the ones listed above are covered by the Verilog synthesis standard and when
writing new designs one should limit herself or himself to these cases.
In behavioural modelling, blocking assignments (=) and non-blocking assignments (<=) can be used. The
concept of blocking vs. non-blocking assignment is one of the most misunderstood constructs in Verilog
[CI00].
The blocking assignment behaves exactly like an assignment in any imperative programming language,
while with the non-blocking assignment the right hand side of the assignment is evaluated immediately
but the actual update of the left hand side register is delayed until the end of the time-step. For example
the Verilog code a <= b; b <= a; exchanges the values of the two registers. See Sec. ?? for a more detailed
description of this behaviour.

2.2.4

Functions and Tasks

Verilog supports Functions and Tasks to bundle statements that are used in multiple places (similar to
Procedures in imperative programming). Both constructs can be implemented easily by substituting the
function/task-call with the body of the function or task.

2.2.5

Conditionals, Loops and Generate-Statements

Verilog supports if-else-statements and for-loops inside always-statements.
It also supports both features in generate-statements on the module level. This can be used to selectively
enable or disable parts of the module based on the module parameters (if-else) or to generate a set of
similar subcircuits (for).
19

CHAPTER 2. BASIC PRINCIPLES
While the if-else-statement inside an always-block is part of behavioural modelling, the three other cases
are (at least for a synthesis tool) part of a built-in macro processor. Therefore it must be possible for
the synthesis tool to completely unroll all loops and evaluate the condition in all if-else-statement in
generate-statements using const-folding.
Examples for this can be found in Fig. ?? and Fig. ?? in App. ??.

2.2.6

Arrays and Memories

Verilog supports arrays. This is in general a synthesizable language feature. In most cases arrays can be
synthesized by generating addressable memories. However, when complex or asynchronous access patterns
are used, it is not possible to model an array as memory. In these cases the array must be modelled using
individual signals for each word and all accesses to the array must be implemented using large multiplexers.
In some cases it would be possible to model an array using memories, but it is not desired. Consider the
following delay circuit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

module (clk, in_data, out_data);
parameter BITS = 8;
parameter STAGES = 4;
input clk;
input [BITS-1:0] in_data;
output [BITS-1:0] out_data;
reg [BITS-1:0] ffs [STAGES-1:0];
integer i;
always @(posedge clk) begin
ffs[0] <= in_data;
for (i = 1; i < STAGES; i = i+1)
ffs[i] <= ffs[i-1];
end
assign out_data = ffs[STAGES-1];
endmodule

This could be implemented using an addressable memory with STAGES input and output ports. A better
implementation would be to use a simple chain of flip-flops (a so-called shift register). This better implementation can either be obtained by first creating a memory-based implementation and then optimizing
it based on the static address signals for all ports or directly identifying such situations in the language
front end and converting all memory accesses to direct accesses to the correct signals.

2.3

Challenges in Digital Circuit Synthesis

This section summarizes the most important challenges in digital circuit synthesis. Tools can be characterized by how well they address these topics.

2.3.1

Standards Compliance

The most important challenge is compliance with the HDL standards in question (in case of Verilog the
IEEE Standards 1364.1-2002 and 1364-2005). This can be broken down in two items:
20

CHAPTER 2. BASIC PRINCIPLES
• Completeness of implementation of the standard
• Correctness of implementation of the standard
Completeness is mostly important to guarantee compatibility with existing HDL code. Once a design has
been verified and tested, HDL designers are very reluctant regarding changes to the design, even if it is
only about a few minor changes to work around a missing feature in a new synthesis tool.
Correctness is crucial. In some areas this is obvious (such as correct synthesis of basic behavioural models).
But it is also crucial for the areas that concern minor details of the standard, such as the exact rules for
handling signed expressions, even when the HDL code does not target different synthesis tools. This is
because (unlike software source code that is only processed by compilers), in most design flows HDL code
is not only processed by the synthesis tool but also by one or more simulators and sometimes even a formal
verification tool. It is key for this verification process that all these tools use the same interpretation for
the HDL code.

2.3.2

Optimizations

Generally it is hard to give a one-dimensional description of how well a synthesis tool optimizes the design.
First of all because not all optimizations are applicable to all designs and all synthesis tasks. Some
optimizations work (best) on a coarse-grained level (with complex cells such as adders or multipliers) and
others work (best) on a fine-grained level (single bit gates). Some optimizations target area and others
target speed. Some work well on large designs while others don’t scale well and can only be applied to
small designs.
A good tool is capable of applying a wide range of optimizations at different levels of abstraction and gives
the designer control over which optimizations are performed (or skipped) and what the optimization goals
are.

2.3.3

Technology Mapping

Technology mapping is the process of converting the design into a netlist of cells that are available in the
target architecture. In an ASIC flow this might be the process-specific cell library provided by the fab. In
an FPGA flow this might be LUT cells as well as special function units such as dedicated multipliers. In
a coarse-grain flow this might even be more complex special function units.
An open and vendor independent tool is especially of interest if it supports a wide range of different types
of target architectures.

2.4

Script-Based Synthesis Flows

A digital design is usually started by implementing a high-level or system-level simulation of the desired
function. This description is then manually transformed (or re-implemented) into a synthesizable lowerlevel description (usually at the behavioural level) and the equivalence of the two representations is verified
by simulating both and comparing the simulation results.
Then the synthesizable description is transformed to lower-level representations using a series of tools and
the results are again verified using simulation. This process is illustrated in Fig. 2.2.
In this example the System Level Model and the Behavioural Model are both manually written design
files. After the equivalence of system level model and behavioural model has been verified, the lower level
representations of the design can be generated using synthesis tools. Finally the RTL Model and the
Gate-Level Model are verified and the design process is finished.
21

CHAPTER 2. BASIC PRINCIPLES
synthesis
System Level
Model

Behavioral
Model
verify

synthesis
RTL
Model

verify

Gate-Level
Model
verify

Figure 2.2: Typical design flow. Green boxes represent manually created models. Orange boxes represent
models generated by synthesis tools.

However, in any real-world design effort there will be multiple iterations for this design process. The reason
for this can be the late change of a design requirement or the fact that the analysis of a low-abstraction
model (e.g. gate-level timing analysis) revealed that a design change is required in order to meet the design
requirements (e.g. maximum possible clock speed).
Whenever the behavioural model or the system level model is changed their equivalence must be re-verified
by re-running the simulations and comparing the results. Whenever the behavioural model is changed the
synthesis must be re-run and the synthesis results must be re-verified.
In order to guarantee reproducibility it is important to be able to re-run all automatic steps in a design
project with a fixed set of settings easily. Because of this, usually all programs used in a synthesis flow can
be controlled using scripts. This means that all functions are available via text commands. When such a
tool provides a GUI, this is complementary to, and not instead of, a command line interface.
Usually a synthesis flow in an UNIX/Linux environment would be controlled by a shell script that calls all
required tools (synthesis and simulation/verification in this example) in the correct order. Each of these
tools would be called with a script file containing commands for the respective tool. All settings required
for the tool would be provided by these script files so that no manual interaction would be necessary. These
script files are considered design sources and should be kept under version control just like the source code
of the system level and the behavioural model.

2.5

Methods from Compiler Design

Some parts of synthesis tools involve problem domains that are traditionally known from compiler design.
This section addresses some of these domains.

2.5.1

Lexing and Parsing

The best known concepts from compiler design are probably lexing and parsing. These are two methods
that together can be used to process complex computer languages easily. [ASU86]
A lexer consumes single characters from the input and generates a stream of lexical tokens that consist of
a type and a value. For example the Verilog input “assign foo = bar + 42;” might be translated by the
lexer to the list of lexical tokens given in Tab. 2.1.
The lexer is usually generated by a lexer generator (e.g. flex [17]) from a description file that is using
regular expressions to specify the text pattern that should match the individual tokens.
The lexer is also responsible for skipping ignored characters (such as whitespace outside string constants
and comments in the case of Verilog) and converting the original text snippet to a token value.
Note that individual keywords use different token types (instead of a keyword type with different token
values). This is because the parser usually can only use the Token-Type to make a decision on the
grammatical role of a token.

22

CHAPTER 2. BASIC PRINCIPLES
Token-Type
TOK_ASSIGN
TOK_IDENTIFIER
TOK_EQ
TOK_IDENTIFIER
TOK_PLUS
TOK_NUMBER
TOK_SEMICOLON

Token-Value
“foo”
“bar”
42
-

Table 2.1: Exemplary token list for the statement “assign

foo = bar + 42;”.

The parser then transforms the list of tokens into a parse tree that closely resembles the productions from
the computer languages grammar. As the lexer, the parser is also typically generated by a code generator
(e.g. bison [18]) from a grammar description in Backus-Naur Form (BNF).
Let’s consider the following BNF (in Bison syntax):
1
2

assign_stmt: TOK_ASSIGN TOK_IDENTIFIER TOK_EQ expr TOK_SEMICOLON;
expr: TOK_IDENTIFIER | TOK_NUMBER | expr TOK_PLUS expr;

The parser converts the token list to the parse tree in Fig. 2.3. Note that the parse tree never actually exists
as a whole as data structure in memory. Instead the parser calls user-specified code snippets (so-called
reduce-functions) for all inner nodes of the parse tree in depth-first order.
In some very simple applications (e.g. code generation for stack machines) it is possible to perform the
task at hand directly in the reduce functions. But usually the reduce functions are only used to build an
in-memory data structure with the relevant information from the parse tree. This data structure is called
an abstract syntax tree (AST).
The exact format for the abstract syntax tree is application specific (while the format of the parse tree
and token list are mostly dictated by the grammar of the language at hand). Figure 2.4 illustrates what
an AST for the parse tree in Fig. 2.3 could look like.
Usually the AST is then converted into yet another representation that is more suitable for further processing. In compilers this is often an assembler-like three-address-code intermediate representation. [ASU86]

assign_stmt

TOK_EQ

TOK_ASSIGN

TOK_SEMICOLON
expr

TOK_IDENTIFIER

expr

expr

TOK_PLUS

TOK_IDENTIFIER

TOK_NUMBER

Figure 2.3: Example parse tree for the Verilog expression “assign

23

foo = bar + 42;”.

CHAPTER 2. BASIC PRINCIPLES
ASSIGN

PLUS

ID: foo

CONST: 42

ID: bar

Figure 2.4: Example abstract syntax tree for the Verilog expression “assign

2.5.2

foo = bar + 42;”.

Multi-Pass Compilation

Complex problems are often best solved when split up into smaller problems. This is certainly true for
compilers as well as for synthesis tools. The components responsible for solving the smaller problems can
be connected in two different ways: through Single-Pass Pipelining and by using Multiple Passes.
Traditionally a parser and lexer are connected using the pipelined approach: The lexer provides a function
that is called by the parser. This function reads data from the input until a complete lexical token has
been read. Then this token is returned to the parser. So the lexer does not first generate a complete list
of lexical tokens and then pass it to the parser. Instead they run concurrently and the parser can consume
tokens as the lexer produces them.
The single-pass pipelining approach has the advantage of lower memory footprint (at no time must the
complete design be kept in memory) but has the disadvantage of tighter coupling between the interacting
components.
Therefore single-pass pipelining should only be used when the lower memory footprint is required or the
components are also conceptually tightly coupled. The latter certainly is the case for a parser and its
lexer. But when data is passed between two conceptually loosely coupled components it is often beneficial
to use a multi-pass approach.
In the multi-pass approach the first component processes all the data and the result is stored in a inmemory data structure. Then the second component is called with this data. This reduces complexity,
as only one component is running at a time. It also improves flexibility as components can be exchanged
easier.
Most modern compilers are multi-pass compilers.

24

Chapter 3

Approach
Yosys is a tool for synthesising (behavioural) Verilog HDL code to target architecture netlists. Yosys aims
at a wide range of application domains and thus must be flexible and easy to adapt to new tasks. This
chapter covers the general approach followed in the effort to implement this tool.

3.1

Data- and Control-Flow

The data- and control-flow of a typical synthesis tool is very similar to the data- and control-flow of
a typical compiler: different subsystems are called in a predetermined order, each consuming the data
generated by the last subsystem and generating the data for the next subsystem (see Fig. 3.1).
The first subsystem to be called is usually called a frontend. It does not process the data generated by
another subsystem but instead reads the user input—in the case of a HDL synthesis tool, the behavioural
HDL code.
The subsystems that consume data from previous subsystems and produce data for the next subsystems
(usually in the same or a similar format) are called passes.
The last subsystem that is executed transforms the data generated by the last pass into a suitable output
format and writes it to a disk file. This subsystem is usually called the backend.
In Yosys all frontends, passes and backends are directly available as commands in the synthesis script.
Thus the user can easily create a custom synthesis flow just by calling passes in the right order in a
synthesis script.
High-Level

HDL

Backend

Pass

Pass

Pass

Frontend

Low-Level

Internal Format(s)
Figure 3.1: General data- and control-flow of a synthesis tool

25

Netlist

CHAPTER 3. APPROACH

3.2

Internal Formats in Yosys

Yosys uses two different internal formats. The first is used to store an abstract syntax tree (AST) of a
Verilog input file. This format is simply called AST and is generated by the Verilog Frontend. This data
structure is consumed by a subsystem called AST Frontend1 . This AST Frontend then generates a design in
Yosys’ main internal format, the Register-Transfer-Level-Intermediate-Language (RTLIL) representation.
It does that by first performing a number of simplifications within the AST representation and then
generating RTLIL from the simplified AST data structure.
The RTLIL representation is used by all passes as input and outputs. This has the following advantages
over using different representational formats between different passes:
• The passes can be rearranged in a different order and passes can be removed or inserted.
• Passes can simply pass-thru the parts of the design they don’t change without the need to convert
between formats. In fact Yosys passes output the same data structure they received as input and
performs all changes in place.
• All passes use the same interface, thus reducing the effort required to understand a pass when reading
the Yosys source code, e.g. when adding additional features.
The RTLIL representation is basically a netlist representation with the following additional features:
• An internal cell library with fixed-function cells to represent RTL datapath and register cells as well
as logical gate-level cells (single-bit gates and registers).
• Support for multi-bit values that can use individual bits from wires as well as constant bits to
represent coarse-grain netlists.
• Support for basic behavioural constructs (if-then-else structures and multi-case switches with a sensitivity list for updating the outputs).
• Support for multi-port memories.
The use of RTLIL also has the disadvantage of having a very powerful format between all passes, even
when doing gate-level synthesis where the more advanced features are not needed. In order to reduce
complexity for passes that operate on a low-level representation, these passes check the features used in
the input RTLIL and fail to run when unsupported high-level constructs are used. In such cases a pass that
transforms the higher-level constructs to lower-level constructs must be called from the synthesis script
first.

3.3

Typical Use Case

The following example script may be used in a synthesis flow to convert the behavioural Verilog code from
the input file design.v to a gate-level netlist synth.v using the cell library described by the Liberty file
[25] cells.lib:
1
2
3
4
5

# read input file to internal representation
read_verilog design.v
# convert high-level behavioral parts ("processes") to d-type flip-flops and muxes
proc
1 In

Yosys the term pass is only used to refer to commands that operate on the RTLIL data structure.

26

CHAPTER 3. APPROACH
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# perform some simple optimizations
opt
# convert high-level memory constructs to d-type flip-flops and multiplexers
memory
# perform some simple optimizations
opt
# convert design to (logical) gate-level netlists
techmap
# perform some simple optimizations
opt
# map internal register types to the ones from the cell library
dfflibmap -liberty cells.lib
# use ABC to map remaining logic to cells from the cell library
abc -liberty cells.lib
# cleanup
opt
# write results to output file
write_verilog synth.v

A detailed description of the commands available in Yosys can be found in App. C.

27

Chapter 4

Implementation Overview
Yosys is an extensible open source hardware synthesis tool. It is aimed at designers who are looking for an
easily accessible, universal, and vendor-independent synthesis tool, as well as scientists who do research in
electronic design automation (EDA) and are looking for an open synthesis framework that can be used to
test algorithms on complex real-world designs.
Yosys can synthesize a large subset of Verilog 2005 and has been tested with a wide range of real-world
designs, including the OpenRISC 1200 CPU [23], the openMSP430 CPU [22], the OpenCores I2 C master
[20] and the k68 CPU [21].
As of this writing a Yosys VHDL frontend is in development.
Yosys is written in C++ (using some features from the new C++11 standard). This chapter describes
some of the fundamental Yosys data structures. For the sake of simplicity the C++ type names used in
the Yosys implementation are used in this chapter, even though the chapter only explains the conceptual
idea behind it and can be used as reference to implement a similar system in any language.

4.1

Simplified Data Flow

Figure 4.1 shows the simplified data flow within Yosys. Rectangles in the figure represent program modules
and ellipses internal data structures that are used to exchange design data between the program modules.
Design data is read in using one of the frontend modules. The high-level HDL frontends for Verilog and
VHDL code generate an abstract syntax tree (AST) that is then passed to the AST frontend. Note that
both HDL frontends use the same AST representation that is powerful enough to cover the Verilog HDL
and VHDL language.
The AST Frontend then compiles the AST to Yosys’s main internal data format, the RTL Intermediate
Language (RTLIL). A more detailed description of this format is given in the next section.
There is also a text representation of the RTLIL data structure that can be parsed using the ILANG
Frontend.
The design data may then be transformed using a series of passes that all operate on the RTLIL representation of the design.
Finally the design in RTLIL representation is converted back to text by one of the backends, namely the
Verilog Backend for generating Verilog netlists and the ILANG Backend for writing the RTLIL data in
the same format that is understood by the ILANG Frontend.
With the exception of the AST Frontend, which is called by the high-level HDL frontends and can’t be
called directly by the user, all program modules are called by the user (usually using a synthesis script
that contains text commands for Yosys).
28

CHAPTER 4. IMPLEMENTATION OVERVIEW

Verilog Frontend

VHDL Frontend

ILANG Frontend

AST

AST Frontend

RTLIL

Verilog Backend

ILANG Backend

Passes

Other Backends

Figure 4.1: Yosys simplified data flow (ellipses: data structures, rectangles: program modules)

By combining passes in different ways and/or adding additional passes to Yosys it is possible to adapt
Yosys to a wide range of applications. For this to be possible it is key that (1) all passes operate on the
same data structure (RTLIL) and (2) that this data structure is powerful enough to represent the design
in different stages of the synthesis.

4.2

The RTL Intermediate Language

All frontends, passes and backends in Yosys operate on a design in RTLIL1 representation. The only
exception are the high-level frontends that use the AST representation as an intermediate step before
generating RTLIL data.
In order to avoid reinventing names for the RTLIL classes, they are simply referred to by their full C++
name, i.e. including the RTLIL:: namespace prefix, in this document.
Figure 4.2 shows a simplified Entity-Relationship Diagram (ER Diagram) of RTLIL. In 1 : N relationships
the arrow points from the N side to the 1. For example one RTLIL::Design contains N (zero to many)
instances of RTLIL::Module. A two-pointed arrow indicates a 1 : 1 relationship.
The RTLIL::Design is the root object of the RTLIL data structure. There is always one “current design”
in memory which passes operate on, frontends add data to and backends convert to exportable formats.
But in some cases passes internally generate additional RTLIL::Design objects. For example when a pass
is reading an auxiliary Verilog file such as a cell library, it might create an additional RTLIL::Design object
and call the Verilog frontend with this other object to parse the cell library.
There is only one active RTLIL::Design object that is used by all frontends, passes and backends called
by the user, e.g. using a synthesis script. The RTLIL::Design then contains zero to many RTLIL::Module
objects. This corresponds to modules in Verilog or entities in VHDL. Each module in turn contains objects
from three different categories:
1 The Language in RTL Intermediate Language refers to the fact, that RTLIL also has a text representation, usually
referred to as Intermediate Language (ILANG).

29

CHAPTER 4. IMPLEMENTATION OVERVIEW

RTLIL::Cell

RTLIL::Design

1

N

RTLIL::Module

RTLIL::Wire

RTLIL::SyncRule

RTLIL::Process

RTLIL::CaseRule

RTLIL::Memory

RTLIL::SwitchRule

Figure 4.2: Simplified RTLIL Entity-Relationship Diagram

• RTLIL::Cell and RTLIL::Wire objects represent classical netlist data.
• RTLIL::Process objects represent the decision trees (if-then-else statements, etc.) and synchronization declarations (clock signals and sensitivity) from Verilog always and VHDL process blocks.
• RTLIL::Memory objects represent addressable memories (arrays).
Usually the output of the synthesis procedure is a netlist, i.e. all RTLIL::Process and RTLIL::Memory
objects must be replaced by RTLIL::Cell and RTLIL::Wire objects by synthesis passes.
All features of the HDL that cannot be mapped directly to these RTLIL classes must be transformed to an
RTLIL-compatible representation by the HDL frontend. This includes Verilog-features such as generateblocks, loops and parameters.
The following sections contain a more detailed description of the different parts of RTLIL and rationale
behind some of the design decisions.

4.2.1

RTLIL Identifiers

All identifiers in RTLIL (such as module names, port names, signal names, cell types, etc.) follow the
following naming convention: they must either start with a backslash (\) or a dollar sign ($).
Identifiers starting with a backslash are public visible identifiers. Usually they originate from one of the
HDL input files. For example the signal name “\sig42” is most likely a signal that was declared using the
name “sig42” in an HDL input file. On the other hand the signal name “$sig42” is an auto-generated
signal name. The backends convert all identifiers that start with a dollar sign to identifiers that do not
collide with identifiers that start with a backslash.
This has three advantages:
• First, it is impossible that an auto-generated identifier collides with an identifier that was provided
by the user.
• Second, the information about which identifiers were originally provided by the user is always available which can help guide some optimizations. For example the “opt_rmunused” tries to preserve
signals with a user-provided name but doesn’t hesitate to delete signals that have auto-generated
names when they just duplicate other signals.
30

CHAPTER 4. IMPLEMENTATION OVERVIEW
• Third, the delicate job of finding suitable auto-generated public visible names is deferred to one
central location. Internally auto-generated names that may hold important information for Yosys
developers can be used without disturbing external tools. For example the Verilog backend assigns
names in the form _integer_.
In order to avoid programming errors, the RTLIL data structures check if all identifiers start with either
a backslash or a dollar sign and generate a runtime error if this rule is violated.
All RTLIL identifiers are case sensitive.

4.2.2

RTLIL::Design and RTLIL::Module

The RTLIL::Design object is basically just a container for RTLIL::Module objects. In addition to a list of
RTLIL::Module objects the RTLIL::Design also keeps a list of selected objects, i.e. the objects that passes
should operate on. In most cases the whole design is selected and therefore passes operate on the whole
design. But this mechanism can be useful for more complex synthesis jobs in which only parts of the design
should be affected by certain passes.
Besides the objects shown in the ER diagram in Fig. 4.2 an RTLIL::Module object contains the following
additional properties:
• The module name
• A list of attributes
• A list of connections between wires
• An optional frontend callback used to derive parametrized variations of the module
The attributes can be Verilog attributes imported by the Verilog frontend or attributes assigned by passes.
They can be used to store additional metadata about modules or just mark them to be used by certain
part of the synthesis script but not by others.
Verilog and VHDL both support parametric modules (known as “generic entities” in VHDL). The RTLIL
format does not support parametric modules itself. Instead each module contains a callback function into
the AST frontend to generate a parametrized variation of the RTLIL::Module as needed. This callback then
returns the auto-generated name of the parametrized variation of the module. (A hash over the parameters
and the module name is used to prohibit the same parametrized variation from being generated twice. For
modules with only a few parameters, a name directly containing all parameters is generated instead of a
hash string.)

4.2.3

RTLIL::Cell and RTLIL::Wire

A module contains zero to many RTLIL::Cell and RTLIL::Wire objects. Objects of these types are used
to model netlists. Usually the goal of all synthesis efforts is to convert all modules to a state where the
functionality of the module is implemented only by cells from a given cell library and wires to connect
these cells with each other. Note that module ports are just wires with a special property.
An RTLIL::Wire object has the following properties:
• The wire name
• A list of attributes
• A width (buses are just wires with a width > 1)
31

CHAPTER 4. IMPLEMENTATION OVERVIEW
• If the wire is a port: port number and direction (input/output/inout)
As with modules, the attributes can be Verilog attributes imported by the Verilog frontend or attributes
assigned by passes.
In Yosys, busses (signal vectors) are represented using a single wire object with a width > 1. So Yosys
does not convert signal vectors to individual signals. This makes some aspects of RTLIL more complex
but enables Yosys to be used for coarse grain synthesis where the cells of the target architecture operate
on entire signal vectors instead of single bit wires.
An RTLIL::Cell object has the following properties:
• The cell name and type
• A list of attributes
• A list of parameters (for parametric cells)
• Cell ports and the connections of ports to wires and constants
The connections of ports to wires are coded by assigning an RTLIL::SigSpec to each cell port. The
RTLIL::SigSpec data type is described in the next section.

4.2.4

RTLIL::SigSpec

A “signal” is everything that can be applied to a cell port. I.e.
• Any constant value of arbitrary bit-width
For example: 1337, 16’b0000010100111001, 1’b1, 1’bx
• All bits of a wire or a selection of bits from a wire
For example: mywire, mywire[24], mywire[15:8]
• Concatenations of the above
For example: {16’d1337, mywire[15:8]}
The RTLIL::SigSpec data type is used to represent signals. The RTLIL::Cell object contains one RTLIL::SigSpec
for each cell port.
In addition, connections between wires are represented using a pair of RTLIL::SigSpec objects. Such pairs
are needed in different locations. Therefore the type name RTLIL::SigSig was defined for such a pair.

4.2.5

RTLIL::Process

When a high-level HDL frontend processes behavioural code it splits it up into data path logic (e.g. the
expression a + b is replaced by the output of an adder that takes a and b as inputs) and an RTLIL::Process
that models the control logic of the behavioural code. Let’s consider a simple example:
1
2
3
4
5
6
7
8
9

module ff_with_en_and_async_reset(clock, reset, enable, d, q);
input clock, reset, enable, d;
output reg q;
always @(posedge clock, posedge reset)
if (reset)
q <= 0;
else if (enable)
q <= d;
endmodule

32

CHAPTER 4. IMPLEMENTATION OVERVIEW
In this example there is no data path and therefore the RTLIL::Module generated by the frontend only
contains a few RTLIL::Wire objects and an RTLIL::Process. The RTLIL::Process in ILANG syntax:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

process $proc$ff_with_en_and_async_reset.v:4$1
assign $0\q[0:0] \q
switch \reset
case 1’1
assign $0\q[0:0] 1’0
case
switch \enable
case 1’1
assign $0\q[0:0] \d
case
end
end
sync posedge \clock
update \q $0\q[0:0]
sync posedge \reset
update \q $0\q[0:0]
end

This RTLIL::Process contains two RTLIL::SyncRule objects, two RTLIL::SwitchRule objects and five
RTLIL::CaseRule objects. The wire $0\q[0:0] is an automatically created wire that holds the next value
of \q. The lines 2 . . . 12 describe how $0\q[0:0] should be calculated. The lines 13 . . . 16 describe how the
value of $0\q[0:0] is used to update \q.
An RTLIL::Process is a container for zero or more RTLIL::SyncRule objects and exactly one RTLIL::CaseRule
object, which is called the root case.
An RTLIL::SyncRule object contains an (optional) synchronization condition (signal and edge-type) and
zero or more assignments (RTLIL::SigSig).
An RTLIL::CaseRule is a container for zero or more assignments (RTLIL::SigSig) and zero or more
RTLIL::SwitchRule objects. An RTLIL::SwitchRule objects is a container for zero or more RTLIL::CaseRule
objects.
In the above example the lines 2 . . . 12 are the root case. Here $0\q[0:0] is first assigned the old value \q
as default value (line 2). The root case also contains an RTLIL::SwitchRule object (lines 3 . . . 12). Such an
object is very similar to the C switch statement as it uses a control signal (\reset in this case) to determine
which of its cases should be active. The RTLIL::SwitchRule object then contains one RTLIL::CaseRule
object per case. In this example there is a case2 for \reset == 1 that causes $0\q[0:0] to be set (lines 4
and 5) and a default case that in turn contains a switch that sets $0\q[0:0] to the value of \d if \enable
is active (lines 6 . . . 11).
The lines 13 . . . 16 then cause \q to be updated whenever there is a positive clock edge on \clock or \reset.
In order to generate such a representation, the language frontend must be able to handle blocking and
nonblocking assignments correctly. However, the language frontend does not need to identify the correct
type of storage element for the output signal or generate multiplexers for the decision tree. This is done
by passes that work on the RTLIL representation. Therefore it is relatively easy to substitute these
steps with other algorithms that target different target architectures or perform optimizations or other
transformations on the decision trees before further processing them.
One of the first actions performed on a design in RTLIL representation in most synthesis scripts is identifying asynchronous resets. This is usually done using the proc_arst pass. This pass transforms the above
example to the following RTLIL::Process:
2 The syntax 1’1 in the ILANG code specifies a constant with a length of one bit (the first “1”), and this bit is a one (the
second “1”).

33

CHAPTER 4. IMPLEMENTATION OVERVIEW

1
2
3
4
5
6
7
8
9
10
11
12

process $proc$ff_with_en_and_async_reset.v:4$1
assign $0\q[0:0] \q
switch \enable
case 1’1
assign $0\q[0:0] \d
case
end
sync posedge \clock
update \q $0\q[0:0]
sync high \reset
update \q 1’0
end

This pass has transformed the outer RTLIL::SwitchRule into a modified RTLIL::SyncRule object for the
\reset signal. Further processing converts the RTLIL::Process into e.g. a d-type flip-flop with asynchronous
reset and a multiplexer for the enable signal:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

cell $adff $procdff$6
parameter \ARST_POLARITY 1’1
parameter \ARST_VALUE 1’0
parameter \CLK_POLARITY 1’1
parameter \WIDTH 1
connect \ARST \reset
connect \CLK \clock
connect \D $0\q[0:0]
connect \Q \q
end
cell $mux $procmux$3
parameter \WIDTH 1
connect \A \q
connect \B \d
connect \S \enable
connect \Y $0\q[0:0]
end

Different combinations of passes may yield different results. Note that $adff and $mux are internal cell
types that still need to be mapped to cell types from the target cell library.
Some passes refuse to operate on modules that still contain RTLIL::Process objects as the presence of these
objects in a module increases the complexity. Therefore the passes to translate processes to a netlist of
cells are usually called early in a synthesis script. The proc pass calls a series of other passes that together
perform this conversion in a way that is suitable for most synthesis tasks.

4.2.6

RTLIL::Memory

For every array (memory) in the HDL code an RTLIL::Memory object is created. A memory object has
the following properties:
• The memory name
• A list of attributes
• The width of an addressable word
34

CHAPTER 4. IMPLEMENTATION OVERVIEW
• The size of the memory in number of words
All read accesses to the memory are transformed to $memrd cells and all write accesses to $memwr cells by the
language frontend. These cells consist of independent read- and write-ports to the memory. The \MEMID
parameter on these cells is used to link them together and to the RTLIL::Memory object they belong to.
The rationale behind using separate cells for the individual ports versus creating a large multiport memory
cell right in the language frontend is that the separate $memrd and $memwr cells can be consolidated using
resource sharing. As resource sharing is a non-trivial optimization problem where different synthesis tasks
can have different requirements it lends itself to do the optimisation in separate passes and merge the
RTLIL::Memory objects and $memrd and $memwr cells to multiport memory blocks after resource sharing is
completed.
The memory pass performs this conversion and can (depending on the options passed to it) transform the
memories directly to d-type flip-flops and address logic or yield multiport memory blocks (represented
using $mem cells).
See Sec. 5.1.5 for details about the memory cell types.

4.3

Command Interface and Synthesis Scripts

Yosys reads and processes commands from synthesis scripts, command line arguments and an interactive
command prompt. Yosys commands consist of a command name and an optional whitespace separated
list of arguments. Commands are terminated using the newline character or a semicolon (;). Empty lines
and lines starting with the hash sign (#) are ignored. See Sec. 3.3 for an example synthesis script.
The command help can be used to access the command reference manual.
Most commands can operate not only on the entire design but also specifically on selected parts of the
design. For example the command dump will print all selected objects in the current design while dump
foobar will only print the module foobar and dump * will print the entire design regardless of the current
selection.
The selection mechanism is very powerful. For example the command dump */t:$add %x:+[A] */w:* %i
will print all wires that are connected to the \A port of a $add cell. Detailed documentation of the select
framework can be found in the command reference for the select command.

4.4

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.
• 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 and rtlil.cc), the main() function (driver.cc),
the internal framework for generating log messages (log.h and log.cc), the internal framework for
registering and calling passes (register.h and register.cc), some core commands that are not really
passes (select.cc, show.cc, . . . ) and a couple of other small utility libraries.

35

CHAPTER 4. IMPLEMENTATION OVERVIEW
• passes/
This directory contains a subdirectory for each pass or group of passes. For example as of this
writing the directory passes/opt/ contains the code for seven passes: opt, opt_expr, opt_muxtree,
opt_reduce, opt_rmdff, opt_rmunused and opt_merge.
• techlibs/
This directory contains simulation models and standard implementations for the cells from the internal cell library.
• tests/
This directory contains a couple of test cases. Most of the smaller tests are executed automatically
when make test is called. The larger tests must be executed manually. Most of the larger tests require
downloading external HDL source code and/or external tools. The tests range from comparing
simulation results of the synthesized design to the original sources to logic equivalence checking of
entire CPU cores.
frontends/*/Makefile.inc,
passes/*/Makefile.inc
and
extending Yosys it is enough to create a new directory in
your sources and a Makefile.inc. The Yosys kernel automatically
detects all commands linked with Yosys. So it is not needed to add additional commands to a central list
of commands.

The

top-level

Makefile

includes

backends/*/Makefile.inc.
So when
frontends/, passes/ or backends/ with

Good starting points for reading example source code to learn how to write passes are passes/opt/opt_rmdff.cc
and passes/opt/opt_merge.cc.
See the top-level README file for a quick Getting Started guide and build instructions. The Yosys build
is based solely on Makefiles.
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.

36

Chapter 5

Internal Cell Library
Most of the passes in Yosys operate on netlists, i.e. they only care about the RTLIL::Wire and RTLIL::Cell
objects in an RTLIL::Module. This chapter discusses the cell types used by Yosys to represent a behavioural
design internally.
This chapter is split in two parts. In the first part the internal RTL cells are covered. These cells are used
to represent the design on a coarse grain level. Like in the original HDL code on this level the cells operate
on vectors of signals and complex cells like adders exist. In the second part the internal gate cells are
covered. These cells are used to represent the design on a fine-grain gate-level. All cells from this category
operate on single bit signals.

5.1

RTL Cells

Most of the RTL cells closely resemble the operators available in HDLs such as Verilog or VHDL. Therefore
Verilog operators are used in the following sections to define the behaviour of the RTL cells.
Note that all RTL cells have parameters indicating the size of inputs and outputs. When passes modify
RTL cells they must always keep the values of these parameters in sync with the size of the signals
connected to the inputs and outputs.
Simulation models for the RTL cells can be found in the file techlibs/common/simlib.v in the Yosys source
tree.

5.1.1

Unary Operators

All unary RTL cells have one input port \A and one output port \Y. They also have the following parameters:
• \A_SIGNED
Set to a non-zero value if the input \A is signed and therefore should be sign-extended when needed.
• \A_WIDTH
The width of the input port \A.
• \Y_WIDTH
The width of the output port \Y.
Table 5.1 lists all cells for unary RTL operators.
Note that $reduce_or and $reduce_bool actually represent the same logic function. But the HDL frontends
generate them in different situations. A $reduce_or cell is generated when the prefix | operator is being
used. A $reduce_bool cell is generated when a bit vector is used as a condition in an if-statement or
?:-expression.
37

CHAPTER 5. INTERNAL CELL LIBRARY
Verilog

Cell Type

Y = ~A

$not

Y = +A
Y = -A

$pos
$neg

Y = &A

$reduce_and

Y = |A
Y = ^A
Y = ~^A

$reduce_or
$reduce_xor
$reduce_xnor

Y = |A
Y = !A

$reduce_bool
$logic_not

Table 5.1: Cell types for unary operators with their corresponding Verilog expressions.

5.1.2

Binary Operators

All binary RTL cells have two input ports \A and \B and one output port \Y. They also have the following
parameters:
• \A_SIGNED
Set to a non-zero value if the input \A is signed and therefore should be sign-extended when needed.
• \A_WIDTH
The width of the input port \A.
• \B_SIGNED
Set to a non-zero value if the input \B is signed and therefore should be sign-extended when needed.
• \B_WIDTH
The width of the input port \B.
• \Y_WIDTH
The width of the output port \Y.
Table 5.2 lists all cells for binary RTL operators.

5.1.3

Multiplexers

Multiplexers are generated by the Verilog HDL frontend for ?:-expressions. Multiplexers are also generated
by the proc pass to map the decision trees from RTLIL::Process objects to logic.
The simplest multiplexer cell type is $mux. Cells of this type have a \WIDTH parameter and data inputs \A
and \B and a data output \Y, all of the specified width. This cell also has a single bit control input \S. If
\S is 0 the value from the \A input is sent to the output, if it is 1 the value from the \B input is sent to
the output. So the $mux cell implements the function Y = S ? B : A.
The $pmux cell is used to multiplex between many inputs using a one-hot select signal. Cells of this type have
a \WIDTH and a \S_WIDTH parameter and inputs \A, \B, and \S and an output \Y. The \S input is \S_WIDTH
bits wide. The \A input and the output are both \WIDTH bits wide and the \B input is \WIDTH*\S_WIDTH
bits wide. When all bits of \S are zero, the value from \A input is sent to the output. If the n’th bit from
\S is set, the value n’th \WIDTH bits wide slice of the \B input is sent to the output. When more than one
bit from \S is set the output is undefined. Cells of this type are used to model “parallel cases” (defined by
using the parallel_case attribute or detected by an optimization).
Behavioural code with cascaded if-then-else- and case-statements usually results in trees of multiplexer
cells. Many passes (from various optimizations to FSM extraction) heavily depend on these multiplexer
trees to understand dependencies between signals. Therefore optimizations should not break these multiplexer trees (e.g. by replacing a multiplexer between a calculated signal and a constant zero with an $and
gate).
38

CHAPTER 5. INTERNAL CELL LIBRARY
Verilog

Cell Type

Verilog

Cell Type

Y = A & B

$and

Y = A < B

$lt

Y = A | B
Y = A ^ B
Y = A ~^ B

$or
$xor
$xnor

Y
Y
Y
Y

$shl
$shr
$sshl
$sshr

Y
Y
Y
Y
Y

=
=
=
=
=

A
A
A
A
A

<= B
== B
!= B
>= B
> B

$le
$eq
$ne
$ge
$gt

=
=
=
=

A
A
A
A

+ B
- B
* B
/ B

$add
$sub
$mul
$div

=
=
=
=

A
A
A
A

<< B
>> B
<<< B
>>> B

Y = A && B
Y = A || B

$logic_and
$logic_or

Y
Y
Y
Y

Y = A === B
Y = A !== B

$eqx
$nex

Y = A % B
Y = A ** B

$mod
$pow

Table 5.2: Cell types for binary operators with their corresponding Verilog expressions.

5.1.4

Registers

D-Type Flip-Flops are represented by $dff cells. These cells have a clock port \CLK, an input port \D and
an output port \Q. The following parameters are available for $dff cells:
• \WIDTH
The width of input \D and output \Q.
• \CLK_POLARITY
Clock is active on the positive edge if this parameter has the value 1’b1 and on the negative edge if
this parameter is 1’b0.
D-Type Flip-Flops with asynchronous resets are represented by $adff cells. As the $dff cells they have
and \Q ports. In addition they also have a single-bit \ARST input port for the reset pin and the
following additional two parameters:
\CLK, \D

• \ARST_POLARITY
The asynchronous reset is high-active if this parameter has the value 1’b1 and low-active if this
parameter is 1’b0.
• \ARST_VALUE
The state of \Q will be set to this value when the reset is active.
Note that the $adff cell can only be used when the reset value is constant.
Usually these cells are generated by the proc pass using the information in the designs RTLIL::Process
objects.
FIXME:
Add information about $sr cells (set-reset flip-flops) and d-type latches.

5.1.5

Memories

Memories are either represented using RTLIL::Memory objects and $memrd and $memwr cells or simply by
using $mem cells.
In the first alternative the RTLIL::Memory objects hold the general metadata for the memory (bit width,
size in number of words, etc.) and for each port a $memrd (read port) or $memwr (write port) cell is created.
39

CHAPTER 5. INTERNAL CELL LIBRARY
Having individual cells for read and write ports has the advantage that they can be consolidated using
resource sharing passes. In some cases this drastically reduces the number of required ports on the memory
cell.
The $memrd cells have a clock input \CLK, an enable input \EN, an address input \ADDR, and a data output
\DATA. They also have the following parameters:
• \MEMID
The name of the RTLIL::Memory object that is associated with this read port.
• \ABITS
The number of address bits (width of the \ADDR input port).
• \WIDTH
The number of data bits (width of the \DATA output port).
• \CLK_ENABLE
When this parameter is non-zero, the clock is used. Otherwise this read port is asynchronous and
the \CLK input is not used.
• \CLK_POLARITY
Clock is active on the positive edge if this parameter has the value 1’b1 and on the negative edge if
this parameter is 1’b0.
• \TRANSPARENT
If this parameter is set to 1’b1, a read and write to the same address in the same cycle will return
the new value. Otherwise the old value is returned.
The $memwr cells have a clock input \CLK, an enable input \EN (one enable bit for each data bit), an address
input \ADDR and a data input \DATA. They also have the following parameters:
• \MEMID
The name of the RTLIL::Memory object that is associated with this read port.
• \ABITS
The number of address bits (width of the \ADDR input port).
• \WIDTH
The number of data bits (width of the \DATA output port).
• \CLK_ENABLE
When this parameter is non-zero, the clock is used. Otherwise this read port is asynchronous and
the \CLK input is not used.
• \CLK_POLARITY
Clock is active on positive edge if this parameter has the value 1’b1 and on the negative edge if this
parameter is 1’b0.
• \PRIORITY
The cell with the higher integer value in this parameter wins a write conflict.
The HDL frontend models a memory using RTLIL::Memory objects and asynchronous $memrd and $memwr
cells. The memory pass (i.e. its various sub-passes) migrates $dff cells into the $memrd and $memwr cells
making them synchronous, then converts them to a single $mem cell and (optionally) maps this cell type to
$dff cells for the individual words and multiplexer-based address decoders for the read and write interfaces.
When the last step is disabled or not possible, a $mem cell is left in the design.
The $mem cell provides the following parameters:
40

CHAPTER 5. INTERNAL CELL LIBRARY
• \MEMID
The name of the original RTLIL::Memory object that became this $mem cell.
• \SIZE
The number of words in the memory.
• \ABITS
The number of address bits.
• \WIDTH
The number of data bits per word.
• \RD_PORTS
The number of read ports on this memory cell.
• \RD_CLK_ENABLE
This parameter is \RD_PORTS bits wide, containing a clock enable bit for each read port.
• \RD_CLK_POLARITY
This parameter is \RD_PORTS bits wide, containing a clock polarity bit for each read port.
• \RD_TRANSPARENT
This parameter is \RD_PORTS bits wide, containing a transparent bit for each read port.
• \WR_PORTS
The number of write ports on this memory cell.
• \WR_CLK_ENABLE
This parameter is \WR_PORTS bits wide, containing a clock enable bit for each write port.
• \WR_CLK_POLARITY
This parameter is \WR_PORTS bits wide, containing a clock polarity bit for each write port.
The $mem cell has the following ports:
• \RD_CLK
This input is \RD_PORTS bits wide, containing all clock signals for the read ports.
• \RD_EN
This input is \RD_PORTS bits wide, containing all enable signals for the read ports.
• \RD_ADDR
This input is \RD_PORTS*\ABITS bits wide, containing all address signals for the read ports.
• \RD_DATA
This input is \RD_PORTS*\WIDTH bits wide, containing all data signals for the read ports.
• \WR_CLK
This input is \WR_PORTS bits wide, containing all clock signals for the write ports.
• \WR_EN
This input is \WR_PORTS*\WIDTH bits wide, containing all enable signals for the write ports.
• \WR_ADDR
This input is \WR_PORTS*\ABITS bits wide, containing all address signals for the write ports.
• \WR_DATA
This input is \WR_PORTS*\WIDTH bits wide, containing all data signals for the write ports.
The techmap pass can be used to manually map $mem cells to specialized memory cells on the target
architecture, such as block ram resources on an FPGA.
41

CHAPTER 5. INTERNAL CELL LIBRARY
Verilog
Y = ~A
Y
Y
Y
Y

=
=
=
=

A
A
A
S

&
|
^
?

B
B
B
B : A

always @(negedge C) Q <= D
always @(posedge C) Q <= D

Cell Type

ClkEdge

RstLvl

RstV al

Cell Type

$_NOT_

negedge

0

0

$_DFF_NN0_

$_AND_
$_OR_
$_XOR_
$_MUX_

negedge
negedge
negedge
posedge
posedge
posedge

0
1
1
0
0
1

1
0
1
0
1
0

$_DFF_NN1_
$_DFF_NP0_
$_DFF_NP1_
$_DFF_PN0_
$_DFF_PN1_
$_DFF_PP0_

posedge

1

1

$_DFF_PP1_

$_DFF_N_
$_DFF_P_

Table 5.3: Cell types for gate level logic networks

5.1.6

Finite State Machines

FIXME:
Add a brief description of the $fsm cell type.

5.2

Gates

For gate level logic networks, fixed function single bit cells are used that do not provide any parameters.
Simulation models for these cells can be found in the file techlibs/common/simcells.v in the Yosys source
tree.
Table 5.3 lists all cell types used for gate level logic. The cell types $_NOT_, $_AND_, $_OR_, $_XOR_ and
$_MUX_ are used to model combinatorial logic. The cell types $_DFF_N_ and $_DFF_P_ represent d-type
flip-flops.
The cell types $_DFF_NN0_, $_DFF_NN1_, $_DFF_NP0_, $_DFF_NP1_, $_DFF_PN0_, $_DFF_PN1_, $_DFF_PP0_ and
implement d-type flip-flops with asynchronous resets. The values in the table for these cell
types relate to the following Verilog code template, where RstEdge is posedge if RstLvl if 1, and negedge
otherwise.
$_DFF_PP1_

always @(ClkEdge C, RstEdge R)
if (R == RstLvl)
Q <= RstV al;
else
Q <= D;

In most cases gate level logic networks are created from RTL networks using the techmap pass. The flip-flop
cells from the gate level logic network can be mapped to physical flip-flop cells from a Liberty file using
the dfflibmap pass. The combinatorial logic cells can be mapped to physical cells from a Liberty file via
ABC [27] using the abc pass.
FIXME:
Add information about $assert, $assume, $live, $fair, $cover, $equiv, $initstate, $anyconst, and
$anyseq cells.
FIXME:
Add information about $slice and $concat cells.
FIXME:
Add information about $lut and $sop cells.
FIXME:
Add information about $alu, $macc, $fa, and $lcu cells.
42

CHAPTER 5. INTERNAL CELL LIBRARY
FIXME:
Add information about $ff and $_FF_ cells.
FIXME:
Add information about $dffe, $dffsr, $dlatch, and $dlatchsr cells.
FIXME:
Add information about $_DFFE_??_, $_DFFSR_???_, $_DLATCH_?_, and $_DLATCHSR_???_ cells.
FIXME:
Add information about $_NAND_, $_NOR_, $_XNOR_, $_ANDNOT_, $_ORNOT_, $_AOI3_, $_OAI3_, $_AOI4_, and
$_OAI4_ cells.

43

Chapter 6

Programming Yosys Extensions
This chapter contains some bits and pieces of information about programming yosys extensions. Also
consult the section on programming in the “Yosys Presentation” (can be downloaded from the Yosys
website as PDF) and don’t be afraid to ask questions on the Yosys Subreddit.

6.1

The “CodingReadme” File

The following is an excerpt of the CodingReadme file from the Yosys source tree.
CodingReadme

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

Getting Started
===============

Outline of a Yosys command
-------------------------Here is a the C++ code for a "hello_world" Yosys command (hello.cc):
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct HelloWorldPass : public Pass {
HelloWorldPass() : Pass("hello_world") { }
virtual void execute(vector, Design*) {
log("Hello World!\n");
}
} HelloWorldPass;
PRIVATE_NAMESPACE_END
This can be built into a Yosys module using the following command:
yosys-config --exec --cxx --cxxflags --ldflags -o hello.so -shared hello.cc --ldlibs

44

CHAPTER 6. PROGRAMMING YOSYS EXTENSIONS
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

Or short:
yosys-config --build hello.so hello.cc
And then executed using the following command:
yosys -m hello.so -p hello_world

Yosys Data Structures
--------------------Here is a short list of data structures that you should make yourself familiar
with before you write C++ code for Yosys. The following data structures are all
defined when "kernel/yosys.h" is included and USING_YOSYS_NAMESPACE is used.
1. Yosys Container Classes
Yosys uses dict and pool as main container classes. dict is
essentially a replacement for std::unordered_map and pool is a
replacement for std::unordered_set. The main characteristics are:
- dict and pool are about 2x faster than the std containers
- references to elements in a dict or pool are invalidated by
insert and remove operations (similar to std::vector on push_back()).
- some iterators are invalidated by erase(). specifically, iterators
that have not passed the erased element yet are invalidated. (erase()
itself returns valid iterator to the next element.)
- no iterators are invalidated by insert(). elements are inserted at
begin(). i.e. only a new iterator that starts at begin() will see the
inserted elements.
- the method .count(key, iterator) is like .count(key) but only
considers elements that can be reached via the iterator.
- iterators can be compared. it1 < it2 means that the position of t2
can be reached via t1 but not vice versa.
- the method .sort() can be used to sort the elements in the container
the container stays sorted until elements are added or removed.
- dict and pool will have the same order of iteration across
all compilers, standard libraries and architectures.
In addition to dict and pool there is also an idict that
creates a bijective map from K to the integers. For example:
idict si;
log("%d\n", si("hello"));

// will print 42

log("%d\n", si("world"));
log("%d\n", si.at("world"));

// will print 43
// will print 43

45

CHAPTER 6. PROGRAMMING YOSYS EXTENSIONS
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

log("%d\n",
log("%s\n",
log("%s\n",
log("%s\n",

si.at("dummy"));
si[42].c_str()));
si[43].c_str()));
si[44].c_str()));

//
//
//
//

will
will
will
will

throw
print
print
throw

exception
hello
world
exception

It is not possible to remove elements from an idict.
Finally mfp implements a merge-find set data structure (aka. disjoint-set or
union-find) over the type K ("mfp" = merge-find-promote).
2. Standard STL data types
In Yosys we use std::vector and std::string whenever applicable. When
dict and pool are not suitable then std::map and std::set
are used instead.
The types std::vector and std::string are also available as vector
and string in the Yosys namespace.
3. RTLIL objects
The current design (essentially a collection of modules, each defined by a
netlist) is stored in memory using RTLIL object (declared in kernel/rtlil.h,
automatically included by kernel/yosys.h). You should glance over at least
the declarations for the following types in kernel/rtlil.h:
RTLIL::IdString
This is a handle for an identifier (e.g. cell or wire name).
It feels a lot like a std::string, but is only a single int
in size. (The actual string is stored in a global lookup
table.)
RTLIL::SigBit
A single signal bit. I.e. either a constant state (0, 1,
x, z) or a single bit from a wire.
RTLIL::SigSpec
Essentially a vector of SigBits.
RTLIL::Wire
RTLIL::Cell
The building blocks of the netlist in a module.
RTLIL::Module
RTLIL::Design
The module is a container with connected cells and wires
in it. The design is a container with modules in it.
All this types are also available without the RTLIL:: prefix in the Yosys
namespace.
4. SigMap and other Helper Classes
There are a couple of additional helper classes that are in wide use

46

CHAPTER 6. PROGRAMMING YOSYS EXTENSIONS
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

in Yosys. Most importantly there is SigMap (declared in kernel/sigtools.h).
When a design has many wires in it that are connected to each other, then a
single signal bit can have multiple valid names. The SigMap object can be used
to map SigSpecs or SigBits to unique SigSpecs and SigBits that consistently
only use one wire from such a group of connected wires. For example:
SigBit a = module->addWire(NEW_ID);
SigBit b = module->addWire(NEW_ID);
module->connect(a, b);
log("%d\n", a == b); // will print 0
SigMap sigmap(module);
log("%d\n", sigmap(a) == sigmap(b)); // will print 1

Using the RTLIL Netlist Format
-----------------------------In the RTLIL netlist format the cell ports contain SigSpecs that point to the
Wires. There are no references in the other direction. This has two direct
consequences:
(1) It is very easy to go from cells to wires but hard to go in the other way.
(2) There is no danger in removing cells from the netlists, but removing wires
can break the netlist format when there are still references to the wire
somewhere in the netlist.
The solution to (1) is easy: Create custom indexes that allow you to make fast
lookups for the wire-to-cell direction. You can either use existing generic
index structures to do that (such as the ModIndex class) or write your own
index. For many application it is simplest to construct a custom index. For
example:
SigMap sigmap(module);
dict sigbit_to_driver_index;
for (auto cell : module->cells())
for (auto &conn : cell->connections())
if (cell->output(conn.first))
for (auto bit : sigmap(conn.second))
sigbit_to_driver_index[bit] = cell;
Regarding (2): There is a general theme in Yosys that you don’t remove wires
from the design. You can rename them, unconnect them, but you do not actually remove
the Wire object from the module. Instead you let the "clean" command take care
of the dangling wires. On the other hand it is safe to remove cells (as long as
you make sure this does not invalidate a custom index you are using in your code).

Example Code
------------

47

CHAPTER 6. PROGRAMMING YOSYS EXTENSIONS
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248

The following yosys commands are a good starting point if you are looking for examples
of how to use the Yosys API:
manual/CHAPTER_Prog/stubnets.cc
manual/PRESENTATION_Prog/my_cmd.cc

Notes on the existing codebase
-----------------------------For historical reasons not all parts of Yosys adhere to the current coding
style. When adding code to existing parts of the system, adhere to this guide
for the new code instead of trying to mimic the style of the surrounding code.

Coding Style
============

Formatting of code
------------------ Yosys code is using tabs for indentation. Tabs are 8 characters.
- A continuation of a statement in the following line is indented by
two additional tabs.
- Lines are as long as you want them to be. A good rule of thumb is
to break lines at about column 150.
- Opening braces can be put on the same or next line as the statement
opening the block (if, switch, for, while, do). Put the opening brace
on its own line for larger blocks, especially blocks that contains
blank lines.
- Otherwise stick to the Linux Kernel Coding Style:
https://www.kernel.org/doc/Documentation/CodingStyle

C++ Language
------------Yosys is written in C++11. At the moment only constructs supported by
gcc 4.8 are allowed in Yosys code. This will change in future releases.
In general Yosys uses "int" instead of "size_t". To avoid compiler
warnings for implicit type casts, always use "GetSize(foobar)" instead
of "foobar.size()". (GetSize() is defined in kernel/yosys.h)
Use range-based for loops whenever applicable.

48

CHAPTER 6. PROGRAMMING YOSYS EXTENSIONS

6.2

The “stubsnets” Example Module

The following is the complete code of the “stubsnets” example module. It is included in the Yosys source
distribution as manual/CHAPTER_Prog/stubnets.cc.
stubnets.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non-commercial, and by any
// means.
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include 
#include 
#include 
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
// this function is called for each module in the design
static void find_stub_nets(RTLIL::Design *design, RTLIL::Module *module, bool report_bits)
{
// use a SigMap to convert nets to a unique representation
SigMap sigmap(module);
// count how many times a single-bit signal is used
std::map bit_usage_count;
// count output lines for this module (needed only for summary output at the end)
int line_count = 0;
log("Looking for stub wires in module %s:\n", RTLIL::id2cstr(module->name));
// For all ports on all cells
for (auto &cell_iter : module->cells_)
for (auto &conn : cell_iter.second->connections())
{
// Get the signals on the port
// (use sigmap to get a uniqe signal name)
RTLIL::SigSpec sig = sigmap(conn.second);
// add each bit to bit_usage_count, unless it is a constant
for (auto &bit : sig)
if (bit.wire != NULL)
bit_usage_count[bit]++;
}
// for each wire in the module
for (auto &wire_iter : module->wires_)
{

49

CHAPTER 6. PROGRAMMING YOSYS EXTENSIONS
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

RTLIL::Wire *wire = wire_iter.second;
// .. but only selected wires
if (!design->selected(module, wire))
continue;
// add +1 usage if this wire actually is a port
int usage_offset = wire->port_id > 0 ? 1 : 0;
// we will record which bits of the (possibly multi-bit) wire are stub signals
std::set stub_bits;
// get a signal description for this wire and split it into separate bits
RTLIL::SigSpec sig = sigmap(wire);
// for each bit (unless it is a constant):
// check if it is used at least two times and add to stub_bits otherwise
for (int i = 0; i < GetSize(sig); i++)
if (sig[i].wire != NULL && (bit_usage_count[sig[i]] + usage_offset) < 2)
stub_bits.insert(i);
// continue if no stub bits found
if (stub_bits.size() == 0)
continue;
// report stub bits and/or stub wires, don’t report single bits
// if called with report_bits set to false.
if (GetSize(stub_bits) == GetSize(sig)) {
log(" found stub wire: %s\n", RTLIL::id2cstr(wire->name));
} else {
if (!report_bits)
continue;
log(" found wire with stub bits: %s [", RTLIL::id2cstr(wire->name));
for (int bit : stub_bits)
log("%s%d", bit == *stub_bits.begin() ? "" : ", ", bit);
log("]\n");
}
// we have outputted a line, increment summary counter
line_count++;
}
// report summary
if (report_bits)
log(" found %d stub wires or wires with stub bits.\n", line_count);
else
log("

found %d stub wires.\n", line_count);

}
// each pass contains a singleton object that is derived from Pass
struct StubnetsPass : public Pass {
StubnetsPass() : Pass("stubnets") { }
virtual void execute(std::vector args, RTLIL::Design *design)
{

50

CHAPTER 6. PROGRAMMING YOSYS EXTENSIONS
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

// variables to mirror information from passed options
bool report_bits = 0;
log_header(design, "Executing STUBNETS pass (find stub nets).\n");
// parse options
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-report_bits") {
report_bits = true;
continue;
}
break;
}
// handle extra options (e.g. selection)
extra_args(args, argidx, design);
// call find_stub_nets() for each module that is either
// selected as a whole or contains selected objects.
for (auto &it : design->modules_)
if (design->selected_module(it.first))
find_stub_nets(design, it.second, report_bits);
}
} StubnetsPass;
PRIVATE_NAMESPACE_END

Makefile

1
2
3
4
5
6
7
8
9
10
11
12

test: stubnets.so
yosys -ql test1.log -m ./stubnets.so test.v -p "stubnets"
yosys -ql test2.log -m ./stubnets.so test.v -p "opt; stubnets"
yosys -ql test3.log -m ./stubnets.so test.v -p "techmap; opt; stubnets -report_bits"
tail test1.log test2.log test3.log
stubnets.so: stubnets.cc
yosys-config --exec --cxx --cxxflags --ldflags -o $@ -shared $^ --ldlibs
clean:
rm -f test1.log test2.log test3.log
rm -f stubnets.so stubnets.d

test.v

1
2
3
4
5
6
7
8

module uut(in1, in2, in3, out1, out2);
input [8:0] in1, in2, in3;
output [8:0] out1, out2;
assign out1 = in1 + in2 + (in3 >> 4);
endmodule

51

Chapter 7

The Verilog and AST Frontends
This chapter provides an overview of the implementation of the Yosys Verilog and AST frontends. The
Verilog frontend reads Verilog-2005 code and creates an abstract syntax tree (AST) representation of the
input. This AST representation is then passed to the AST frontend that converts it to RTLIL data, as
illustrated in Fig. 7.1.

7.1

Transforming Verilog to AST

The Verilog frontend converts the Verilog sources to an internal AST representation that closely resembles the structure of the original Verilog code. The Verilog frontend consists of three components, the
Preprocessor, the Lexer and the Parser.
The source code to the Verilog frontend can be found in frontends/verilog/ in the Yosys source tree.

Verilog Source
Preprocessor
Verilog Frontend

Lexer
Parser

AST

Simplifier
AST Frontend
RTLIL Generator

RTLIL

Figure 7.1: Simplified Verilog to RTLIL data flow

52

CHAPTER 7. THE VERILOG AND AST FRONTENDS

7.1.1

The Verilog Preprocessor

The Verilog preprocessor scans over the Verilog source code and interprets some of the Verilog compiler
directives such as ‘include, ‘define and ‘ifdef.
It is implemented as a C++ function that is passed a file descriptor as input and returns the pre-processed
Verilog code as a std::string.
The source code to the Verilog Preprocessor can be found in frontends/verilog/preproc.cc in the Yosys
source tree.

7.1.2

The Verilog Lexer

The Verilog Lexer is written using the lexer generator flex [17]. Its source code can be found in
in the Yosys source tree. The lexer does little more than identifying all keywords and literals recognised by the Yosys Verilog frontend.
frontends/verilog/lexer.l

The lexer keeps track of the current location in the Verilog source code using some global variables. These
variables are used by the constructor of AST nodes to annotate each node with the source code location
it originated from.
Finally the lexer identifies and handles special comments such as “// synopsys translate_off” and
“// synopsys full_case”. (It is recommended to use ‘ifdef constructs instead of the Synsopsys translate_on/off comments and attributes such as (* full_case *) over “// synopsys full_case” whenever
possible.)

7.1.3

The Verilog Parser

The Verilog Parser is written using the parser generator bison [18]. Its source code can be found in
frontends/verilog/parser.y in the Yosys source tree.
It generates an AST using the AST::AstNode data structure defined in frontends/ast/ast.h. An AST::AstNode
object has the following properties:
• The node type
This enum (AST::AstNodeType) specifies the role of the node. Table 7.1 contains a list of all node
types.
• The child nodes
This is a list of pointers to all children in the abstract syntax tree.
• Attributes
As almost every AST node might have Verilog attributes assigned to it, the AST::AstNode has direct
support for attributes. Note that the attribute values are again AST nodes.
• Node content
Each node might have additional content data. A series of member variables exist to hold such
data. For example the member std::string str can hold a string value and is used e.g. in the
AST_IDENTIFIER node type to store the identifier name.
• Source code location
Each AST::AstNode is automatically annotated with the current source code location by the AST::AstNode
constructor. It is stored in the std::string filename and int linenum member variables.
The AST::AstNode constructor can be called with up to two child nodes that are automatically added to
the list of child nodes for the new object. This simplifies the creation of AST nodes for simple expressions
a bit. For example the bison code for parsing multiplications:
53

CHAPTER 7. THE VERILOG AND AST FRONTENDS

basic_expr ’*’ attr basic_expr {

1
2
3
4

$$ = new AstNode(AST_MUL, $1, $4);
append_attr($$, $3);
} |

The generated AST data structure is then passed directly to the AST frontend that performs the actual
conversion to RTLIL.
Note that the Yosys command read_verilog provides the options -yydebug and -dump_ast that can be used
to print the parse tree or abstract syntax tree respectively.

7.2

Transforming AST to RTLIL

The AST Frontend converts a set of modules in AST representation to modules in RTLIL representation
and adds them to the current design. This is done in two steps: simplification and RTLIL generation.
The source code to the AST frontend can be found in frontends/ast/ in the Yosys source tree.

7.2.1

AST Simplification

A full-featured AST is too complex to be transformed into RTLIL directly. Therefore it must first be
brought into a simpler form. This is done by calling the AST::AstNode::simplify() method of all AST_MODULE
nodes in the AST. This initiates a recursive process that performs the following transformations on the
AST data structure:
AST Node Type
AST_NONE
AST_DESIGN
AST_MODULE, AST_TASK, AST_FUNCTION
AST_WIRE
AST_MEMORY
AST_AUTOWIRE
AST_PARAMETER, AST_LOCALPARAM
AST_PARASET
AST_ARGUMENT
AST_RANGE
AST_CONSTANT
AST_CELLTYPE
AST_IDENTIFIER
AST_PREFIX

AST_FCALL, AST_TCALL
AST_TO_SIGNED, AST_TO_UNSIGNED

Corresponding Verilog Construct
This Node type should never be used.
This node type is used for the top node of the AST
tree. It has no corresponding Verilog construct.
module, task and function
input, output, wire, reg and integer
Verilog Arrays
Created by the simplifier when an undeclared signal
name is used.
parameter and localparam
Parameter set in cell instantiation
Port connection in cell instantiation
Bit-Index in a signal or element index in array
A literal value
The type of cell in cell instantiation
An Identifier (signal name in expression or
cell/task/etc. name in other contexts)
Construct an identifier in the form
[]. (used only in
advanced generate constructs)
Call to function or task
The $signed() and $unsigned() functions

Table 7.1: AST node types with their corresponding Verilog constructs.
(continued on next page)

54

CHAPTER 7. THE VERILOG AND AST FRONTENDS
AST Node Type
AST_CONCAT AST_REPLICATE
AST_BIT_NOT, AST_BIT_AND, AST_BIT_OR,
AST_BIT_XOR, AST_BIT_XNOR
AST_REDUCE_AND, AST_REDUCE_OR,
AST_REDUCE_XOR, AST_REDUCE_XNOR
AST_REDUCE_BOOL
AST_SHIFT_LEFT, AST_SHIFT_RIGHT,
AST_SHIFT_SLEFT, AST_SHIFT_SRIGHT
AST_LT, AST_LE, AST_EQ, AST_NE, AST_GE,
AST_GT
AST_ADD, AST_SUB, AST_MUL, AST_DIV, AST_MOD,
AST_POW
AST_POS, AST_NEG
AST_LOGIC_AND, AST_LOGIC_OR, AST_LOGIC_NOT
AST_TERNARY
AST_MEMRD AST_MEMWR

AST_ASSIGN
AST_CELL
AST_PRIMITIVE
AST_ALWAYS, AST_INITIAL
AST_BLOCK
AST_ASSIGN_EQ. AST_ASSIGN_LE
AST_CASE. AST_COND, AST_DEFAULT
AST_FOR
AST_GENVAR, AST_GENBLOCK, AST_GENFOR,
AST_GENIF
AST_POSEDGE, AST_NEGEDGE, AST_EDGE

Corresponding Verilog Construct
The {...} and {...{...}} operators
The bitwise operators
~, &, |, ^ and ~^
The unary reduction operators
~, &, |, ^ and ~^
Conversion from multi-bit value to boolean value
(equivalent to AST_REDUCE_OR)
The shift operators
<<, >>, <<< and >>>
The relational operators
<, <=, ==, !=, >= and >
The binary operators
+, -, *, /, % and **
The prefix operators + and The logic operators &&, || and !
The ternary ?:-operator
Read and write memories. These nodes are
generated by the AST simplifier for writes/reads
to/from Verilog arrays.
An assign statement
A cell instantiation
A primitive cell (and, nand, or, etc.)
Verilog always- and initial-blocks
A begin-end-block
Blocking (=) and nonblocking (<=) assignments
within an always- or initial-block
The case (if) statements, conditions within a case
and the default case respectively
A for-loop with an always- or initial-block
The genvar and generate keywords and for and if
within a generate block.
Event conditions for always blocks.

Table 7.1: AST node types with their corresponding Verilog constructs.
(continuation from previous page)

• Inline all task and function calls.
• Evaluate all generate-statements and unroll all for-loops.
• Perform const folding where it is necessary (e.g. in the value part of AST_PARAMETER, AST_LOCALPARAM,
AST_PARASET and AST_RANGE nodes).
• Replace AST_PRIMITIVE nodes with appropriate AST_ASSIGN nodes.
• Replace dynamic bit ranges in the left-hand-side of assignments with AST_CASE nodes with AST_COND
children for each possible case.
• Detect array access patterns that are too complicated for the RTLIL::Memory abstraction and replace
them with a set of signals and cases for all reads and/or writes.
• Otherwise replace array accesses with AST_MEMRD and AST_MEMWR nodes.
In addition to these transformations, the simplifier also annotates the AST with additional information
that is needed for the RTLIL generator, namely:
55

CHAPTER 7. THE VERILOG AND AST FRONTENDS
• All ranges (width of signals and bit selections) are not only const folded but (when a constant value
is found) are also written to member variables in the AST_RANGE node.
• All identifiers are resolved and all AST_IDENTIFIER nodes are annotated with a pointer to the AST
node that contains the declaration of the identifier. If no declaration has been found, an AST_AUTOWIRE
node is created and used for the annotation.
This produces an AST that is fairly easy to convert to the RTLIL format.

7.2.2

Generating RTLIL

After AST simplification, the AST::AstNode::genRTLIL() method of each AST_MODULE node in the AST is
called. This initiates a recursive process that generates equivalent RTLIL data for the AST data.
The AST::AstNode::genRTLIL() method returns an RTLIL::SigSpec structure. For nodes that represent
expressions (operators, constants, signals, etc.), the cells needed to implement the calculation described by
the expression are created and the resulting signal is returned. That way it is easy to generate the circuits
for large expressions using depth-first recursion. For nodes that do not represent an expression (such as
AST_CELL), the corresponding circuit is generated and an empty RTLIL::SigSpec is returned.

7.3

Synthesizing Verilog always Blocks

For behavioural Verilog code (code utilizing always- and initial-blocks) it is necessary to also generate
objects. This is done in the following way:

RTLIL::Process

• Whenever AST::AstNode::genRTLIL() encounters an always- or initial-block, it creates an instance
of AST_INTERNAL::ProcessGenerator. This object then generates the RTLIL::Process object for the
block. It also calls AST::AstNode::genRTLIL() for all right-hand-side expressions contained within
the block.
• First the AST_INTERNAL::ProcessGenerator creates a list of all signals assigned within the block. It
then creates a set of temporary signals using the naming scheme $\ for
each of the assigned signals.
• Then an RTLIL::Process is created that assigns all intermediate values for each left-hand-side signal
to the temporary signal in its RTLIL::CaseRule/RTLIL::SwitchRule tree.
• Finally a RTLIL::SyncRule is created for the RTLIL::Process that assigns the temporary signals for
the final values to the actual signals.
• Calls to AST::AstNode::genRTLIL() are generated for right hand sides as needed. When blocking
assignments are used, AST::AstNode::genRTLIL() is configured using global variables to use the temporary signals that hold the correct intermediate values whenever one of the previously assigned
signals is used in an expression.
Unfortunately the generation of a correct RTLIL::CaseRule/RTLIL::SwitchRule tree for behavioural code
is a non-trivial task. The AST frontend solves the problem using the approach described on the following
pages. The following example illustrates what the algorithm is supposed to do. Consider the following
Verilog code:

56

CHAPTER 7. THE VERILOG AND AST FRONTENDS

1
2
3
4
5
6
7
8
9
10
11
12
13
14

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

This is translated by the Verilog and AST frontends into the following RTLIL code (attributes, cell
parameters and wire declarations not included):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

cell $logic_not $logic_not$:4$2
connect
connect
end
cell $xor
connect
connect

\A \in1
\Y $logic_not$:4$2_Y
$xor$:13$3
\A $1\out1[0:0]
\B \out2

connect \Y $xor$:13$3_Y
end
process $proc$:1$1
assign $0\out3[0:0] \out3
assign $0\out2[0:0] $1\out1[0:0]
assign $0\out1[0:0] $xor$:13$3_Y
switch \in2
case 1’1
assign $1\out1[0:0] $logic_not$:4$2_Y
case
assign $1\out1[0:0] \in1
end
switch \in3
case 1’1
assign $0\out2[0:0] \out2
case
end
switch \in4
case 1’1
switch \in5
case 1’1
assign $0\out3[0:0] \in6
case
assign $0\out3[0:0] \in7
end
case
end
sync posedge \clock
update \out1 $0\out1[0:0]

57

CHAPTER 7. THE VERILOG AND AST FRONTENDS
37
38
39

update \out2 $0\out2[0:0]
update \out3 $0\out3[0:0]
end

Note that the two operators are translated into separate cells outside the generated process. The signal
out1 is assigned using blocking assignments and therefore out1 has been replaced with a different signal
in all expressions after the initial assignment. The signal out2 is assigned using nonblocking assignments
and therefore is not substituted on the right-hand-side expressions.
The RTLIL::CaseRule/RTLIL::SwitchRule tree must be interpreted the following way:
• On each case level (the body of the process is the root case), first the actions on this level are
evaluated and then the switches within the case are evaluated. (Note that the last assignment on
line 13 of the Verilog code has been moved to the beginning of the RTLIL process to line 13 of the
RTLIL listing.)
I.e. the special cases deeper in the switch hierarchy override the defaults on the upper levels. The
assignments in lines 12 and 22 of the RTLIL code serve as an example for this.
Note that in contrast to this, the order within the RTLIL::SwitchRule objects within a RTLIL::CaseRule
is preserved with respect to the original AST and Verilog code.
• The whole RTLIL::CaseRule/RTLIL::SwitchRule tree describes an asynchronous circuit. I.e. the decision tree formed by the switches can be seen independently for each assigned signal. Whenever
one assigned signal changes, all signals that depend on the changed signals are to be updated. For
example the assignments in lines 16 and 18 in the RTLIL code in fact influence the assignment in
line 12, even though they are in the “wrong order”.
The only synchronous part of the process is in the RTLIL::SyncRule object generated at line 35 in the RTLIL
code. The sync rule is the only part of the process where the original signals are assigned. The synchronization event from the original Verilog code has been translated into the synchronization type (posedge) and
signal (\clock) for the RTLIL::SyncRule object. In the case of this simple example the RTLIL::SyncRule object is later simply transformed into a set of d-type flip-flops and the RTLIL::CaseRule/RTLIL::SwitchRule
tree to a decision tree using multiplexers.
In more complex examples (e.g. asynchronous resets) the part of the RTLIL::CaseRule/RTLIL::SwitchRule
tree that describes the asynchronous reset must first be transformed to the correct RTLIL::SyncRule objects.
This is done by the proc_adff pass.

7.3.1

The ProcessGenerator Algorithm

The AST_INTERNAL::ProcessGenerator uses the following internal state variables:
• subst_rvalue_from and subst_rvalue_to
These two variables hold the replacement pattern that should be used by AST::AstNode::genRTLIL()
for signals with blocking assignments. After initialization of AST_INTERNAL::ProcessGenerator these
two variables are empty.
• subst_lvalue_from and subst_lvalue_to
These two variables contain the mapping from left-hand-side signals (\) to the current
temporary signal for the same thing (initially $0\).
• current_case
A pointer to a RTLIL::CaseRule object. Initially this is the root case of the generated RTLIL::Process.

58

CHAPTER 7. THE VERILOG AND AST FRONTENDS
As the algorithm runs these variables are continuously modified as well as pushed to the stack and later
restored to their earlier values by popping from the stack.
On startup the ProcessGenerator generates a new RTLIL::Process object with an empty root case and
initializes its state variables as described above. Then the RTLIL::SyncRule objects are created using
the synchronization events from the AST_ALWAYS node and the initial values of subst_lvalue_from and
subst_lvalue_to. Then the AST for this process is evaluated recursively.
During this recursive evaluation, three different relevant types of AST nodes can be discovered: AST_ASSIGN_LE
(nonblocking assignments), AST_ASSIGN_EQ (blocking assignments) and AST_CASE (if or case statement).
7.3.1.1

Handling of Nonblocking Assignments

When an AST_ASSIGN_LE node is discovered, the following actions are performed by the ProcessGenerator:
• The left-hand-side is evaluated using AST::AstNode::genRTLIL() and mapped to a temporary signal
name using subst_lvalue_from and subst_lvalue_to.
• The right-hand-side is evaluated using AST::AstNode::genRTLIL(). For this call, the values of subst_rvalue_from
and subst_rvalue_to are used to map blocking-assigned signals correctly.
• Remove all assignments to the same left-hand-side as this assignment from the current_case and all
cases within it.
• Add the new assignment to the current_case.
7.3.1.2

Handling of Blocking Assignments

When an AST_ASSIGN_EQ node is discovered, the following actions are performed by the ProcessGenerator:
• Perform all the steps that would be performed for a nonblocking assignment (see above).
• Remove the found left-hand-side (before lvalue mapping) from subst_rvalue_from and also remove
the respective bits from subst_rvalue_to.
• Append the found left-hand-side (before lvalue mapping) to subst_rvalue_from and append the found
right-hand-side to subst_rvalue_to.
7.3.1.3

Handling of Cases and if-Statements

When an AST_CASE node is discovered, the following actions are performed by the ProcessGenerator:
• The values of subst_rvalue_from, subst_rvalue_to, subst_lvalue_from and subst_lvalue_to are
pushed to the stack.
• A new RTLIL::SwitchRule object is generated, the selection expression is evaluated using
AST::AstNode::genRTLIL() (with the use of subst_rvalue_from and subst_rvalue_to) and added to
the RTLIL::SwitchRule object and the object is added to the current_case.
• All lvalues assigned to within the AST_CASE node using blocking assignments are collected and saved
in the local variable this_case_eq_lvalue.
• New temporary signals are generated for all signals in this_case_eq_lvalue and stored in
this_case_eq_ltemp.

59

CHAPTER 7. THE VERILOG AND AST FRONTENDS
• The signals in this_case_eq_lvalue are mapped using subst_rvalue_from and subst_rvalue_to and
the resulting set of signals is stored in this_case_eq_rvalue.
Then the following steps are performed for each AST_COND node within the AST_CASE node:
• Set subst_rvalue_from, subst_rvalue_to, subst_lvalue_from and subst_lvalue_to to the values that
have been pushed to the stack.
• Remove this_case_eq_lvalue from subst_lvalue_from/subst_lvalue_to.
this_case_eq_lvalue
subst_lvalue_to.

• Append

to

subst_lvalue_from

and

append

this_case_eq_ltemp

to

• Push the value of current_case.
• Create a new RTLIL::CaseRule. Set current_case to the new object and add the new object to the
RTLIL::SwitchRule created above.
• Add an assignment from this_case_eq_rvalue to this_case_eq_ltemp to the new current_case.
• Evaluate the compare value for this case using AST::AstNode::genRTLIL() (with the use of
subst_rvalue_from and subst_rvalue_to) modify the new current_case accordingly.
• Recursion into the children of the AST_COND node.
• Restore current_case by popping the old value from the stack.
Finally the following steps are performed:
• The values of subst_rvalue_from, subst_rvalue_to, subst_lvalue_from and subst_lvalue_to are
popped from the stack.
• The signals from this_case_eq_lvalue are removed from the subst_rvalue_from/subst_rvalue_topair.
• The value of this_case_eq_lvalue is appended to subst_rvalue_from and the value of
this_case_eq_ltemp is appended to subst_rvalue_to.
• Map the signals in this_case_eq_lvalue using subst_lvalue_from/subst_lvalue_to.
• Remove all assignments to signals in this_case_eq_lvalue in current_case and all cases within it.
• Add an assignment from this_case_eq_ltemp to this_case_eq_lvalue to current_case.
7.3.1.4

Further Analysis of the Algorithm for Cases and if-Statements

With respect to nonblocking assignments the algorithm is easy: later assignments invalidate earlier assignments. For each signal assigned using nonblocking assignments exactly one temporary variable is generated
(with the $0-prefix) and this variable is used for all assignments of the variable.
Note how all the _eq_-variables become empty when no blocking assignments are used and many of the
steps in the algorithm can then be ignored as a result of this.
For a variable with blocking assignments the algorithm shows the following behaviour: First a new temporary variable is created. This new temporary variable is then registered as the assignment target for all
assignments for this variable within the cases for this AST_CASE node. Then for each case the new temporary variable is first assigned the old temporary variable. This assignment is overwritten if the variable is
actually assigned in this case and is kept as a default value otherwise.
60

CHAPTER 7. THE VERILOG AND AST FRONTENDS
This yields an RTLIL::CaseRule that assigns the new temporary variable in all branches. So when all cases
have been processed a final assignment is added to the containing block that assigns the new temporary
variable to the old one. Note how this step always overrides a previous assignment to the old temporary variable. Other than nonblocking assignments, the old assignment could still have an effect somewhere in the
design, as there have been calls to AST::AstNode::genRTLIL() with a subst_rvalue_from/subst_rvalue_totuple that contained the right-hand-side of the old assignment.

7.3.2

The proc pass

The ProcessGenerator converts a behavioural model in AST representation to a behavioural model in
RTLIL::Process representation. The actual conversion from a behavioural model to an RTL representation
is performed by the proc pass and the passes it launches:
• proc_clean and proc_rmdead
These two passes just clean up the RTLIL::Process structure. The proc_clean pass removes empty
parts (eg. empty assignments) from the process and proc_rmdead detects and removes unreachable
branches from the process’s decision trees.
• proc_arst
This pass detects processes that describe d-type flip-flops with asynchronous resets and rewrites the
process to better reflect what they are modelling: Before this pass, an asynchronous reset has two
edge-sensitive sync rules and one top-level RTLIL::SwitchRule for the reset path. After this pass the
sync rule for the reset is level-sensitive and the top-level RTLIL::SwitchRule has been removed.
• proc_mux
This pass converts the RTLIL::CaseRule/RTLIL::SwitchRule-tree to a tree of multiplexers per written
signal. After this, the RTLIL::Process structure only contains the RTLIL::SyncRules that describe
the output registers.
• proc_dff
This pass replaces the RTLIL::SyncRules to d-type flip-flops (with asynchronous resets if necessary).
• proc_clean
A final call to proc_clean removes the now empty RTLIL::Process objects.
Performing these last processing steps in passes instead of in the Verilog frontend has two important
benefits:
First it improves the transparency of the process. Everything that happens in a separate pass is easier to
debug, as the RTLIL data structures can be easily investigated before and after each of the steps.
Second it improves flexibility. This scheme can easily be extended to support other types of storageelements, such as sr-latches or d-latches, without having to extend the actual Verilog frontend.

7.4

Synthesizing Verilog Arrays

FIXME:
Add some information on the generation of $memrd and $memwr cells and how they are processed in the
memory pass.

7.5

Synthesizing Parametric Designs

FIXME:
Add some information on the RTLIL::Module::derive() method and how it is used to synthesize parametric modules via the hierarchy pass.
61

Chapter 8

Optimizations
Yosys employs a number of optimizations to generate better and cleaner results. This chapter outlines
these optimizations.

8.1

Simple Optimizations

The Yosys pass opt runs a number of simple optimizations. This includes removing unused signals and
cells and const folding. It is recommended to run this pass after each major step in the synthesis script. At
the time of this writing the opt pass executes the following passes that each perform a simple optimization:
• Once at the beginning of opt:
– opt_expr
– opt_merge -nomux
• Repeat until result is stable:
– opt_muxtree
– opt_reduce
– opt_merge
– opt_rmdff
– opt_clean
– opt_expr
The following section describes each of the opt_* passes.

8.1.1

The opt_expr pass

This pass performs const folding on the internal combinational cell types described in Chap. 5. This means
a cell with all constant inputs is replaced with the constant value this cell drives. In some cases this pass
can also optimize cells with some constant inputs.
Table 8.1 shows the replacement rules used for optimizing an $_AND_ gate. The first three rules implement
the obvious const folding rules. Note that ‘any’ might include dynamic values calculated by other parts of
the circuit. The following three lines propagate undef (X) states. These are the only three cases in which
it is allowed to propagate an undef according to Sec. 5.1.10 of IEEE Std. 1364-2005 [Ver06].
62

CHAPTER 8. OPTIMIZATIONS
A-Input
any
0
1
X/Z
1
X/Z
any
X/Z
a
1

B-Input
0
any
1
X/Z
X/Z
1
X/Z
any
1
b

Table 8.1: Const folding rules for

Replacement
0
0
1
X
X
X
0
0
a
b
$_AND_

cells as used in

opt_expr.

The next two lines assume the value 0 for undef states. These two rules are only used if no other substitutions are possible in the current module. If other substitutions are possible they are performed first, in
the hope that the ‘any’ will change to an undef value or a 1 and therefore the output can be set to undef.
The last two lines simply replace an $_AND_ gate with one constant-1 input with a buffer.
Besides this basic const folding the opt_expr pass can replace 1-bit wide $eq and $ne cells with buffers or
not-gates if one input is constant.
The opt_expr pass is very conservative regarding optimizing $mux cells, as these cells are often used to
model decision-trees and breaking these trees can interfere with other optimizations.

8.1.2

The opt_muxtree pass

This pass optimizes trees of multiplexer cells by analyzing the select inputs. Consider the following simple
example:
1
2
3
4

module uut(a, y);
input a;
output [1:0] y = a ? (a ? 1 : 2) : 3;
endmodule

The output can never be 2, as this would require a to be 1 for the outer multiplexer and 0 for the inner
multiplexer. The opt_muxtree pass detects this contradiction and replaces the inner multiplexer with a
constant 1, yielding the logic for y = a ? 1 : 3.

8.1.3

The opt_reduce pass

This is a simple optimization pass that identifies and consolidates identical input bits to $reduce_and and
cells. It also sorts the input bits to ease identification of shareable $reduce_and and $reduce_or
cells in other passes.
$reduce_or

This pass also identifies and consolidates identical inputs to multiplexer cells. In this case the new shared
select bit is driven using a $reduce_or cell that combines the original select bits.
Lastly this pass consolidates trees of $reduce_and cells and trees of $reduce_or cells to single large
$reduce_and or $reduce_or cells.
These three simple optimizations are performed in a loop until a stable result is produced.

63

CHAPTER 8. OPTIMIZATIONS

8.1.4

The opt_rmdff pass

This pass identifies single-bit d-type flip-flops ($_DFF_*, $dff, and $adff cells) with a constant data input
and replaces them with a constant driver.

8.1.5

The opt_clean pass

This pass identifies unused signals and cells and removes them from the design. It also creates an
\unused_bits attribute on wires with unused bits. This attribute can be used for debugging or by other
optimization passes.

8.1.6

The opt_merge pass

This pass performs trivial resource sharing. This means that this pass identifies cells with identical inputs
and replaces them with a single instance of the cell.
The option -nomux can be used to disable resource sharing for multiplexer cells ($mux and $pmux. This
can be useful as it prevents multiplexer trees to be merged, which might prevent opt_muxtree to identify
possible optimizations.

8.2

FSM Extraction and Encoding

The fsm pass performs finite-state-machine (FSM) extraction and recoding. The fsm pass simply executes
the following other passes:
• Identify and extract FSMs:
– fsm_detect
– fsm_extract
• Basic optimizations:
– fsm_opt
– opt_clean
– fsm_opt
• Expanding to nearby gate-logic (if called with -expand):
– fsm_expand
– opt_clean
– fsm_opt
• Re-code FSM states (unless called with -norecode):
– fsm_recode
• Print information about FSMs:
– fsm_info
• Export FSMs in KISS2 file format (if called with -export):
– fsm_export
64

CHAPTER 8. OPTIMIZATIONS
• Map FSMs to RTL cells (unless called with -nomap):
– fsm_map
The fsm_detect pass identifies FSM state registers and marks them using the \fsm_encoding= "auto" attribute. The fsm_extract extracts all FSMs marked using the \fsm_encoding attribute (unless \fsm_encoding
is set to "none") and replaces the corresponding RTL cells with a $fsm cell. All other fsm_* passes operate
on these $fsm cells. The fsm_map call finally replaces the $fsm cells with RTL cells.
Note that these optimizations operate on an RTL netlist. I.e. the fsm pass should be executed after the
proc pass has transformed all RTLIL::Process objects to RTL cells.
The algorithms used for FSM detection and extraction are influenced by a more general reported technique
[STGR10].

8.2.1

FSM Detection

The fsm_detect pass identifies FSM state registers. It sets the \fsm_encoding= "auto" attribute on any
(multi-bit) wire that matches the following description:
• Does not already have the \fsm_encoding attribute.
• Is not an output of the containing module.
• Is driven by single $dff or $adff cell.
• The \D-Input of this $dff or $adff cell is driven by a multiplexer tree that only has constants or the
old state value on its leaves.
• The state value is only used in the said multiplexer tree or by simple relational cells that compare
the state value to a constant (usually $eq cells).
This heuristic has proven to work very well. It is possible to overwrite it by setting \fsm_encoding= "auto"
on registers that should be considered FSM state registers and setting \fsm_encoding= "none" on registers
that match the above criteria but should not be considered FSM state registers.
Note however that marking state registers with \fsm_encoding that are not suitable for FSM recoding can
cause synthesis to fail or produce invalid results.

8.2.2

FSM Extraction

The fsm_extract pass operates on all state signals marked with the \fsm_encoding (!= "none") attribute.
For each state signal the following information is determined:
• The state registers
• The asynchronous reset state if the state registers use asynchronous reset
• All states and the control input signals used in the state transition functions
• The control output signals calculated from the state signals and control inputs
• A table of all state transitions and corresponding control inputs- and outputs

65

CHAPTER 8. OPTIMIZATIONS
The state registers (and asynchronous reset state, if applicable) is simply determined by identifying the
driver for the state signal.
From there the $mux-tree driving the state register inputs is recursively traversed. All select inputs are
control signals and the leaves of the $mux-tree are the states. The algorithm fails if a non-constant leaf
that is not the state signal itself is found.
The list of control outputs is initialized with the bits from the state signal. It is then extended by adding
all values that are calculated by cells that compare the state signal with a constant value.
In most cases this will cover all uses of the state register, thus rendering the state encoding arbitrary. If
however a design uses e.g. a single bit of the state value to drive a control output directly, this bit of the
state signal will be transformed to a control output of the same value.
Finally, a transition table for the FSM is generated. This is done by using the ConstEval C++ helper class
(defined in kernel/consteval.h) that can be used to evaluate parts of the design. The ConstEval class can
be asked to calculate a given set of result signals using a set of signal-value assignments. It can also be
passed a list of stop-signals that abort the ConstEval algorithm if the value of a stop-signal is needed in
order to calculate the result signals.
The fsm_extract pass uses the ConstEval class in the following way to create a transition table. For each
state:
1. Create a ConstEval object for the module containing the FSM
2. Add all control inputs to the list of stop signals
3. Set the state signal to the current state
4. Try to evaluate the next state and control output
5. If step 4 was not successful:
• Recursively goto step 4 with the offending stop-signal set to 0.
• Recursively goto step 4 with the offending stop-signal set to 1.
6. If step 4 was successful: Emit transition
Finally a $fsm cell is created with the generated transition table and added to the module. This new cell
is connected to the control signals and the old drivers for the control outputs are disconnected.

8.2.3

FSM Optimization

The fsm_opt pass performs basic optimizations on $fsm cells (not including state recoding). The following
optimizations are performed (in this order):
• Unused control outputs are removed from the $fsm cell. The attribute \unused_bits (that is usually
set by the opt_clean pass) is used to determine which control outputs are unused.
• Control inputs that are connected to the same driver are merged.
• When a control input is driven by a control output, the control input is removed and the transition
table altered to give the same performance without the external feedback path.
• Entries in the transition table that yield the same output and only differ in the value of a single
control input bit are merged and the different bit is removed from the sensitivity list (turned into a
don’t-care bit).
• Constant inputs are removed and the transition table is altered to give an unchanged behaviour.
• Unused inputs are removed.
66

CHAPTER 8. OPTIMIZATIONS

8.2.4

FSM Recoding

The fsm_recode pass assigns new bit pattern to the states. Usually this also implies a change in the width
of the state signal. At the moment of this writing only one-hot encoding with all-zero for the reset state
is supported.
The fsm_recode pass can also write a text file with the changes performed by it that can be used when
verifying designs synthesized by Yosys using Synopsys Formality [24].

8.3

Logic Optimization

Yosys can perform multi-level combinational logic optimization on gate-level netlists using the external
program ABC [27]. The abc pass extracts the combinational gate-level parts of the design, passes it
through ABC, and re-integrates the results. The abc pass can also be used to perform other operations
using ABC, such as technology mapping (see Sec. 9.3 for details).

67

Chapter 9

Technology Mapping
Previous chapters outlined how HDL code is transformed into an RTL netlist. The RTL netlist is still
based on abstract coarse-grain cell types like arbitrary width adders and even multipliers. This chapter
covers how an RTL netlist is transformed into a functionally equivalent netlist utilizing the cell types
available in the target architecture.
Technology mapping is often performed in two phases. In the first phase RTL cells are mapped to an
internal library of single-bit cells (see Sec. 5.2). In the second phase this netlist of internal gate types is
transformed to a netlist of gates from the target technology library.
When the target architecture provides coarse-grain cells (such as block ram or ALUs), these must be
mapped to directly form the RTL netlist, as information on the coarse-grain structure of the design is lost
when it is mapped to bit-width gate types.

9.1

Cell Substitution

The simplest form of technology mapping is cell substitution, as performed by the techmap pass. This pass,
when provided with a Verilog file that implements the RTL cell types using simpler cells, simply replaces
the RTL cells with the provided implementation.
When no map file is provided, techmap uses a built-in map file that maps the Yosys RTL cell types to the internal gate library used by Yosys. The curious reader may find this map file as techlibs/common/techmap.v
in the Yosys source tree.
Additional features have been added to techmap to allow for conditional mapping of cells (see help techmap
or Sec. C.126). This can for example be useful if the target architecture supports hardware multipliers for
certain bit-widths but not for others.
A usual synthesis flow would first use the techmap pass to directly map some RTL cells to coarse-grain cells
provided by the target architecture (if any) and then use techmap with the built-in default file to map the
remaining RTL cells to gate logic.

9.2

Subcircuit Substitution

Sometimes the target architecture provides cells that are more powerful than the RTL cells used by Yosys.
For example a cell in the target architecture that can calculate the absolute-difference of two numbers does
not match any single RTL cell type but only combinations of cells.

68

CHAPTER 9. TECHNOLOGY MAPPING
For these cases Yosys provides the extract pass that can match a given set of modules against a design
and identify the portions of the design that are identical (i.e. isomorphic subcircuits) to any of the given
modules. These matched subcircuits are then replaced by instances of the given modules.
The extract pass also finds basic variations of the given modules, such as swapped inputs on commutative
cell types.
In addition to this the extract pass also has limited support for frequent subcircuit mining, i.e. the process
of finding recurring subcircuits in the design. This has a few applications, including the design of new
coarse-grain architectures [GW13].
The hard algorithmic work done by the extract pass (solving the isomorphic subcircuit problem and
frequent subcircuit mining) is performed using the SubCircuit library that can also be used stand-alone
without Yosys (see Sec. A.3).

9.3

Gate-Level Technology Mapping

On the gate-level the target architecture is usually described by a “Liberty file”. The Liberty file format is
an industry standard format that can be used to describe the behaviour and other properties of standard
library cells [25].
Mapping a design utilizing the Yosys internal gate library (e.g. as a result of mapping it to this representation using the techmap pass) is performed in two phases.
First the register cells must be mapped to the registers that are available on the target architectures. The
target architecture might not provide all variations of d-type flip-flops with positive and negative clock
edge, high-active and low-active asynchronous set and/or reset, etc. Therefore the process of mapping the
registers might add additional inverters to the design and thus it is important to map the register cells
first.
Mapping of the register cells may be performed by using the dfflibmap pass. This pass expects a Liberty
file as argument (using the -liberty option) and only uses the register cells from the Liberty file.
Secondly the combinational logic must be mapped to the target architecture. This is done using the
external program ABC [27] via the abc pass by using the -liberty option to the pass. Note that in this
case only the combinatorial cells are used from the cell library.
Occasionally Liberty files contain trade secrets (such as sensitive timing information) that cannot be shared
freely. This complicates processes such as reporting bugs in the tools involved. When the information in
the Liberty file used by Yosys and ABC are not part of the sensitive information, the additional tool
yosys-filterlib (see Sec. B.2) can be used to strip the sensitive information from the Liberty file.

69

Appendix A

Auxiliary Libraries
The Yosys source distribution contains some auxiliary libraries that are bundled with Yosys.

A.1

SHA1

The files in libs/sha1/ provide a public domain SHA1 implementation written by Steve Reid, Bruce
Guenter, and Volker Grabsch. It is used for generating unique names when specializing parameterized
modules.

A.2

BigInt

The files in libs/bigint/ provide a library for performing arithmetic with arbitrary length integers. It is
written by Matt McCutchen [29].
The BigInt library is used for evaluating constant expressions, e.g. using the ConstEval class provided in
kernel/consteval.h.

A.3

SubCircuit

The files in libs/subcircuit provide a library for solving the subcircuit isomorphism problem. It is written
by Clifford Wolf and based on the Ullmann Subgraph Isomorphism Algorithm [Ull76]. It is used by the
extract pass (see help extract or Sec. C.39).

A.4

ezSAT

The files in libs/ezsat provide a library for simplifying generating CNF formulas for SAT solvers. It also
contains bindings of MiniSAT. The ezSAT library is written by Clifford Wolf. It is used by the sat pass
(see help sat or Sec. C.102).

70

Appendix B

Auxiliary Programs
Besides the main yosys executable, the Yosys distribution contains a set of additional helper programs.

B.1

yosys-config

The yosys-config tool (an auto-generated shell-script) can be used to query compiler options and other
information needed for building loadable modules for Yosys. FIXME: See Sec. 6 for details.

B.2

yosys-filterlib

The yosys-filterlib tool is a small utility that can be used to strip or extract information from a Liberty
file. See Sec. 9.3 for details.

B.3

yosys-abc

This is a unmodified copy of ABC [27]. Not all versions of Yosys work with all versions of ABC. So Yosys
comes with its own yosys-abc to avoid compatibility issues between the two.

71

Appendix C

Command Reference Manual
C.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

abc – use ABC for technology mapping

abc [options] [selection]
This pass uses the ABC tool [1] for technology mapping of yosys’s internal gate
library to a target architecture.
-exe 
use the specified command instead of "/yosys-abc" to execute ABC.
This can e.g. be used to call a specific version of ABC or a wrapper.
-script 
use the specified ABC script file instead of the default script.
if  starts with a plus sign (+), then the rest of the filename
string is interpreted as the command string to be passed to ABC. The
leading plus sign is removed and all commas (,) in the string are
replaced with blanks before the string is passed to ABC.
if no -script parameter is given, the following scripts are used:
for -liberty without -constr:
strash; dc2; scorr; ifraig; retime -o {D}; strash; dch -f;
map {D}
for -liberty with -constr:
strash; dc2; scorr; ifraig; retime -o {D}; strash; dch -f;
map {D}; buffer; upsize {D}; dnsize {D}; stime -p
for -lut/-luts (only one LUT size):
strash; dc2; scorr; ifraig; retime -o; strash; dch -f; if; mfs;
lutpack
for -lut/-luts (different LUT sizes):
strash; dc2; scorr; ifraig; retime -o; strash; dch -f; if; mfs
for -sop:

72

APPENDIX C. COMMAND REFERENCE MANUAL
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

strash; dc2; scorr; ifraig; retime -o; strash; dch -f;
cover {I} {P}
otherwise:
strash; dc2; scorr; ifraig; retime -o; strash; dch -f; map
-fast
use different default scripts that are slightly faster (at the cost
of output quality):
for -liberty without -constr:
retime -o {D}; map {D}
for -liberty with -constr:
retime -o {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p
for -lut/-luts:
retime -o; if
for -sop:
retime -o; cover -I {I} -P {P}
otherwise:
retime -o; map
-liberty 
generate netlists for the specified cell library (using the liberty
file format).
-constr 
pass this file with timing constraints to ABC. use with -liberty.
a constr file contains two lines:
set_driving_cell 
set_load 
the set_driving_cell statement defines which cell type is assumed to
drive the primary inputs and the set_load statement sets the load in
femtofarads for each primary output.
-D 
set delay target. the string {D} in the default scripts above is
replaced by this option when used, and an empty string otherwise.
-I 
maximum number of SOP inputs.
(replaces {I} in the default scripts above)
-P 
maximum number of SOP products.
(replaces {P} in the default scripts above)
-lut 
generate netlist using luts of (max) the specified width.

73

APPENDIX C. COMMAND REFERENCE MANUAL
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

-lut :
generate netlist using luts of (max) the specified width . All
luts with width <=  have constant cost. for luts larger than 
the area cost doubles with each additional input bit. the delay cost
is still constant for all lut widths.
-luts ,,,:,..
generate netlist using luts. Use the specified costs for luts with 1,
2, 3, .. inputs.
-sop
map to sum-of-product cells and inverters
-g type1,type2,...
Map the the specified list of gate types. Supported gates types are:
AND, NAND, OR, NOR, XOR, XNOR, MUX, AOI3, OAI3, AOI4, OAI4.
(The NOT gate is always added to this list automatically.)
-dff
also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many
clock domains are automatically partitioned in clock domains and each
domain is passed through ABC independently.
-clk [!][,[!]]
use only the specified clock domain. this is like -dff, but only FF
cells that belong to the specified clock domain are used.
-keepff
set the "keep" attribute on flip-flop output wires. (and thus preserve
them, for example for equivalence checking.)
-nocleanup
when this option is used, the temporary files created by this pass
are not removed. this is useful for debugging.
-showtmp
print the temp dir name in log. usually this is suppressed so that the
command output is identical across runs.
-markgroups
set a ’abcgroup’ attribute on all objects created by ABC. The value of
this attribute is a unique integer for each ABC process started. This
is useful for debugging the partitioning of clock domains.
When neither -liberty nor -lut is used, the Yosys standard cell library is
loaded into ABC before the ABC script is executed.
This pass does not operate on modules with unprocessed processes in it.
(I.e. the ’proc’ pass should be used first to convert processes to netlists.)
[1] http://www.eecs.berkeley.edu/~alanmi/abc/

74

APPENDIX C. COMMAND REFERENCE MANUAL

C.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

add  [selection]
This command adds objects to the design. It operates on all fully selected
modules. So e.g. ’add -wire foo’ will add a wire foo to all selected modules.

add {-wire|-input|-inout|-output}   [selection]
Add a wire (input, inout, output port) with the given name and width. The
command will fail if the object exists already and has different properties
than the object to be created.

add -global_input   [selection]
Like ’add -input’, but also connect the signal between instances of the
selected modules.

C.3
1
2
3
4
5
6
7

Replace all logic cells with circuits made of only $_AND_ and
$_NOT_ cells.
-nand
Enable creation of $_NAND_ cells

alumacc – extract ALU and MACC cells

alumacc [selection]
This pass translates arithmetic operations like $add, $mul, $lt, etc. to $alu
and $macc cells.

C.5
1
2
3
4
5
6
7
8

aigmap – map logic to and-inverter-graph circuit

aigmap [options] [selection]

C.4
1
2
3
4

add – add objects to the design

assertpmux – convert internal signals to module ports

assertpmux [options] [selection]
This command adds asserts to the design that assert that all parallel muxes
($pmux cells) have a maximum of one of their inputs enable at any time.
-noinit
do not enforce the pmux condition during the init state

75

APPENDIX C. COMMAND REFERENCE MANUAL
9
10
11
12

-always
usually the $pmux condition is only checked when the $pmux output
is used be the mux tree it drives. this option will deactivate this
additional constrained and check the $pmux condition always.

C.6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

attrmap [options] [selection]
This command renames attributes and/or mapps key/value pairs to
other key/value pairs.
-tocase 
Match attribute names case-insensitively and set it to the specified
name.
-rename  
Rename attributes as specified
-map = =
Map key/value pairs as indicated.
-imap = =
Like -map, but use case-insensitive match for  when
it is a string value.
-remove =
Remove attributes matching this pattern.
-modattr
Operate on module attributes instead of attributes on wires and cells.
For example, mapping Xilinx-style "keep" attributes to Yosys-style:
attrmap -tocase keep -imap keep="true" keep=1 \
-imap keep="false" keep=0 -remove keep=0

C.7

1
2
3
4
5
6
7
8
9

attrmap – renaming attributes

attrmvcp – move or copy attributes from wires to driving
cells

attrmvcp [options] [selection]
Move or copy attributes on wires to the cells driving them.
-copy
By default, attributes are moved. This will only add
the attribute to the cell, without removing it from
the wire.

76

APPENDIX C. COMMAND REFERENCE MANUAL
10
11
12
13
14
15
16
17
18
19
20
21
22
23

-purge
If no selected cell consumes the attribute, then it is
left on the wire by default. This option will cause the
attribute to be removed from the wire, even if no selected
cell takes it.
-driven
By default, attriburtes are moved to the cell driving the
wire. With this option set it will be moved to the cell
driven by the wire instead.
-attr 
Move or copy this attribute. This option can be used
multiple times.

C.8
1
2
3
4
5
6
7
8
9
10
11
12
13
14

cd 
This is just a shortcut for ’select -module ’.

cd 
When no module with the specified name is found, but there is a cell
with the specified name in the current module, then this is equivalent
to ’cd ’.
cd ..
This is just a shortcut for ’select -clear’.

C.9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

cd – a shortcut for ’select -module ’

check – check for obvious problems in the design

check [options] [selection]
This pass identifies the following problems in the current design:
- combinatorial loops
- two or more conflicting drivers for one wire
- used wires that do not have a driver
When called with -noinit then this command also checks for wires which have
the ’init’ attribute set.
When called with -assert then the command will produce an error if any
problems are found in the current design.

77

APPENDIX C. COMMAND REFERENCE MANUAL

C.10
1
2
3
4
5
6
7
8
9

chparam [ -set name value ]... [selection]
Re-evaluate the selected modules with new parameters. String values must be
passed in double quotes (").

chparam -list [selection]
List the available parameters of the selected modules.

C.11
1
2
3
4
5
6
7
8
9

This is identical to ’opt_clean’, but less verbose.
When commands are separated using the ’;;’ token, this command will be executed
between the commands.
When commands are separated using the ’;;;’ token, this command will be executed
in -purge mode between the commands.

clk2fflogic – convert clocked FFs to generic $ff cells

clk2fflogic [options] [selection]
This command replaces clocked flip-flops with generic $ff cells that use the
implicit global clock. This is useful for formal verification of designs with
multiple clocks.

C.13
1
2
3
4
5
6
7
8
9
10
11
12
13

clean – remove unused cells and wires

clean [options] [selection]

C.12
1
2
3
4
5

chparam – re-evaluate modules with new parameters

connect – create or remove connections

connect [-nomap] [-nounset] -set  
Create a connection. This is equivalent to adding the statement ’assign
 = ;’ to the Verilog input. Per default, all existing
drivers for  are unconnected. This can be overwritten by using
the -nounset option.

connect [-nomap] -unset 
Unconnect all existing drivers for the specified expression.

78

APPENDIX C. COMMAND REFERENCE MANUAL
14
15
16
17
18
19
20
21
22
23
24
25
26

connect [-nomap] -port   
Connect the specified cell port to the specified cell port.

Per default signal alias names are resolved and all signal names are mapped
the the signal name of the primary driver. Using the -nomap option deactivates
this behavior.
The connect command operates in one module only. Either only one module must
be selected or an active module must be set using the ’cd’ command.
This command does not operate on module with processes.

C.14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

connwrappers [options] [selection]
Wrappers are used in coarse-grain synthesis to wrap cells with smaller ports
in wrapper cells with a (larger) constant port size. I.e. the upper bits
of the wrapper output are signed/unsigned bit extended. This command uses this
knowledge to rewire the inputs of the driven cells to match the output of
the driving cell.
-signed   
-unsigned   
consider the specified signed/unsigned wrapper output
-port    
use the specified parameter to decide if signed or unsigned
The options -signed, -unsigned, and -port can be specified multiple times.

C.15
1
2
3
4

copy – copy modules in the design

copy old_name new_name
Copy the specified module. Note that selection patterns are not supported
by this command.

C.16
1
2
3
4
5

connwrappers – replace undef values with defined constants

cover – print code coverage counters

cover [options] [pattern]
Print the code coverage counters collected using the cover() macro in the Yosys
C++ code. This is useful to figure out what parts of Yosys are utilized by a
test bench.

79

APPENDIX C. COMMAND REFERENCE MANUAL
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

-q
Do not print output to the normal destination (console and/or log file)
-o file
Write output to this file, truncate if exists.
-a file
Write output to this file, append if exists.
-d dir
Write output to a newly created file in the specified directory.
When one or more pattern (shell wildcards) are specified, then only counters
matching at least one pattern are printed.

It is also possible to instruct Yosys to print the coverage counters on program
exit to a file using environment variables:
YOSYS_COVER_DIR="{dir-name}" yosys {args}
This will create a file (with an auto-generated name) in this
directory and write the coverage counters to it.
YOSYS_COVER_FILE="{file-name}" yosys {args}
This will append the coverage counters to the specified file.

Hint: Use the following AWK command to consolidate Yosys coverage files:
gawk ’{ p[$3] = $1; c[$3] += $2; } END { for (i in p)
printf "%-60s %10d %s\n", p[i], c[i], i; }’ {files} | sort -k3

Coverage counters are only available in Yosys for Linux.

C.17
1
2
3
4
5
6
7
8
9
10

delete – delete objects in the design

delete [selection]
Deletes the selected objects. This will also remove entire modules, if the
whole module is selected.

delete {-input|-output|-port} [selection]
Does not delete any object but removes the input and/or output flag on the
selected wires, thus ’deleting’ module ports.

80

APPENDIX C. COMMAND REFERENCE MANUAL

C.18
1
2
3

deminout [options] [selection]
"Demote" inout ports to input or output ports, if possible.

C.19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

deminout – demote inout ports to input or output

design – save, restore and reset current design

design -reset
Clear the current design.

design -save 
Save the current design under the given name.

design -stash 
Save the current design under the given name and then clear the current design.

design -push
Push the current design to the stack and then clear the current design.

design -pop
Reset the current design and pop the last design from the stack.

design -load 
Reset the current design and load the design previously saved under the given
name.

design -copy-from  [-as ] 
Copy modules from the specified design into the current one. The selection is
evaluated in the other design.

design -copy-to  [-as ] [selection]
Copy modules from the current design into the specified one.

C.20

dff2dffe – transform $dff cells to $dffe cells
81

APPENDIX C. COMMAND REFERENCE MANUAL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

dff2dffe [options] [selection]
This pass transforms $dff cells driven by a tree of multiplexers with one or
more feedback paths to $dffe cells. It also works on gate-level cells such as
$_DFF_P_, $_DFF_N_ and $_MUX_.
-unmap
operate in the opposite direction: replace $dffe cells with combinations
of $dff and $mux cells. the options below are ignore in unmap mode.
-direct  
map directly to external gate type.  can
be any internal gate-level FF cell (except $_DFFE_??_). the
 is the cell type name for a cell with an
identical interface to the , except it
also has an high-active enable port ’E’.
Usually  is an intermediate cell type
that is then translated to the final type using ’techmap’.
-direct-match 
like -direct for all DFF cell types matching the expression.
this will use $__DFFE_* as  matching the
internal gate type $_DFF_*_, except for $_DFF_[NP]_, which is
converted to $_DFFE_[NP]_.

C.21
1
2
3
4
5
6
7
8

dffinit [options] [selection]
This pass sets an FF cell parameter to the the initial value of the net it
drives. (This is primarily used in FPGA flows.)
-ff   
operate on the specified cell type. this option can be used
multiple times.

C.22
1
2
3
4
5
6
7
8
9
10
11

dffinit – set INIT param on FF cells

dfflibmap – technology mapping of flip-flops

dfflibmap [-prepare] -liberty  [selection]
Map internal flip-flop cells to the flip-flop cells in the technology
library specified in the given liberty file.
This pass may add inverters as needed. Therefore it is recommended to
first run this pass and then map the logic paths to the target technology.
When called with -prepare, this command will convert the internal FF cells
to the internal cell types that best match the cells found in the given
liberty file.

82

APPENDIX C. COMMAND REFERENCE MANUAL

C.23
1
2
3
4

dffsr2dff [options] [selection]
This pass converts DFFSR cells ($dffsr, $_DFFSR_???_) and ADFF cells ($adff,
$_DFF_???_) to simpler FF cell types when any of the set/reset inputs is unused.

C.24
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Write the selected parts of the design to the console or specified file in
ilang format.
-m
also dump the module headers, even if only parts of a single
module is selected
-n
only dump the module headers if the entire module is selected
-o 
write to the specified file.
-a 
like -outfile but append instead of overwrite

echo – turning echoing back of commands on and off

echo on
Print all commands to log before executing them.

echo off
Do not print all commands to log before executing them. (default)

C.26
1
2
3
4

dump – print parts of the design in ilang format

dump [options] [selection]

C.25
1
2
3
4
5
6
7
8

dffsr2dff – convert DFFSR cells to simpler FF cell types

edgetypes – list all types of edges in selection

edgetypes [options] [selection]
This command lists all unique types of ’edges’ found in the selection. An ’edge’
is a 4-tuple of source and sink cell type and port name.

83

APPENDIX C. COMMAND REFERENCE MANUAL

C.27
1
2
3
4
5
6
7
8

equiv_add [-try] gold_sig gate_sig
This command adds an $equiv cell for the specified signals.

equiv_add [-try] -cell gold_cell gate_cell
This command adds $equiv cells for the ports of the specified cells.

C.28

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

equiv_induct – proving $equiv cells using temporal induction

equiv_induct [options] [selection]
Uses a version of temporal induction to prove $equiv cells.
Only selected $equiv cells are proven and only selected cells are used to
perform the proof.
-undef
enable modelling of undef states
-seq 
the max. number of time steps to be considered (default = 4)
This command is very effective in proving complex sequential circuits, when
the internal state of the circuit quickly propagates to $equiv cells.
However, this command uses a weak definition of ’equivalence’: This command
proves that the two circuits will not diverge after they produce equal
outputs (observable points via $equiv) for at least  cycles (the 
specified via -seq).
Combined with simulation this is very powerful because simulation can give
you confidence that the circuits start out synced for at least  cycles
after reset.

C.29
1
2
3
4
5
6
7
8

equiv_add – add a $equiv cell

equiv_make – prepare a circuit for equivalence checking

equiv_make [options] gold_module gate_module equiv_module
This creates a module annotated with $equiv cells from two presumably
equivalent modules. Use commands such as ’equiv_simple’ and ’equiv_status’
to work with the created equivalent checking module.
-inames
Also match cells and wires with $... names.

84

APPENDIX C. COMMAND REFERENCE MANUAL
9
10
11
12
13
14
15
16
17
18
19

-blacklist 
Do not match cells or signals that match the names in the file.
-encfile 
Match FSM encodings using the description from the file.
See ’help fsm_recode’ for details.
Note: The circuit created by this command is not a miter (with something like
a trigger output), but instead uses $equiv cells to encode the equivalence
checking problem. Use ’miter -equiv’ if you want to create a miter circuit.

C.30
1
2
3
4
5
6

equiv_mark [options] [selection]
This command marks the regions in an equivalence checking module. Region 0 is
the proven part of the circuit. Regions with higher numbers are connected
unproven subcricuits. The integer attribute ’equiv_region’ is set on all
wires and cells.

C.31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

equiv_miter – extract miter from equiv circuit

equiv_miter [options] miter_module [selection]
This creates a miter module for further analysis of the selected $equiv cells.
-trigger
Create a trigger output
-cmp
Create cmp_* outputs for individual unproven $equiv cells
-assert
Create a $assert cell for each unproven $equiv cell
-undef
Create compare logic that handles undefs correctly

C.32
1
2
3
4
5

equiv_mark – mark equivalence checking regions

equiv_purge – purge equivalence checking module

equiv_purge [options] [selection]
This command removes the proven part of an equivalence checking module, leaving
only the unproven segments in the design. This will also remove and add module
ports as needed.

85

APPENDIX C. COMMAND REFERENCE MANUAL

C.33
1
2
3
4
5
6
7
8
9
10

equiv_remove [options] [selection]
This command removes the selected $equiv cells. If neither -gold nor -gate is
used then only proven cells are removed.
-gold
keep gold circuit
-gate
keep gate circuit

C.34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

This command tries to prove $equiv cells using a simple direct SAT approach.
-v
verbose output
-undef
enable modelling of undef states
-nogroup
disabling grouping of $equiv cells by output wire
-seq 
the max. number of time steps to be considered (default = 1)

equiv_status – print status of equivalent checking module

equiv_status [options] [selection]
This command prints status information for all selected $equiv cells.
-assert
produce an error if any unproven $equiv cell is found

C.36
1
2
3
4
5

equiv_simple – try proving simple $equiv instances

equiv_simple [options] [selection]

C.35
1
2
3
4
5
6

equiv_remove – remove $equiv cells

equiv_struct – structural equivalence checking

equiv_struct [options] [selection]
This command adds additional $equiv cells based on the assumption that the
gold and gate circuit are structurally equivalent. Note that this can introduce
bad $equiv cells in cases where the netlists are not structurally equivalent,

86

APPENDIX C. COMMAND REFERENCE MANUAL
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

for example when analyzing circuits with cells with commutative inputs. This
command will also de-duplicate gates.
-fwd
by default this command performans forward sweeps until nothing can
be merged by forwards sweeps, then backward sweeps until forward
sweeps are effective again. with this option set only forward sweeps
are performed.
-fwonly 
add the specified cell type to the list of cell types that are only
merged in forward sweeps and never in backward sweeps. $equiv is in
this list automatically.
-icells
by default, the internal RTL and gate cell types are ignored. add
this option to also process those cell types with this command.
-maxiter 
maximum number of iterations to run before aborting

C.37
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

eval [options] [selection]
This command evaluates the value of a signal given the value of all required
inputs.
-set  
set the specified signal to the specified value.
-set-undef
set all unspecified source signals to undef (x)
-table 
create a truth table using the specified input signals
-show 
show the value for the specified signal. if no -show option is passed
then all output ports of the current module are used.

C.38
1
2
3
4
5
6
7

eval – evaluate the circuit given an input

expose – convert internal signals to module ports

expose [options] [selection]
This command exposes all selected internal signals of a module as additional
outputs.
-dff
only consider wires that are directly driven by register cell.

87

APPENDIX C. COMMAND REFERENCE MANUAL
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

-cut
when exposing a wire, create an input/output pair and cut the internal
signal path at that wire.
-shared
only expose those signals that are shared among the selected modules.
this is useful for preparing modules for equivalence checking.
-evert
also turn connections to instances of other modules to additional
inputs and outputs and remove the module instances.
-evert-dff
turn flip-flops to sets of inputs and outputs.
-sep 
when creating new wire/port names, the original object name is suffixed
with this separator (default: ’.’) and the port name or a type
designator for the exposed signal.

C.39
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

extract – find subcircuits and replace them with cells

extract -map  [options] [selection]
extract -mine  [options] [selection]
This pass looks for subcircuits that are isomorphic to any of the modules
in the given map file and replaces them with instances of this modules. The
map file can be a Verilog source file (*.v) or an ilang file (*.il).
-map 
use the modules in this file as reference. This option can be used
multiple times.
-map %
use the modules in this in-memory design as reference. This option can
be used multiple times.
-verbose
print debug output while analyzing
-constports
also find instances with constant drivers. this may be much
slower than the normal operation.
-nodefaultswaps
normally builtin port swapping rules for internal cells are used per
default. This turns that off, so e.g. ’a^b’ does not match ’b^a’
when this option is used.
-compat  
Per default, the cells in the map file (needle) must have the

88

APPENDIX C. COMMAND REFERENCE MANUAL
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

type as the cells in the active design (haystack). This option
can be used to register additional pairs of types that should
match. This option can be used multiple times.
-swap  ,[,...]
Register a set of swappable ports for a needle cell type.
This option can be used multiple times.
-perm  ,[,...] ,[,...]
Register a valid permutation of swappable ports for a needle
cell type. This option can be used multiple times.
-cell_attr 
Attributes on cells with the given name must match.
-wire_attr 
Attributes on wires with the given name must match.
-ignore_parameters
Do not use parameters when matching cells.
-ignore_param  
Do not use this parameter when matching cells.
This pass does not operate on modules with unprocessed processes in it.
(I.e. the ’proc’ pass should be used first to convert processes to netlists.)
This pass can also be used for mining for frequent subcircuits. In this mode
the following options are to be used instead of the -map option.
-mine 
mine for frequent subcircuits and write them to the given ilang file
-mine_cells_span  
only mine for subcircuits with the specified number of cells
default value: 3 5
-mine_min_freq 
only mine for subcircuits with at least the specified number of matches
default value: 10
-mine_limit_matches_per_module 
when calculating the number of matches for a subcircuit, don’t count
more than the specified number of matches per module
-mine_max_fanout 
don’t consider internal signals with more than  connections
The modules in the map file may have the attribute ’extract_order’ set to an
integer value. Then this value is used to determine the order in which the pass
tries to map the modules to the design (ascending, default value is 0).
See ’help techmap’ for a pass that does the opposite thing.

89

APPENDIX C. COMMAND REFERENCE MANUAL

C.40
1
2
3
4
5
6
7
8

flatten [selection]
This pass flattens the design by replacing cells by their implementation. This
pass is very similar to the ’techmap’ pass. The only difference is that this
pass is using the current design as mapping library.
Cells and/or modules with the ’keep_hierarchy’ attribute set will not be
flattened by this command.

C.41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

freduce – perform functional reduction

freduce [options] [selection]
This pass performs functional reduction in the circuit. I.e. if two nodes are
equivalent, they are merged to one node and one of the redundant drivers is
disconnected. A subsequent call to ’clean’ will remove the redundant drivers.
-v, -vv
enable verbose or very verbose output
-inv
enable explicit handling of inverted signals
-stop 
stop after  reduction operations. this is mostly used for
debugging the freduce command itself.
-dump 
dump the design to __.il after each reduction
operation. this is mostly used for debugging the freduce command.
This pass is undef-aware, i.e. it considers don’t-care values for detecting
equivalent nodes.
All selected wires are considered for rewiring. The selected cells cover the
circuit that is analyzed.

C.42
1
2
3
4
5
6
7
8

flatten – flatten design

fsm – extract and optimize finite state machines

fsm [options] [selection]
This pass calls all the other fsm_* passes in a useful order. This performs
FSM extraction and optimization. It also calls opt_clean as needed:
fsm_detect
fsm_extract

unless got option -nodetect

90

APPENDIX C. COMMAND REFERENCE MANUAL
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

fsm_opt
opt_clean
fsm_opt
fsm_expand

if got option -expand

opt_clean
fsm_opt

if got option -expand
if got option -expand

fsm_recode

unless got option -norecode

fsm_info
fsm_export
fsm_map
Options:
-expand, -norecode, -export, -nomap
enable or disable passes as indicated above
-fullexpand
call expand with -full option
-encoding type
-fm_set_fsm_file file
-encfile file
passed through to fsm_recode pass

C.43
1
2
3
4
5
6
7
8
9
10

fsm_detect – finding FSMs in design

fsm_detect [selection]
This pass detects finite state machines by identifying the state signal.
The state signal is then marked by setting the attribute ’fsm_encoding’
on the state signal to "auto".
Existing ’fsm_encoding’ attributes are not changed by this pass.
Signals can be protected from being detected by this pass by setting the
’fsm_encoding’ attribute to "none".

C.44
1
2
3
4
5
6
7

if got option -export
unless got option -nomap

fsm_expand – expand FSM cells by merging logic into it

fsm_expand [-full] [selection]
The fsm_extract pass is conservative about the cells that belong to a finite
state machine. This pass can be used to merge additional auxiliary gates into
the finite state machine.
By default, fsm_expand is still a bit conservative regarding merging larger

91

APPENDIX C. COMMAND REFERENCE MANUAL
8

word-wide cells. Call with -full to consider all cells for merging.

C.45
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

fsm_export [-noauto] [-o filename] [-origenc] [selection]
This pass creates a KISS2 file for every selected FSM. For FSMs with the
’fsm_export’ attribute set, the attribute value is used as filename, otherwise
the module and cell name is used as filename. If the parameter ’-o’ is given,
the first exported FSM is written to the specified filename. This overwrites
the setting as specified with the ’fsm_export’ attribute. All other FSMs are
exported to the default name as mentioned above.
-noauto
only export FSMs that have the ’fsm_export’ attribute set
-o filename
filename of the first exported FSM
-origenc
use binary state encoding as state names instead of s0, s1, ...

C.46
1
2
3
4
5
6
7
8
9
10

fsm_extract – extracting FSMs in design

fsm_extract [selection]
This pass operates on all signals marked as FSM state signals using the
’fsm_encoding’ attribute. It consumes the logic that creates the state signal
and uses the state signal to generate control signal and replaces it with an
FSM cell.
The generated FSM cell still generates the original state signal with its
original encoding. The ’fsm_opt’ pass can be used in combination with the
’opt_clean’ pass to eliminate this signal.

C.47
1
2
3
4
5

fsm_export – exporting FSMs to KISS2 files

fsm_info – print information on finite state machines

fsm_info [selection]
This pass dumps all internal information on FSM cells. It can be useful for
analyzing the synthesis process and is called automatically by the ’fsm’
pass so that this information is included in the synthesis log file.

92

APPENDIX C. COMMAND REFERENCE MANUAL

C.48
1
2
3

fsm_map [selection]
This pass translates FSM cells to flip-flops and logic.

C.49
1
2
3
4
5

This pass optimizes FSM cells. It detects which output signals are actually
not used and removes them from the FSM. This pass is usually used in
combination with the ’opt_clean’ pass (see also ’help fsm’).

fsm_recode – recoding finite state machines

fsm_recode [options] [selection]
This pass reassign the state encodings for FSM cells. At the moment only
one-hot encoding and binary encoding is supported.
-encoding 
specify the encoding scheme used for FSMs without the
’fsm_encoding’ attribute or with the attribute set to ‘auto’.
-fm_set_fsm_file 
generate a file containing the mapping from old to new FSM encoding
in form of Synopsys Formality set_fsm_* commands.
-encfile 
write the mappings from old to new FSM encoding to a file in the
following format:
.fsm  
.map  

C.51
1
2
3
4

fsm_opt – optimize finite state machines

fsm_opt [selection]

C.50
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

fsm_map – mapping FSMs to basic logic

greenpak4_counters – Extract GreenPak4 counter cells

greenpak4_counters [options] [selection]
This pass converts non-resettable or async resettable down counters to GreenPak4
counter cells (All other GreenPak4 counter modes must be instantiated manually.)

93

APPENDIX C. COMMAND REFERENCE MANUAL

C.52
1
2
3

greenpak4_dffinv [options] [selection]
Merge GP_INV cells with GP_DFF* cells.

C.53
1
2
3
4
5
6
7

help

help – display help messages
................

list all commands

help  ......
help -all ...........

print help message for given command
print complete command reference

help -cells ..........
help  .....
help + ....

list all cell types
print help message for given cell type
print verilog code for given cell type

C.54
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

greenpak4_dffinv – merge greenpak4 inverters and DFFs

hierarchy – check, expand and clean up design hierarchy

hierarchy [-check] [-top ]
hierarchy -generate  
In parametric designs, a module might exists in several variations with
different parameter values. This pass looks at all modules in the current
design an re-runs the language frontends for the parametric modules as
needed.
-check
also check the design hierarchy. this generates an error when
an unknown module is used as cell type.
-purge_lib
by default the hierarchy command will not remove library (blackbox)
modules. use this option to also remove unused blackbox modules.
-libdir 
search for files named .v in the specified directory
for unknown modules and automatically run read_verilog for each
unknown module.
-keep_positionals
per default this pass also converts positional arguments in cells
to arguments using port names. this option disables this behavior.
-nokeep_asserts
per default this pass sets the "keep" attribute on all modules
that directly or indirectly contain one or more $assert cells. this
option disables this behavior.
-top 

94

APPENDIX C. COMMAND REFERENCE MANUAL
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

use the specified top module to built a design hierarchy. modules
outside this tree (unused modules) are removed.
when the -top option is used, the ’top’ attribute will be set on the
specified top module. otherwise a module with the ’top’ attribute set
will implicitly be used as top module, if such a module exists.
-auto-top
automatically determine the top of the design hierarchy and mark it.
In -generate mode this pass generates blackbox modules for the given cell
types (wildcards supported). For this the design is searched for cells that
match the given types and then the given port declarations are used to
determine the direction of the ports. The syntax for a port declaration is:
{i|o|io}[@]:
Input ports are specified with the ’i’ prefix, output ports with the ’o’
prefix and inout ports with the ’io’ prefix. The optional  specifies
the position of the port in the parameter list (needed when instantiated
using positional arguments). When  is not specified, the  can
also contain wildcard characters.
This pass ignores the current selection and always operates on all modules
in the current design.

C.55

1
2
3
4
5
6
7
8
9
10
11
12
13
14

hilomap [options] [selection]
Map constants to ’tielo’ and ’tiehi’ driver cells.
-hicell  
Replace constant hi bits with this cell.
-locell  
Replace constant lo bits with this cell.
-singleton
Create only one hi/lo cell and connect all constant bits
to that cell. Per default a separate cell is created for
each constant bit.

C.56
1
2
3

hilomap – technology mapping of constant hi- and/or lodrivers

history – show last interactive commands

history
This command prints all commands in the shell history buffer. This are

95

APPENDIX C. COMMAND REFERENCE MANUAL
4
5

all commands executed in an interactive session, but not the commands
from executed scripts.

C.57
1
2
3
4

ice40_ffinit [options] [selection]
Remove zero init values for FF output signals. Add inverters to implement
nonzero init values.

C.58

1
2
3

Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.

ice40_opt – iCE40: perform simple optimizations

ice40_opt [options] [selection]
This command executes the following script:
do

opt_expr -mux_undef -undriven [-full]
opt_merge
opt_rmdff
opt_clean
while 
When called with the option -unlut, this command will transform all already
mapped SB_LUT4 cells back to logic.

C.60
1
2
3
4
5
6
7

ice40_ffssr – iCE40: merge synchronous set/reset into FF
cells

ice40_ffssr [options] [selection]

C.59
1
2
3
4
5
6
7
8
9
10
11
12
13
14

ice40_ffinit – iCE40: handle FF init values

insbuf – insert buffer cells for connected wires

insbuf [options] [selection]
Insert buffer cells into the design for directly connected wires.
-buf   
Use the given cell type instead of $_BUF_. (Notice that the next
call to "clean" will remove all $_BUF_ in the design.)

96

APPENDIX C. COMMAND REFERENCE MANUAL

C.61
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

iopadmap [options] [selection]
Map module inputs/outputs to PAD cells from a library. This pass
can only map to very simple PAD cells. Use ’techmap’ to further map
the resulting cells to more sophisticated PAD cells.
-inpad  [:]
Map module input ports to the given cell type with the
given output port name. if a 2nd portname is given, the
signal is passed through the pad call, using the 2nd
portname as the port facing the module port.
-outpad  [:]
-inoutpad  [:]
Similar to -inpad, but for output and inout ports.
-toutpad  :[:]
Merges $_TBUF_ cells into the output pad cell. This takes precedence
over the other -outpad cell. The first portname is the enable input
of the tristate driver.
-tinoutpad  ::[:]
Merges $_TBUF_ cells into the inout pad cell. This takes precedence
over the other -inoutpad cell. The first portname is the enable input
of the tristate driver and the 2nd portname is the internal output
buffering the external signal.
-widthparam 
Use the specified parameter name to set the port width.
-nameparam 
Use the specified parameter to set the port name.
-bits
create individual bit-wide buffers even for ports that
are wider. (the default behavior is to create word-wide
buffers using -widthparam to set the word size on the cell.)
Tristate PADS (-toutpad, -tinoutpad) always operate in -bits mode.

C.62
1
2
3
4
5
6
7
8

iopadmap – technology mapping of i/o pads (or buffers)

json – write design in JSON format

json [options] [selection]
Write a JSON netlist of all selected objects.
-o 
write to the specified file.
-aig

97

APPENDIX C. COMMAND REFERENCE MANUAL
9
10
11

also include AIG models for the different gate types
See ’help write_json’ for a description of the JSON format used.

C.63
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

log string
Print the given string to the screen and/or the log file. This is useful for TCL
scripts, because the TCL command "puts" only goes to stdout but not to
logfiles.
-stdout
Print the output to stdout too. This is useful when all Yosys is executed
with a script and the -q (quiet operation) argument to notify the user.
-stderr
Print the output to stderr too.
-nolog
Don’t use the internal log() command. Use either -stdout or -stderr,
otherwise no output will be generated at all.
-n
do not append a newline

C.64
1
2
3
4
5

When no active module is selected, this prints a list of modules.
When an active module is selected, this prints a list of objects in the module.

lut2mux – convert $lut to $_MUX_

lut2mux [options] [selection]
This pass converts $lut cells to $_MUX_ gates.

C.66
1
2
3
4

ls – list modules or objects in modules

ls [selection]

C.65
1
2
3

log – print text and log files

maccmap – mapping macc cells

maccmap [-unmap] [selection]
This pass maps $macc cells to yosys $fa and $alu cells. When the -unmap option
is used then the $macc cell is mapped to $add, $sub, etc. cells instead.

98

APPENDIX C. COMMAND REFERENCE MANUAL

C.67
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

memory [-nomap] [-nordff] [-memx] [-bram ] [selection]
This pass calls all the other memory_* passes in a useful order:
memory_dff [-nordff]
opt_clean
memory_share
opt_clean
memory_memx

(-memx implies -nordff)

(when called with -memx)

memory_collect
memory_bram -rules 
memory_map

(when called with -bram)
(skipped if called with -nomap)

This converts memories to word-wide DFFs and address decoders
or multiport memory blocks if called with the -nomap option.

C.68
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

memory – translate memories to basic cells

memory_bram – map memories to block rams

memory_bram -rules  [selection]
This pass converts the multi-port $mem memory cells into block ram instances.
The given rules file describes the available resources and how they should be
used.
The rules file contains a set of block ram description and a sequence of match
rules. A block ram description looks like this:
bram RAMB1024X32
init 1
abits 10
dbits 32
groups
ports
wrmode
enable
transp
clocks

2
1
1
4
0
1

1
0
1
2
2

clkpol 2 2
endbram

#
#
#
#

name of BRAM cell
set to ’1’ if BRAM can be initialized
number of address bits
number of data bits

#
#
#
#
#
#

number of port groups
number of ports in each group
set to ’1’ if this groups is write ports
number of enable bits
transparent (for read ports)
clock configuration

# clock polarity configuration

For the option ’transp’ the value 0 means non-transparent, 1 means transparent
and a value greater than 1 means configurable. All groups with the same
value greater than 1 share the same configuration bit.
For the option ’clocks’ the value 0 means non-clocked, and a value greater
than 0 means clocked. All groups with the same value share the same clock
signal.
For the option ’clkpol’ the value 0 means negative edge, 1 means positive edge
and a value greater than 1 means configurable. All groups with the same value

99

APPENDIX C. COMMAND REFERENCE MANUAL
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

greater than 1 share the same configuration bit.
Using the same bram name in different bram blocks will create different variants
of the bram. Verilog configuration parameters for the bram are created as needed.
It is also possible to create variants by repeating statements in the bram block
and appending ’@