yosys针对一套开源verilog的rtl综合框架,从本节开始详细介绍工具的使用,详细分析和解释源代码,首先介绍工具的安装和使用。yosys的git网址为https://github.com/YosysHQ/yosys。
下面将介绍如何在这里ubuntu安装在环境中,使用的环境是ubuntu16.0。
安装
准备工作
安装Tabby CAD Suite工具,网站为:Releases · YosysHQ/oss-cad-suite-build · GitHub,按系统下载指定的安装包:
这里的选择是linux-x64,然后根据安装指南GitHub - YosysHQ/oss-cad-suite-build: Multi-platform nightly builds of open source digital design and verification tools, 设置环境变量很简单。
安装必要的软件包:
apt-get install build-essential clang bison flex \ libreadline-dev gawk tcl-dev libffi-dev git \ graphviz xdot pkg-config python3 libboost-system-dev \ libboost-python-dev libboost-filesystem-dev zlib1g-dev
编译和安装
拷贝代码:
git clone https://github.com/YosysHQ/yosys.git
进入yosys目录执行编译和安装指令
make make install
正常情况下,安装会成功,当前目录会生成yosys等可执行程序:
EDA软件使用
执行当前目录:
./yosys
正常情况下会进入yosys界面:
我们以fiedler-cooley.v(目录/tests/simple以文件为例说明,verilog源代码如下:
module up3down5(clock, data_in, up, down, carry_out, borrow_out, count_out, parity_out); input [8:0] data_in; input clock, up, down; output reg [8:0] count_out; output reg carry_out, borrow_out, parity_out; reg [9:0] cnt_up, cnt_dn; reg [8:0] count_nxt; always @(posedge clock) begin cnt_dn = count_out - 3'b 101; cnt_up = count_out 2'b 11; case ({up,down}) 2'b 00 : count_nxt = data_in; 2'b 01 : count_nxt = cnt_dn; 2'b 10 : count_nxt = cnt_up; 2'b 11 : count_nxt = count_out; default : count_nxt = 9'bX; endcase parity_out <= ^count_nxt; carry_out <= up & cnt_up[9]; borrow_out <= down & cnt_dn[9]; count_out <= count_nxt; end endmodule
执行指令:
read -sv tests/simple/fiedler-cooley.v
读取verilog结果如下:
然后执行指令:
hierarchy -top up3down5
生成RTL结构如下:
然后执行指令:
write_ilang
将设计写入Yosys结果如下:
4. Executing RTLIL backend. Output filename: <stdout> # Generated by Yosys 0.17 50 (git sha1 f698a0514, gcc 5.4.0-6ubuntu1~16.04.12 -fPIC -Os) autoidx 7 attribute \hdlname "\\up3down5" attribute \top 1 attribute \src "tests/simple/fiedler-cooley.v:3.1-33.10" module \up3down5 attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire $0\borrow_out[0:0] attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire $0\carry_out[0:0] attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire width 10 $0\cnt_dn[9:0] attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire width 10 $0\cnt_up[9:0] attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire width 9 $0\count_nxt[8:0] attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire width 9 $0\count_out[8:0] attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire $0\parity_out[0:0] attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4" wire width 9 $1\count_nxt[8:0] attribute \src "tests/simple/fiedler-cooley.v:17.11-17.29" wire width 10 $add$tests/simple/fiedler-cooley.v:17$3_Y attribute \src "tests/simple/fiedler-cooley.v:28.17-28.31" wire $and$tests/simple/fiedler-cooley.v:28$5_Y attribute \src "tests/simple/fiedler-cooley.v:29.17-29.33" wire $and$tests/simple/fiedler-cooley.v:29$6_Y attribute \src "tests/simple/fiedler-cooley.v:27.17-27.27" wire $reduce_xor$tests/simple/fiedler-cooley.v:27$4_Y attribute \src "tests/simple/fiedler-cooley.v:16.11-16.30" wire width 10 $sub$tests/simple/fiedler-cooley.v:16$2_Y attribute \src "tests/simple/fiedler-cooley.v:9.23-9.33" wire output 6 \borrow_out attribute \src "tests/simple/fiedler-cooley.v:9.12-9.21" wire output 5 \carry_out attribute \src "tests/simple/fiedler-cooley.v:6.7-6.12" wire input 1 \clock attribute \src "tests/simple/fiedler-cooley.v:11.19-11.25" wire width 10 \cnt_dn attribute \src "tests/simple/fiedler-cooley.v:11.11-11.17" wire width 10 \cnt_up attribute \src "tests/simple/fiedler-cooley.v:12.11-12.20" wire width 9 \count_nxt attribute \src "tests/simple/fiedler-cooley.v:8.18-8.27" wire width 9 output 7 \count_out attribute \src "tests/simple/fiedler-cooley.v:5.13-5.20" wire width 9 input 2 \data_in attribute \src "tests/simple/fiedler-cooly.v:6.18-6.22"
wire input 4 \down
attribute \src "tests/simple/fiedler-cooley.v:9.35-9.45"
wire output 8 \parity_out
attribute \src "tests/simple/fiedler-cooley.v:6.14-6.16"
wire input 3 \up
attribute \src "tests/simple/fiedler-cooley.v:17.11-17.29"
cell $add $add$tests/simple/fiedler-cooley.v:17$3
parameter \A_SIGNED 0
parameter \A_WIDTH 9
parameter \B_SIGNED 0
parameter \B_WIDTH 2
parameter \Y_WIDTH 10
connect \A \count_out
connect \B 2'11
connect \Y $add$tests/simple/fiedler-cooley.v:17$3_Y
end
attribute \src "tests/simple/fiedler-cooley.v:28.17-28.31"
cell $and $and$tests/simple/fiedler-cooley.v:28$5
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \up
connect \B $add$tests/simple/fiedler-cooley.v:17$3_Y [9]
connect \Y $and$tests/simple/fiedler-cooley.v:28$5_Y
end
attribute \src "tests/simple/fiedler-cooley.v:29.17-29.33"
cell $and $and$tests/simple/fiedler-cooley.v:29$6
parameter \A_SIGNED 0
parameter \A_WIDTH 1
parameter \B_SIGNED 0
parameter \B_WIDTH 1
parameter \Y_WIDTH 1
connect \A \down
connect \B $sub$tests/simple/fiedler-cooley.v:16$2_Y [9]
connect \Y $and$tests/simple/fiedler-cooley.v:29$6_Y
end
attribute \src "tests/simple/fiedler-cooley.v:27.17-27.27"
cell $reduce_xor $reduce_xor$tests/simple/fiedler-cooley.v:27$4
parameter \A_SIGNED 0
parameter \A_WIDTH 9
parameter \Y_WIDTH 1
connect \A $1\count_nxt[8:0]
connect \Y $reduce_xor$tests/simple/fiedler-cooley.v:27$4_Y
end
attribute \src "tests/simple/fiedler-cooley.v:16.11-16.30"
cell $sub $sub$tests/simple/fiedler-cooley.v:16$2
parameter \A_SIGNED 0
parameter \A_WIDTH 9
parameter \B_SIGNED 0
parameter \B_WIDTH 3
parameter \Y_WIDTH 10
connect \A \count_out
connect \B 3'101
connect \Y $sub$tests/simple/fiedler-cooley.v:16$2_Y
end
attribute \src "tests/simple/fiedler-cooley.v:14.1-31.4"
process $proc$tests/simple/fiedler-cooley.v:14$1
assign { } { }
assign { } { }
assign { } { }
assign { } { }
assign { } { }
assign { } { }
assign { } { }
assign $0\cnt_dn[9:0] $sub$tests/simple/fiedler-cooley.v:16$2_Y
assign $0\cnt_up[9:0] $add$tests/simple/fiedler-cooley.v:17$3_Y
assign $0\count_nxt[8:0] $1\count_nxt[8:0]
assign $0\parity_out[0:0] $reduce_xor$tests/simple/fiedler-cooley.v:27$4_Y
assign $0\carry_out[0:0] $and$tests/simple/fiedler-cooley.v:28$5_Y
assign $0\borrow_out[0:0] $and$tests/simple/fiedler-cooley.v:29$6_Y
assign $0\count_out[8:0] $1\count_nxt[8:0]
attribute \src "tests/simple/fiedler-cooley.v:19.2-25.9"
switch { \up \down }
attribute \src "tests/simple/fiedler-cooley.v:0.0-0.0"
case 2'00
assign { } { }
assign $1\count_nxt[8:0] \data_in
attribute \src "tests/simple/fiedler-cooley.v:0.0-0.0"
case 2'01
assign { } { }
assign $1\count_nxt[8:0] $sub$tests/simple/fiedler-cooley.v:16$2_Y [8:0]
attribute \src "tests/simple/fiedler-cooley.v:0.0-0.0"
case 2'10
assign { } { }
assign $1\count_nxt[8:0] $add$tests/simple/fiedler-cooley.v:17$3_Y [8:0]
attribute \src "tests/simple/fiedler-cooley.v:0.0-0.0"
case 2'11
assign { } { }
assign $1\count_nxt[8:0] \count_out
attribute \src "tests/simple/fiedler-cooley.v:0.0-0.0"
case
assign { } { }
assign $1\count_nxt[8:0] 9'x
end
sync posedge \clock
update \count_out $0\count_out[8:0]
update \carry_out $0\carry_out[0:0]
update \borrow_out $0\borrow_out[0:0]
update \parity_out $0\parity_out[0:0]
update \cnt_up $0\cnt_up[9:0]
update \cnt_dn $0\cnt_dn[9:0]
update \count_nxt $0\count_nxt[8:0]
end
end
接下来执行指令:
proc; opt
将process转换为网络元素并做一些优化,结果如下:
5. Executing PROC pass (convert processes to netlists).
5.1. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Cleaned up 0 empty switches.
5.2. Executing PROC_RMDEAD pass (remove dead branches from decision trees).
Removed 1 dead cases from process $proc$tests/simple/fiedler-cooley.v:14$1 in module up3down5.
Marked 1 switch rules as full_case in process $proc$tests/simple/fiedler-cooley.v:14$1 in module up3down5.
Removed a total of 1 dead cases.
5.3. Executing PROC_PRUNE pass (remove redundant assignments in processes).
Removed 0 redundant assignments.
Promoted 7 assignments to connections.
5.4. Executing PROC_INIT pass (extract init attributes).
5.5. Executing PROC_ARST pass (detect async resets in processes).
5.6. Executing PROC_ROM pass (convert switches to ROMs).
Converted 0 switches.
<suppressed ~1 debug messages>
5.7. Executing PROC_MUX pass (convert decision trees to multiplexers).
Creating decoders for process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
1/1: $1\count_nxt[8:0]
5.8. Executing PROC_DLATCH pass (convert process syncs to latches).
5.9. Executing PROC_DFF pass (convert process syncs to FFs).
Creating register for signal `\up3down5.\count_out' using process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
created $dff cell `$procdff$12' with positive edge clock.
Creating register for signal `\up3down5.\carry_out' using process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
created $dff cell `$procdff$13' with positive edge clock.
Creating register for signal `\up3down5.\borrow_out' using process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
created $dff cell `$procdff$14' with positive edge clock.
Creating register for signal `\up3down5.\parity_out' using process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
created $dff cell `$procdff$15' with positive edge clock.
Creating register for signal `\up3down5.\cnt_up' using process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
created $dff cell `$procdff$16' with positive edge clock.
Creating register for signal `\up3down5.\cnt_dn' using process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
created $dff cell `$procdff$17' with positive edge clock.
Creating register for signal `\up3down5.\count_nxt' using process `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
created $dff cell `$procdff$18' with positive edge clock.
5.10. Executing PROC_MEMWR pass (convert process memory writes to cells).
5.11. Executing PROC_CLEAN pass (remove empty switches from decision trees).
Found and cleaned up 1 empty switch in `\up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
Removing empty process `up3down5.$proc$tests/simple/fiedler-cooley.v:14$1'.
Cleaned up 1 empty switch.
5.12. Executing OPT_EXPR pass (perform const folding).
Optimizing module up3down5.
<suppressed ~1 debug messages>
6. Executing OPT pass (performing simple optimizations).
6.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module up3down5.
6.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\up3down5'.
<suppressed ~3 debug messages>
Removed a total of 1 cells.
6.3. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \up3down5..
Creating internal representation of mux trees.
Evaluating internal representation of mux trees.
Analyzing evaluation results.
Removed 0 multiplexer ports.
<suppressed ~1 debug messages>
6.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
Optimizing cells in module \up3down5.
Performed a total of 0 changes.
6.5. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\up3down5'.
Removed a total of 0 cells.
6.6. Executing OPT_DFF pass (perform DFF optimizations).
6.7. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \up3down5..
Removed 2 unused cells and 10 unused wires.
<suppressed ~5 debug messages>
6.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module up3down5.
6.9. Rerunning OPT passes. (Maybe there is more to do..)
6.10. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \up3down5..
Creating internal representation of mux trees.
Evaluating internal representation of mux trees.
Analyzing evaluation results.
Removed 0 multiplexer ports.
<suppressed ~1 debug messages>
6.11. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
Optimizing cells in module \up3down5.
Performed a total of 0 changes.
6.12. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\up3down5'.
Removed a total of 0 cells.
6.13. Executing OPT_DFF pass (perform DFF optimizations).
6.14. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \up3down5..
6.15. Executing OPT_EXPR pass (perform const folding).
Optimizing module up3down5.
6.16. Finished OPT passes. (There is nothing left to do.)
接着执行指令
show
可以看到xdot格式的网络图:
执行指令:
techmap; opt
将网络表转换为逻辑门,并做一些优化,执行结果如下:
10. Executing TECHMAP pass (map to technology primitives).
10.1. Executing Verilog-2005 frontend: /home/joezhoushen/yosys/share/techmap.v
Parsing Verilog input from `/home/joezhoushen/yosys/share/techmap.v' to AST representation.
Generating RTLIL representation for module `\_90_simplemap_bool_ops'.
Generating RTLIL representation for module `\_90_simplemap_reduce_ops'.
Generating RTLIL representation for module `\_90_simplemap_logic_ops'.
Generating RTLIL representation for module `\_90_simplemap_compare_ops'.
Generating RTLIL representation for module `\_90_simplemap_various'.
Generating RTLIL representation for module `\_90_simplemap_registers'.
Generating RTLIL representation for module `\_90_shift_ops_shr_shl_sshl_sshr'.
Generating RTLIL representation for module `\_90_shift_shiftx'.
Generating RTLIL representation for module `\_90_fa'.
Generating RTLIL representation for module `\_90_lcu'.
Generating RTLIL representation for module `\_90_alu'.
Generating RTLIL representation for module `\_90_macc'.
Generating RTLIL representation for module `\_90_alumacc'.
Generating RTLIL representation for module `\$__div_mod_u'.
Generating RTLIL representation for module `\$__div_mod_trunc'.
Generating RTLIL representation for module `\_90_div'.
Generating RTLIL representation for module `\_90_mod'.
Generating RTLIL representation for module `\$__div_mod_floor'.
Generating RTLIL representation for module `\_90_divfloor'.
Generating RTLIL representation for module `\_90_modfloor'.
Generating RTLIL representation for module `\_90_pow'.
Generating RTLIL representation for module `\_90_pmux'.
Generating RTLIL representation for module `\_90_demux'.
Generating RTLIL representation for module `\_90_lut'.
Successfully finished Verilog frontend.
10.2. Continuing TECHMAP pass.
Using extmapper simplemap for cells of type $eq.
Using template $paramod$1e99ce38f701dd11f85f107c1bfc7d0aa5d10769\_90_pmux for cells of type $pmux.
Using extmapper simplemap for cells of type $and.
Using extmapper simplemap for cells of type $logic_not.
Using extmapper simplemap for cells of type $dff.
Running "alumacc" on wrapper $extern:wrap:$sub:A_SIGNED=0:A_WIDTH=9:B_SIGNED=0:B_WIDTH=3:Y_WIDTH=10:394426c56d1a028ba8fdd5469b163e04011def47.
Using template $extern:wrap:$sub:A_SIGNED=0:A_WIDTH=9:B_SIGNED=0:B_WIDTH=3:Y_WIDTH=10:394426c56d1a028ba8fdd5469b163e04011def47 for cells of type $extern:wrap:$sub:A_SIGNED=0:A_WIDTH=9:B_SIGNED=0:B_WIDTH=3:Y_WIDTH=10:394426c56d1a028ba8fdd5469b163e04011def47.
Running "alumacc" on wrapper $extern:wrap:$add:A_SIGNED=0:A_WIDTH=9:B_SIGNED=0:B_WIDTH=2:Y_WIDTH=10:394426c56d1a028ba8fdd5469b163e04011def47.
Using template $extern:wrap:$add:A_SIGNED=0:A_WIDTH=9:B_SIGNED=0:B_WIDTH=2:Y_WIDTH=10:394426c56d1a028ba8fdd5469b163e04011def47 for cells of type $extern:wrap:$add:A_SIGNED=0:A_WIDTH=9:B_SIGNED=0:B_WIDTH=2:Y_WIDTH=10:394426c56d1a028ba8fdd5469b163e04011def47.
Using extmapper simplemap for cells of type $reduce_xor.
Using extmapper simplemap for cells of type $reduce_or.
Using extmapper simplemap for cells of type $mux.
Using template $paramod$9ba033cb42591e01e61f078c95ea0ab8e1e30f70\_90_alu for cells of type $alu.
Using template $paramod$de9286bb3f6c9573089ef1694e580944d318189a\_90_alu for cells of type $alu.
Using extmapper simplemap for cells of type $xor.
Using template $paramod\_90_lcu\WIDTH=32'00000000000000000000000000001010 for cells of type $lcu.
Using extmapper simplemap for cells of type $pos.
Using extmapper simplemap for cells of type $not.
Using extmapper simplemap for cells of type $or.
No more expansions possible.
<suppressed ~384 debug messages>
11. Executing OPT pass (performing simple optimizations).
11.1. Executing OPT_EXPR pass (perform const folding).
Optimizing module up3down5.
<suppressed ~113 debug messages>
11.2. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\up3down5'.
<suppressed ~57 debug messages>
Removed a total of 19 cells.
11.3. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \up3down5..
Creating internal representation of mux trees.
No muxes found in this module.
Removed 0 multiplexer ports.
11.4. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
Optimizing cells in module \up3down5.
Performed a total of 0 changes.
11.5. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\up3down5'.
Removed a total of 0 cells.
11.6. Executing OPT_DFF pass (perform DFF optimizations).
11.7. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \up3down5..
Removed 1 unused cells and 145 unused wires.
<suppressed ~2 debug messages>
11.8. Executing OPT_EXPR pass (perform const folding).
Optimizing module up3down5.
11.9. Rerunning OPT passes. (Maybe there is more to do..)
11.10. Executing OPT_MUXTREE pass (detect dead branches in mux trees).
Running muxtree optimizer on module \up3down5..
Creating internal representation of mux trees.
No muxes found in this module.
Removed 0 multiplexer ports.
11.11. Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).
Optimizing cells in module \up3down5.
Performed a total of 0 changes.
11.12. Executing OPT_MERGE pass (detect identical cells).
Finding identical cells in module `\up3down5'.
Removed a total of 0 cells.
11.13. Executing OPT_DFF pass (perform DFF optimizations).
11.14. Executing OPT_CLEAN pass (remove unused cells and wires).
Finding unused cells or wires in module \up3down5..
11.15. Executing OPT_EXPR pass (perform const folding).
Optimizing module up3down5.
11.16. Finished OPT passes. (There is nothing left to do.)
基本操作先介绍到这里,后续会对代码做详细解析。