FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

オープンソースの論理合成ツールYosysを試す

f:id:msyksphinz:20220103010108p:plain

オープンソースEDAツール関係を調査している。今回はオープンソースの論理合成ツールYosysだ。 まずはインストール手順を確認する。

github.com

WSL2のUbuntu-20.04 LTSに環境を構築している。

sudo 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
curl -L https://github.com/YosysHQ/yosys/archive/refs/tags/yosys-0.14.tar.gz | tar xz
cd yosys-yosys-0.14
make

結構時間がかかったが、ビルドが終了した。

[100%] Building share/intel_alm/common/lutram_mlab.txt
[100%] Building share/intel_alm/common/megafunction_bb.v
[100%] Building share/intel_alm/common/quartus_rename.v
[100%] Building share/sf2/arith_map.v
[100%] Building share/sf2/cells_map.v
[100%] Building share/sf2/cells_sim.v

  Build successful.

インストールを行う。

sudo make install
mkdir -p /usr/local/bin
cp yosys yosys-config yosys-abc yosys-filterlib yosys-smtbmc /usr/local/bin
strip -S /usr/local/bin/yosys
strip /usr/local/bin/yosys-abc
strip /usr/local/bin/yosys-filterlib
mkdir -p /usr/local/share/yosys
cp -r share/. /usr/local/share/yosys/.

Yosysを実行してみる

yosysを入力して対話インタフェースを立ち上げる。

 Yosys 0.14 (git sha1 UNKNOWN, clang 10.0.0-4ubuntu1 -fPIC -Os)


yosys>

チュートリアルに従って試していく。

yosys> read -sv tests/simple/fiedler-cooley.v
1. Executing Verilog-2005 frontend: tests/simple/fiedler-cooley.v
Parsing SystemVerilog input from `tests/simple/fiedler-cooley.v' to AST representation.
Storing AST representation for module `$abstract\up3down5'.
Successfully finished Verilog frontend.

こんな感じの回路らしい。なんに使うのかはよく分からない。

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

階層をチェックする。これはElaborationみたいなもんかな?

yosys> hierarchy -top up3down5

2. Executing HIERARCHY pass (managing design hierarchy).

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

3.1. Analyzing design hierarchy..
Top module:  \up3down5

3.2. Analyzing design hierarchy..
Top module:  \up3down5
Removing unused module `$abstract\up3down5'.
Removed 1 unused modules.

次がおそらく合成と最適化かな?

yosys> proc; opt

テクノロマッピング。スタセルへの割り付けかな?

yosys> techmap; opt

最後にデザインの書き出しとなる。

yosys> write_verilog synth.v

出力した回路を眺めてみる。大量のアノテーションはさておき、別にスタセルに置き換わる訳では無いのか(まあ現時点ではライブラリを指定していないので当然)。 デザイン自体も論理合成というか、AND/OR回路みたいに置き換わるのね。

/* ... 中略 ... */
  assign _023_[1] = count_nxt[1] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _023_[2] = count_nxt[2] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _023_[3] = count_nxt[3] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _023_[4] = count_nxt[4] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _023_[5] = count_nxt[5] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _023_[6] = count_nxt[6] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _023_[7] = count_nxt[7] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _023_[8] = count_nxt[8] &(* src = "tests/simple/fiedler-cooley.v:0.0-0.0|tests/simple/fiedler-cooley.v:19.2-25.9|/usr/local/bin/../share/yosys/techmap.v:585.44-585.84" *)  _024_[0];
  assign _022_[20] = count_nxt[2] ^(* src = "tests/simple/fiedler-cooley.v:16.11-16.30|/usr/local/bin/../share/yosys/techmap.v:289.13-289.25" *)  _027_[1];
  assign _022_[21] = _031_[3] ^(* src = "tests/simple/fiedler-cooley.v:16.11-16.30|/usr/local/bin/../share/yosys/techmap.v:289.13-289.25" *)  _027_[2];
  assign _022_[22] = _031_[4] ^(* src = "tests/simple/fiedler-cooley.v:16.11-16.30|/usr/local/bin/../share/yosys/techmap.v:289.13-289.25" *)  _030_[3];
  assign _022_[23] = _031_[5] ^(* src = "tests/simple/fiedler-cooley.v:16.11-16.30|/usr/local/bin/../share/yosys/techmap.v:289.13-289.25" *)  _030_[4];
  assign _022_[24] = _031_[6] ^(* src = "tests/simple/fiedler-cooley.v:16.11-16.30|/usr/local/bin/../share/yosys/techmap.v:289.13-289.25" *)  _030_[5];
  assign _022_[25] = _031_[7] ^(* src = "tests/simple/fiedler-cooley.v:16.11-16.30|/usr/local/bin/../share/yosys/techmap.v:289.13-289.25" *)  _030_[6];
  assign _022_[26] = _031_[8] ^(* src = "tests/simple/fiedler-cooley.v:16.11-16.30|/usr/local/bin/../share/yosys/techmap.v:289.13-289.25" *)  _030_[7];
/* ... 中略 ... */

しれっとalways文もいるので、これは論理合成というか、高レイヤのVerilogを低レイヤのVerilogに書き換えた、という感じに見える。

/* ... 中略 ... */
  always @(posedge clock)
    carry_out <= _001_;
/* ... 中略 ... */