Yosysを使ってみる(その1)

Yosysというオープンソースの論理合成ツール(レジスタ転送レベルからゲートレベルに変換する一種のコンパイラ)があるので使ってみました。

github.com

インストール

公式のREADMEとだいたい同じです。Makefileを書き換えてインストール場所を変更すれば、インストールに特権は必要ありません。

sudo apt update
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
mkdir git
cd git
git clone https://github.com/YosysHQ/yosys
cd yosys/
vi Makefile
make -j
make install

ここで、Makefileは、PREFIX ?= /home/lpha/yosysのように書き換えました。 make -jは、12th Gen Intel(R) Core(TM) i9-12900Kで2分くらいかかりました。 99%になったくらいが折り返し地点です。

使ってみる

チュートリアル

Yosys Open SYnthesis Suite :: Screenshots を見ながら試してみます。 まず、counter.vcmos_cells.libをダウンロードして実験用ディレクトリに置いておきます。 その後、以下のように入力します(各行について、先頭から空白文字まではプロンプトなので入力しません)。

$ ~/yosys/bin/yosys
yosys> read_verilog counter.v
yosys> hierarchy -check
yosys> proc; opt; fsm; opt; memory; opt
yosys> techmap; opt
yosys> dfflibmap -liberty cmos_cells.lib
yosys> abc -liberty cmos_cells_plus.lib

4bitの符号なし整数に1を足す回路は以下のように合成できるようです。

ABC RESULTS:              NAND cells:        7
ABC RESULTS:               NOT cells:        4
ABC RESULTS:               NOR cells:        9

ライブラリを書き換えてみる

cmos_cells.libをコピーしたcmos_cells_2.libに、以下の記述を書き加えてみます。

  cell(XOR) {
    area: 4;
    pin(A) { direction: input; }
    pin(B) { direction: input; }
    pin(Y) { direction: output;
             function: "(A*B+A'*B')"; }
  }

さきほどと同じ手順を踏むと、以下の結果を得ます。

ABC RESULTS:               NOT cells:        3
ABC RESULTS:              NAND cells:        3
ABC RESULTS:               XOR cells:        3
ABC RESULTS:               NOR cells:        6

NANDが4つ、NORが3つ、NOTが1つ、それぞれ減った代わりにXORが3つ増えたようです。 得したのかよくわかりません。

XORのコストを上げたら使われなくなるのかな、と思ってarea: 40;などとしてみたら、以下のようになりました。

ABC RESULTS:               NOT cells:        4
ABC RESULTS:              NAND cells:        6
ABC RESULTS:               XOR cells:        1
ABC RESULTS:               NOR cells:        7

XORの使用がひかえめになりました。 でも、XORはNAND四つで作れるので、NANDの10倍のコストに設定したのに使われるのは変です。 面積を最小化しているわけではないのでしょうか。

ゲートカウント

yosys gate countとかでググると、以下のページが出てきます。

github.com

以下のように入力すれば、CMOSゲートに合成してくれるようです。

$ ~/yosys/bin/yosys
yosys> read_verilog counter.v
yosys> hierarchy -check
yosys> proc; opt; fsm; opt; memory; opt
yosys> techmap; opt
yosys> abc -g cmos

出力は以下のようになりました。

ABC RESULTS:               NOT cells:        2
ABC RESULTS:              NAND cells:        1
ABC RESULTS:              AOI3 cells:        1
ABC RESULTS:               NOR cells:        2
ABC RESULTS:               XOR cells:        2

AOI3のような、CMOSらしさあふれるものが使われていることがわかります(AOI3は複合ゲートの一種で、~((a&b)|c)が6トランジスタで作れるというやつです)。

トランジスタカウント

yosys transistor countとかでググると、以下のページが出てきます。

stackoverflow.com

以下のように入力すれば、トランジスタ数を算出してくれるようです。

$ ~/yosys/bin/yosys
yosys> read_verilog counter.v
yosys> hierarchy -check
yosys> proc; opt; fsm; opt; memory; opt
yosys> techmap; opt
yosys> abc -g cmos
yosys> stat -tech cmos

すると、以下の出力を得ます。

12. Printing statistics.

=== counter ===

   Number of wires:                 19
   Number of wire bits:             31
   Number of public wires:           4
   Number of public wire bits:       7
   Number of memories:               0
   Number of memory bits:            0
   Number of processes:              0
   Number of cells:                 12
     $_AOI3_                         1
     $_NAND_                         1
     $_NOR_                          2
     $_NOT_                          2
     $_SDFFE_PP0P_                   4
     $_XOR_                          2

   Estimated number of transistors:         46+

+がついてしまっているのは、フリップフロップトランジスタ数がわからないことによるもののようです(stat.ccの215~218行目261行目)。 トランジスタ数は、cost.hの53行目~68行目に定義されているものが使われていそうです。 XORゲートは10トランジスタで作れるはず(XORゲート - Wikipedia)ですが、それ以外はあっていそうです。

なお、ソースコードのどこで定義されているかは、GitHub上でcmosと検索することで発見しました。

面積

dffmap libraryとかでググると、以下のページが出てきます。

tom01h.exblog.jp

どうやらOklahoma State Universityが180nm用のスタンダードセルライブラリを公開しているようです。 osu018_stdcells.lib(243KB)をダウンロードして、実験用ディレクトリに入れます。 これを、cmos_cells.libの代わりに使います。

$ ~/yosys/bin/yosys
yosys> read_verilog counter.v
yosys> hierarchy -check
yosys> proc; opt; fsm; opt; memory; opt
yosys> techmap; opt
yosys> dfflibmap -liberty osu018_stdcells.lib
yosys> abc -liberty osu018_stdcells.lib
yosys> stat -liberty osu018_stdcells.lib

出力は以下のようになりました。

12. Printing statistics.

=== counter ===

   Number of wires:                 34
   Number of wire bits:             46
   Number of public wires:           4
   Number of public wire bits:       7
   Number of memories:               0
   Number of memory bits:            0
   Number of processes:              0
   Number of cells:                 17
     AND2X1                          1
     AOI21X1                         3
     DFFPOSX1                        4
     INVX1                           2
     NAND3X1                         1
     NOR2X1                          3
     OAI21X1                         2
     XNOR2X1                         1

   Chip area for module '\counter': 754.000000

スタンダードセルの面積の確認

トランジスタを並べて回路を実現するとき、トランジスタを自由に配置できるとすると検証が大変です。 そこで、よくありそうな回路について検証されたトランジスタ配置を作っておき、それを並べて回路を実現することを考えます。 そのような検証されたトランジスタ配置がスタンダードセルです。 スタンダードセルは並べて使うことが前提なので、回路の外枠が長方形になっていて、かつ高さが固定値です。 高さが固定なので、トランジスタ数の多い回路は幅が広くなります。

osu018のスタンダードセルライブラリは、pMOSトランジスタとnMOSトランジスタのペア当たり、高さ8、幅1、となっていると思われます。

  • NOTゲート:2トランジスタ必要で1列、隣とのスペースに1列、で2列なので面積は16
  • NANDゲートやNORゲート:4トランジスタ必要で2列、隣とのスペースに1列、で3列なので面積は24
  • ANDゲートやORゲート:6トランジスタ必要で3列、隣とのスペースに1列、で4列なので面積は32
  • XORゲート:12トランジスタ必要で6列、隣とのスペースに1列、で7列なので面積は56(やっぱり12トランジスタで作るのが主流なのでしょうか)
  • 半加算器:XORとANDなので18トランジスタ必要で9列、隣とのスペースに1列、で10列なので面積は80
  • 全加算器:負論理で24トランジスタ必要※で12列、反転に4トランジスタ必要で2列、隣とのスペースに1列で15列なので面積は120

※参考文献:https://www.hindawi.com/journals/vlsi/2012/173079/XORゲート - Wikipediaの参考文献として載っていました)

三入力NANDゲートは同様の推論で行くと32になりそうなところ36になっていて謎ですが、他は大体あっていそうです。

次に読む

さきほどのOklahoma State Universityのスタンダードセルライブラリを紹介していたブログの他の記事で、遅延の評価をやっているので、今度はこれをやってみたいと思います。

tom01h.exblog.jp