OpenLane & SkyWater PDKで無料の半導体設計環境(RTL→GDS)構築

スポンサーリンク

これまで半導体を設計するには、非常に高価なEDA(Electronic Design Automation)ツールと半導体製造を行う企業が提供するPDK(Process Design Kit)が必要で、一般の人が設計を行うのはまず不可能でした。

しかし、2020年になってGoogle主導のプロジェクトでオープンソースのツール環境OpenLaneとSkyWarter PDKが発表され、130nm世代の半導体設計を無料で行うための道が開かれました。

2021年現在の先端量産プロセスノードは7nmや5nmといった世代であり、こちらの記事によるとIEDM(IEEE International Electron Devices Meeting)2020の公演で紹介されたロードマップでは1nm世代まで表現されており、まだまだ微細化は止まっていません。

EETimes Japan (https://eetimes.itmedia.co.jp/ee/articles/2108/30/news029_2.html) より引用

そのような先端プロセスと比べると130nmは一昔以上前のテクノロジではありますが、これまで全く不可能だったものが可能になったことは大きな進歩です。

半導体設計を仕事にしている私としては、オープンソースになって誰もが半導体を設計できるようになると、少量多品種の新たな市場が生まれるチャンスとも捉えられますが、会社としては脅威になり得ると感じます。

誰もが無料ツールでソフトウェアを作れるのと同じように、今後は個人が半導体チップを設計でき、それが商品となって流通する時代が来るでしょう。

この記事では、SkyWarter PDKを利用して、Verilogのサンプルコードを入力とし、RTL→GDLのデジタル回路のインプリメンテーション環境OpenLaneを実行して、レイアウト結果ファイルとなるGDSを作成し、GUIで表示する方法、各工程の処理内容、自作Verilog回路でフローを流す方法を紹介します。

M1 Macの方はこちら

本記事の内容を動画に収めていますので、よろしければご覧ください。

Windows版の動画は以下です。

Mac版の動画は以下です。

実行環境

Mac (Intel CPU)とWindowsで動作確認済みです。

M1 Macの方はこちら

Ubuntu等のLinuxでも実行できると思います。

項目Mac (Intel CPU)Windows
PCmacOS Catalina 10.15.7,
macOS Big Sur 11.6
Windows10, Ubuntu20.04 on WSL2
DockerDocker Desktop for Mac 3.6.0,
Docker Desktop for Mac 4.1.1
Docker Desktop for Windows 4.0.1
Python3.8.9 3.8.113.8.10
X11XQuartz 2.8.0_beta3 (xorg-server 1.19.7)MobaXterm v20.6

OpenLane環境構築

Dockerをインストールしていない場合は、こちらからインストールします。

Dockerは主にLinuxの仮想環境を構築するためのツールで、OpenLaneはDocker上で動作する環境として提供されています。

なお、MacやWindows、LinuxのネイティブマシンにOpenLaneをインストールする方法もOpenLaneのGitHubリポジトリのREADMEに紹介されていますが、試せていません。


Macでwgetをインストールしていない場合は以下のコマンドでインストールします。

HomeBrewをインストールしていない場合はこちらからインストールします。

brew install wget

Windowsの場合、基本的にWSL2のターミナルを使います。

以下の動画でWSL2のインストール方法を紹介しています。(音声は不要です)


ターミナルを立ち上げ、OpenLaneのGitHubリポジトリのREADMEに従い、以下のコマンドでpyyamlとclickを追加します。

pip3 install --user pyyaml click

任意の作業ディレクトリを作ってcdでそのディレクトリに移動し、gitコマンドでGitHubからOpenLane環境をダウンロードします。

git clone https://github.com/The-OpenROAD-Project/OpenLane.git

gitをインストールしていない場合、Macはgitコマンドの初回実行時にXcodeがインストールされて実行できるようになります。

UbuntuなどのLinuxの場合はsudo apt-get install gitでインストールします。


WindowsのWSL2のターミナルから上記git cloneを実行した場合に以下のエラーが出るので、OpenLane.gitのみはGit BashやPowerShellのターミナルからネイティブのgitを使用してダウンロードしてください。

以降のgit cloneはWSL2のgitを使用して問題なく実行できました。

ここからGit Bashをインストールできます。

Cloning into 'OpenLane'...
remote: Enumerating objects: 11527, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

続いて、OpenLane環境のビルドを行います。

cd OpenLane
make openlane
make pdk
make test

これでOpenLane環境(efabless/openlaneイメージ)のビルドとチェックが実行され、pdksディレクトリ以下にPDKが展開されます。

ここまでの内容は環境構築のためのものなので、一度だけ実行すれば良いです。

次章でefabless/openlaneイメージのコンテナを立ち上げOpenLaneフローを実行する方法を紹介しますが、デフォルト状態ではチップレイアウトを作れてもGUIを立ち上げて結果のレイアウトを確認することができません。

その次の章でGUIを使うための方法を紹介します。

OpenLaneのディレクトリ構造

GitHubでcloneしたOpenLaneディレクトリをDockerコンテナ内で/openLANE_flowとして共有するので、コンテナに入ってcd /openLANE_flowを実行するとネイティブマシンのOpenLaneディレクトリがそのまま見える状態となります。

主なファイル、ディレクトリ構造は以下です。

Makefile                  ... Makefile for building environment and executing flow
clean_runs.tcl            ... For cleaning runs
flow.tcl                  ... Execution file
designs/                  ... Design directory
    spm/                  ... Sample design of adder
        runs/             ... Design work area
            */            ... Tag
                log/      ... Log
                reports/  ... Report
                results/  ... Output
        src/              ... Input RTL and SDC
pdks/                     ... PDK directory
    open_pdks/
    sky130A/
        libs.ref/         ... cdl, gds, lef, spice, techlef, verilog
        libs.tech/        ... Tool Technology file
    skywater-pdk/
        libraries/        ... udp, techlef, liberty
scripts/
    tcl_commands/         ... tcl proc colled from flow.tcl

OpenLane RTL→GDSフロー実行

OpenLane環境には複数のサンプルVerilogコードが含まれていますが、READMEに従いspmというデザインを使って試していきます。

Verilogは半導体回路の機能を表現するための言語です。

spmというデザインはADDER(加算器)のサンプルのようです。

Dockerイメージefabless/openlaneのコンテナを起動します。(OpenLane環境ではMakefileが用意されていてmake 〜で操作できるようになっています。)

make mount

OpenLaneフローを実行します。

./flow.tcl -design spm

これでRTL→GDSのすべての工程が流れます。

https://github.com/efabless/OpenLane より

正常に実行できていれば、designs/spm/runs/〜/results/magic/spm.gds としてGDSファイルが生成できていると思います。

GDSファイルは半導体設計の結果となる図形情報を格納したファイルです。

通常の半導体設計でここまで自動化されていることはまず無いと思いますが、初心者にはありがたい作りですね。

反面、何が実行されているのか意識しづらいですね。

-from, -toでステージ名を指定して部分的に実行することもできます。

ステージ名はflow.tcl内のrun_non_interactive_mode関数内にある”synthesis”, “floorplan”, …を指定すれば良いです。

-from, -toで部分実行する場合、基本的に-tagオプションでタグ名を指定することが必須になります。

-tagオプションを付けない場合、designs/spm/runs以下に日付と時刻から自動的に決まるディレクトリが作られますが、次の工程を実行する際にも新たにディレクトリが作られ、そこで実行されるため、前の工程のデータを読み込めなくなってしまいます。

以下、synthesisのみ実行する例:

 ./flow.tcl -from syhthesis -to synthesis -design spm -tag trial

ただし、実行後に以下のようなエラーが出てしまいます。

[INFO]: Generating Final Summary Report...
[ERROR]: during executing: "openroad -python /openLANE_flow/report_generation_wrapper.py -d /openLANE_flow/designs/spm -dn spm -t trial -o /openLANE_flow/designs/spm/runs/trial/reports/final_summary_report.csv -m /openLANE_flow/designs/spm/runs/trial/reports/manufacturability_report.rpt -rs /openLANE_flow/designs/spm/runs/trial/reports/runtime_summary_report.rpt -r /openLANE_flow/designs/spm/runs/trial"
[ERROR]: Exit code: 1
[ERROR]: Last 10 lines:
Traceback (most recent call last):
  File "<string>", line 1, in <module>
EOFError: EOF when reading a line
grep: /openLANE_flow/designs/spm/runs/trial/logs/routing/fastroute.log: No such file or directory
sed: can't read /openLANE_flow/designs/spm/runs/trial/logs/routing/fastroute.log: No such file or directory

実行結果のサマライズをする処理が、途中で止めた場合を考慮していないようですが、synthesisの処理は正常に実行できていました。

GUIを使う方法

以降で使用するファイルはvi等のエディタで作成するよう中身も貼り付けてありますが、GitHubにも置いていますので、使いたい方は以下のコマンドで取得してください。

git clone https://github.com/tak6uch1/OpenLane_GUI

※git cloneしてできたディレクトリ/ファイルを前章で作成したOpenLaneディレクトリにコピーして使うことを想定しています。

提供されているOpenLaneのDocker環境だけではGUI表示ができないので、DockerでGUIを表示するための常套手段とも言えるSSHのX11 forwardingを使います。

本章の方法でGUIを表示できて以降、私は基本的にGUIを使う方法のみ使用しています。(デフォルト環境のmake mountなどは使わなくなりました。)


X11 forwarding for Mac

Macの場合、以下のコマンドでXquartzをインストールします。

HomeBrewをインストールしていない場合はこちらからインストールします。

brew install --cask xquartz

X11 forwarding for Windows

Windowsの場合は、下記にMobaXtermを使う方法の記載がありますので、参考にしてください。


以降、OpenLaneディレクトリにいる状態で実行することを前提にしています。

guiというディレクトリを作って、gui/Dockerfileというテキストファイルを作ります。(以下viエディタを使う例ですが、他のテキストエディタでも構いません。Windowならメモ帳でもOK。)

参考までにviの基本的な使い方は以下の動画で紹介しています。

mkdir gui
vi gui/Dockerfile

gui/Dockerfileの中身は以下のようにします。

FROM efabless/openlane

ARG USER=user
ARG USER_ID=501
ARG GROUP_ID=20
ARG PASS=password

RUN yum install -y openssh-server vim

RUN useradd --uid $USER_ID --groups $GROUP_ID -m -s /bin/bash $USER
RUN echo "${USER}:${PASS}" | chpasswd

# SSH settings. Otherwise user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
RUN sed -e 's@#Port 22@Port 22@' -e 's@#AddressFamily any@AddressFamily inet@' -i /etc/ssh/sshd_config

RUN ssh-keygen -A

USER $USER
WORKDIR /home/$USER

RUN echo 'export LANG=C' >> /home/$USER/.bash_profile
RUN echo 'alias ls="ls -a --color=auto --show-control-chars --time-style=long-iso -FH"' >> /home/$USER/.bash_profile
RUN echo 'alias ll="ls -a -lA"' >> /home/$USER/.bash_profile
RUN echo 'alias h=history' >> /home/$USER/.bash_profile
RUN echo 'alias vi=vim' >> /home/$USER/.bash_profile
RUN echo 'syntax on' >> /home/$USER/.vimrc

RUN echo 'export PATH=/openLANE_flow:/openLANE_flow/scripts:/build//bin:/build//bin/Linux-x86_64:/build//pdn/scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' >> /home/$USER/.bash_profile
RUN echo 'export OPENLANE_ROOT=/openLANE_flow' >> /home/$USER/.bash_profile
RUN echo 'export PDK_ROOT=/openLANE_flow/pdks' >> /home/$USER/.bash_profile
RUN echo alias 'kl="klayout -l /openLANE_flow/pdks/sky130A/libs.tech/klayout/sky130A.lyp $@"' >> /home/$USER/.bash_profile
RUN echo 'function mdef() { def=$1; tmpdir=`dirname $def`; lef=`echo $tmpdir/*.lef`; magic -T $PDK_ROOT/sky130A/libs.tech/magic/sky130A.tech lef read $lef def read $def; }' >> /home/$USER/.bash_profile

USER root

EXPOSE 22

efabless/openlaneイメージにopenssh-serverを追加してsshdサーバを立ち上げるための内容になります。

vim(viの高機能版)を立ち上げることも多いでしょうから、合わせてインストールし、viにエイリアス(別名をつける、viと入力するとvimが起動)しています。

また、klayoutをレイヤーマップ指定で立ち上げるコマンドは長いので、kl <GDS-file>で実行できるようにするためのエイリアスも定義しています。

さらにmagicでDEF/LEFを開くコマンドも長いため、mdef <DEF-file>で実行できるようにfunction定義しています。

上記はDockerコンテナにパスワードを使ったSSHログインをするための記述例になります。

user, passwordの部分は任意の文字列に変更してください。

続いて、以下をdocker-compose.ymlというファイル名で作成します。

version: "3.4"
services:
  gui:
    build: gui
    container_name: gui
    command: /usr/sbin/sshd -D
    ports:
      - "49944:22"
    volumes:
      - type: bind
        source: .
        target: /openLANE_flow

これを作っておくとDockerの起動が簡単になります。

DockerコンテナのSSHログイン用ポート22番をネイティブマシンの49944番(別のポートでも構いません。下に紹介するrun_sshの中身と同じ番号にしておく必要があります。)に割り当てています。

Dockerコンテナを起動します。

docker compose up -d

古いDockerバージョンではdocker-compose up -dとなります。

これでSSHDサーバが起動し、SSHログイン可能な状態になります。

Mac/Linuxの場合、SSHログインを実行するrun_sshというファイルを作り、実行権を与えます。

vi run_ssh
chmod +x run_ssh

run_sshの中身は以下のようにします。

#!/bin/bash
ssh -Y -p 49944 user@localhost

SSHログインします。

./run_ssh

パスワードを聞かれるので、上記gui/Dockerfileで設定したパスワードを入力してログインします。

Windowsの場合、MobaXtermからlocalhostの49944番ポートにuserとしてSSHログインします。

うまくログインできない場合は、~/.ssh/known_hostsを削除してから実行してみてください。

コンテナにログインできたらflow.tclをデフォルト環境と同様に実行できます。

cd /openLANE_flow
./flow.tcl -design spm

KLayoutでレイアウト結果のGDSを表示します。

kl designs/spm/runs/22-08_13-54/results/magic/spm.gds

klはOpenLaneで用意されたコマンドではなくklayout -l /openLANE_flow/pdks/sky130A/libs.tech/klayout/sky130A.lypの省略形として.bash_profileに定義したエイリアスです。

22-08_13-54の部分は自動的に作られる名称なので、ls等で確認して変更してください。

Tipが表示されたらYesを押します。

下の用に表示されれば成功です。

Klayout Top

右の方にあるLayers部分が番号で表示されている場合は、上記エイリアスで指定したレイヤーマップ情報が正しく読めていないと思われるので、ディレクトリ構造をご確認ください。

Layersの何らかの層名の上で右クリックしてHide Allとしたあと、表示したい層名の上でダブルクリックすると選択的に表示できます。

拡大縮小はマウスホイールで行い、表示箇所の移動はカーソルキーやマウス中央ボタンのドラッグで行います。

スタンダードセルなどの下位階層の表示ON/OFFは、メニューのDisplayからFull HierarchyやTop Level Onlyなどを選択して切り替えることができます。

上記のような操作をすると以下のように詳細レイアウトを確認することができます。

これがVerilogで記述した回路論理に対応したレイアウト結果ということになります。

これが自動的にできあがって、中身を見られるのは楽しいですね。

スタンダードセルを見てみる

PDKに含まれているスタンダードセルはインバータやANDなどゲートレベルの部品であり、これら1つ1つもGDSを持っていて中身を見ることができます。

kl pdks/sky130A/libs.ref/sky130_fd_sc_hd/gds/sky130_fd_sc_hd.gds

以下は試しに最も単純なインバータセルのGDSを表示したものになります。

論理合成と呼ばれる工程でVerilogで書いた論理をこれらスタンダードセルを組み合わせた接続情報に変換し、レイアウト工程でこれら部品を配置して配線をつないで最終的なGDSができあがるという仕組みになっています。

初回以降の起動方法

2回目以降の起動方法はDockerを起動してから、以下のコマンドを実行すれば良いです。

docker compose up -d
./run_ssh
cd /openLANE_flow

古いDockerバージョンではdocker-compose up -dとなります。

Windowsの場合は、run_sshの代わりにMobaXtermでのSSHログインです。

GUIを使わない場合は以下でも構いません。

make mount

上記いずれかの方法で起動後は./flow.tcl ...でフローを実行できます。

各工程の確認

OpenLaneの各工程はflow.tclのrun_non_interactive_mode関数内、下記(抜粋)で定義される辞書変数stepsのキー(floorplan, placementなど)に従って順に実行されます。

    set steps [dict create "synthesis" {run_synthesis "" } \
                "floorplan" {run_floorplan ""} \
                "placement" {run_placement_step ""} \
                "cts" {run_cts_step ""} \
                "routing" {run_routing_step ""}\
                "diode_insertion" {run_diode_insertion_2_5_step ""} \
                "power_pins_insertion" {run_power_pins_insertion_step ""} \
                "gds_magic" {run_magic ""} \
                "gds_drc_klayout" {run_klayout ""} \
                "gds_xor_klayout" {run_klayout_gds_xor ""} \
                "lvs" "run_lvs_step $LVS_ENABLED" \
                "drc" "run_drc_step $DRC_ENABLED" \
                "antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED" \
                "cvc" {run_lef_cvc}
        ]

ここで、RTL→GDSフローの各工程の中身を見ていきます。

入力となるRTL(Resister Transfer LevelのVerilog記述で書かれた論理回路)はdesigns/spm/src/spm.vで、以下は抜粋です。

module CSADD(clk, rst, x, y, sum);
    input clk, rst;
    input x, y;
    output reg sum;

    reg sc;

    // Half Adders logic
    wire hsum1, hco1;
    assign hsum1 = y ^ sc;
    assign hco1 = y & sc;

    wire hsum2, hco2;
    assign hsum2 = x ^ hsum1;
    assign hco2 = x & hsum1;

    always @(posedge clk or posedge rst) begin
        if (rst) begin
            //Reset logic goes here.
            sum <= 1'b0;
            sc <= 1'b0;
        end
        else begin
            //Sequential logic goes here.
            sum <= hsum2;
            sc <= hco1 ^ hco2;
        end
    end
endmodule

Verilogの書式をここで詳しく説明しませんが、always begin〜endでクロックやリセットが入ったときの順序動作、assign文で常時接続の論理を表現していて、人間が機能を把握できるレベルのハードウェアのソースコードと言えます。

synthesis:論理合成

論理合成の工程のみを実行するには、-from, -toで論理合成を表すsynthesisを指定してflow.tclを実行します。

工程毎に部分実行する場合は、-tagで任意の文字列(ここではtrialとした)を指定するのは基本的に必須になると考えます。

日付・時刻から自動で決まる名称のディレクトリがdesigns/spm/runs以下に作られると前の工程とのつながりが無くなり、実行に失敗してしまうためです。

 ./flow.tcl -from syhthesis -to synthesis -design spm -tag trial

実行ログはdesigns/spm/runs/trial/logs/synthesis/1-yosys.logです。

yosysというツールで論理の合成を行い、yosysから呼び出されるABCというツールで各種セルにマッピングされるようです。

論理合成の結果はdesigns/spm/runs/trial/results/synthesis/spm.synthesis.vになります。(以下、抜粋)

  wire \genblk1[8].csa.hsum2 ;
  wire \genblk1[8].csa.sc ;
  wire \genblk1[8].csa.y ;
  wire \genblk1[9].csa.hsum2 ;
  wire \genblk1[9].csa.sc ;
  output p;
  input rst;
  wire \tcmp.z ;
  input [31:0] x;
  input y;
  sky130_fd_sc_hd__inv_2 _182_ (
    .A(rst),
    .Y(_097_)
  );
  sky130_fd_sc_hd__buf_1 _183_ (
    .A(_097_),
    .X(_098_)
  );
  sky130_fd_sc_hd__buf_1 _184_ (
    .A(_098_),
    .X(_095_)
  );

スタンダードセルの接続記述(上記は全体のうちのほんの一部を掲載)になっており、人間が見て機能を理解するのは困難です。

論理合成の後に静的タイミング解析(STA)が実行されていて、STAレポートはdesigns/spm/runs/trial/reports/placement/7-replace.min_max.rptです。(以下、抜粋)

Startpoint: y (input port clocked by clk)
Endpoint: _404_ (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max

Fanout     Cap    Slew   Delay    Time   Description
-----------------------------------------------------------------------------
                  0.00    0.00    0.00   clock clk (rise edge)
                          0.00    0.00   clock network delay (ideal)
                          2.00    2.00 v input external delay
                  0.02    0.01    2.01 v y (in)
     5    0.01                           y (net)
                  0.02    0.00    2.01 v _276_/A (sky130_fd_sc_hd__buf_1)
                  0.11    0.18    2.19 v _276_/X (sky130_fd_sc_hd__buf_1)
     5    0.01                           _120_ (net)
                  0.11    0.00    2.19 v _277_/A (sky130_fd_sc_hd__buf_1)
                  0.09    0.21    2.40 v _277_/X (sky130_fd_sc_hd__buf_1)
     5    0.01                           _121_ (net)
                  0.09    0.00    2.40 v _278_/A (sky130_fd_sc_hd__and2_2)
                  0.09    0.38    2.78 v _278_/X (sky130_fd_sc_hd__and2_2)
     3    0.01                           _122_ (net)
                  0.09    0.00    2.78 v _281_/B1 (sky130_fd_sc_hd__o2bb2a_2)
                  0.08    0.51    3.30 v _281_/X (sky130_fd_sc_hd__o2bb2a_2)
     1    0.00                           genblk1[3].csa.hsum2 (net)
                  0.08    0.00    3.30 v _404_/D (sky130_fd_sc_hd__dfrtp_2)
                                  3.30   data arrival time

                  0.00   10.00   10.00   clock clk (rise edge)
                          0.00   10.00   clock network delay (ideal)
                          0.00   10.00   clock reconvergence pessimism
                                 10.00 ^ _404_/CLK (sky130_fd_sc_hd__dfrtp_2)
                         -0.30    9.70   library setup time
                                  9.70   data required time
-----------------------------------------------------------------------------
                                  9.70   data required time
                                 -3.30   data arrival time
-----------------------------------------------------------------------------
                                  6.41   slack (MET)

基本的にフリップフロップ(以降F/F)間や入力、出力端子とFF間の遅延が、1サイクル以内に収まるか(Setup)、早すぎて後段のF/Fがデータを取り込む前に取り込むべきデータを上書きしてしまわないか(Hold)をチェックしていて、slack (MET)となっていればOKということになります。

フローにはDFT(Design For Test)の工程があるように書かれていましたが、デフォルト設定の状態でspmサンプルを使ってフローを流した限りは、テスト用の回路挿入はされていないように思います。

何らかのオプションでDFTのON/OFFを制御するのか、現時点では不明です。

静的タイミング解析(STA)は論理合成後だけでなく、配置、CTS、配線後など各工程毎に実施されます。

論理合成や配置の段階のSTAでは0遅延の理想クロックで(上記レポートでclock network delay (ideal)となっている)、CTS後はクロックラインがスタセルの接続として具体化されるので、実遅延でSTAするのが普通ですが、デフォルト設定ではCTS以降のSTAレポートも理想クロックになっていました。理由は不明です。

floorplan:フロアプラン

フロアプランの工程のみを実行するには以下のコマンドを実行します。

 ./flow.tcl -from floorplan -to floorplan -design spm -tag trial

この工程では敷地となるDIE、配線トラックやセルを置くためのROWを作り、Decapセル、Tapセルを配置し、電源配線を行います。

結果ファイルはdesigns/spm/runs/trial/results/floorplan/spm.floorplan.defで同じディレクトリにmerged_unpadded.lefというファイルがあり、テクノロジLEFおよびDEFで使うセルが定義されたLEFになります。

KLayoutを起動してフロアプランの結果を見てみます。

klayout
Initial KLayout

File→Import→DEF/LEFを順にクリックします。

Import DEF/LEF

下図のようにImport Fileの「…」ボタンからDEFファイルdesigns/spm/runs/trial/results/floorplan/spm.floorplan.defを指定します。

DEFファイルを指定すると同じディレクトリにあるmerged_unpadded.lefもWith LEF files:の欄に表示されると思います。(表示されない場合は手動で指定します)

Optionsボタンをクリックします。

File selection for immportin DEF/LEF.g

初回KLayout実行時は以下のようにTechnology Setupの中身が空になると思います。

初回KLayout起動時はこのままOK→さらにOKを押してDEFを開きます。

しかし、下図のようにセルが表示されない状態になると思いますので、File→Exitで一旦KLayoutを閉じます。

再度KLayoutを立ち上げ、File→Import→DEF/LEF→Optionsと進むと下図のようにTechnology Setupが表示されると思います。

Dockerコンテナにログインして最初にDEF/LEFを表示する際は、上記2回読み込みが必要です。

恐らくKLayoutの終了時に何らかの設定が~/.klayoutに保存されることで2回目以降はうまくいくのだと思います。

「LEF+Macro Files」タブを開き、LEF macro geometryの欄にプルダウンから「Always produce LEF geometry and ignore LEF FOREIGN」を選択してOKを押します。

これにしておかないとセルが表示されない状態になりました。

Technology Setup

これで以下のようにフロアプラン結果が表示されます。

Floorplan Result

左側にあるCellsのパネルのLevelsの右側の数値を1にするとセルは下図のように外形のみ表示されます。

フロアプラン結果として、周囲の端子、Decap、Tapセルが置かれていることがわかります。

Level 1

Levelsの右側の数値を2にすると、下図のようにセルの中身(LEF情報)が表示されます。

Display LEF pins

DEF/LEFを表示するもう一つの方法としてレイアウトツールmagicを使用する方法があり、「magicでDEF/LEFを開く」の章に記載しました。

placement:配置

論理合成によってスタンダードセルの接続として表現されたそれぞれのセルを配置する工程です。

配置の工程のみを実行するには以下のコマンドを実行します。

 ./flow.tcl -from placement -to placement -design spm -tag trial

配置の結果はDEFファイルdesigns/spm/runs/trial/results/placement/spm.placement.defに保存されるため、floorplanのときと同様にKLayoutで確認します。

Placement

上図のとおり、セルが配置されていることがわかります。

CTS:クロックツリー生成

同期回路はF/Fがクロックに同期してデータを後段に渡す構造になっています。

多数のF/Fのクロック端子を1つのバッファで駆動するとクロック信号の波形がなまってしまい、大きな遅延が付いたり、動作が不安定になってしまいます。

そのため、ある程度近傍にあるF/Fをまとめて駆動するバッファを各所に配置し、さらにそれらバッファを駆動するバッファを置く、というようにトーナメントのような構造でチップのクロック端子から全F/Fのクロック端子までクロック信号を分配する構造にするのがCTSです。

CTS(Clock Tree Synthesis)の工程のみを実行するコマンドは以下です。

./flow.tcl -from cts -to cts -design spm -tag trial

CTSの結果はDEFファイルdesigns/spm/runs/trial/results/cts/spm.cts.defです。

CTS

セルをクリックしてQを押すと上図のようにセルの情報を表示できます。

routing:配線

論理合成やCTSで作られた回路の接続情報をメタル層、VIA層による結線に落とし込む工程です。

実行結果はDEFファイルdesigns/spm/runs/trial/results/routing/17-spm.defに出力されます。

KLayoutで表示すると下図のようにメタル層、VIA層による信号配線が引かれているのがわかります。

Routing

diode_insertion:ダイオード挿入

製造上問題となるアンテナ違反(アンテナ検証の節も参照のこと)を解消するためのダイオード挿入の工程と思われますが、1つも挿入する必要が無かったためなのか、spmのデザインでは何も起きませんでした。

./flow.tcl -from diode_insertion -to diode_insertion -design spm -tag trial

ダイオード挿入されるとrouting結果のDEFが更新されるようです。

power_pins_insertion:電源端子追加

Verilog回路に電源端子を挿入する工程です。

./flow.tcl -from power_pins_insertion -to power_pins_insertion -design spm -tag trial

結果ファイルはdesigns/spm/runs/trial/results/lvs/spm.lvs.powered.vです。

gds_magic:GDS出力

magicでGDSを出力する工程で、このGDSがRTL→GDSフローの最終成果物になります。

./flow.tcl -from gds_magic -to gds_magic -design spm -tag trial

出力結果はdesigns/spm/runs/trial/results/magic/spm.gdsです。

以下のコマンドで表示できます。

kl designs/spm/runs/trial/results/magic/spm.gds
GDS image

gds_drc_klayout:DRC用GDS出力

DRC用GDS出力の工程です。

./flow.tcl -from gds_drc_klayout -to gds_drc_klayout -design spm -tag trial

出力結果は/openLANE_flow/designs/spm/runs/trial/results/klayout/spm.gdsで、以下のように表示されました。

KLayout output GDS

DIEとスタセルのUnitが合っていないように思われる(DIEが小さく扱われている?)変なGDSになっています。

現在のところ、原因は未確認です。

gds_xor_klayout:GDS差分確認

magicから出力したGDSとKLayoutから出力したGDSの差分(XOR)を確認する工程です。

./flow.tcl -from gds_xor_klayout -to gds_xor_klayout -design spm -tag trial

差分結果のGDSはdesigns/spm/runs/trial/results/klayout/spm.xor.gdsです。

GDS XOR Result

最終GDSとDRC用GDSのXORを取って、差分がなければ結果図形は空になるはずですが、前の工程gds_drc_klayoutのKLayout出力のGDSが変な状態なので、差分も大量に出ています。(^^;

lvs:LVS検証

LVS(Layout Versus Schematic)検証(レイアウトと回路の一致性を確認)の工程です。

./flow.tcl -from lvs -to lvs -design spm -tag trial

ログはdesigns/spm/runs/trial/results/lvs/spm.lvs.lef.logで、下記のようにequivalentと表示されていれば問題ありません。

Cell pin lists are equivalent.
Device classes spm and spm are equivalent.
Circuits match uniquely.

drc:DRC検証

DRC(Design Rule Check)検証(レイアウト図形の問題をチェック)の工程です。

./flow.tcl -from drc -to drc -design spm -tag trial

magicでDRCを実施したログはdesigns/spm/runs/trial/logs/magic/30-magic.drc.logです。

以下のようにNo errors found.となっていれば問題ありません。

No errors found.
[INFO]: COUNT: 0
[INFO]: Should be divided by 3 or 4
[INFO]: DRC Checking DONE (/openLANE_flow/designs/spm/runs/trial/reports/magic/30-magic.drc)
[INFO]: Saving mag view with DRC errors(/openLANE_flow/designs/spm/runs/trial/results/magic/spm.drc.mag)
[INFO]: Saved

KLayoutでGDSのDRCを実施したログはdesigns/spm/runs/trial/reports/magic/30-magic.drc.klayout.xmlでエラーが無ければ問題ありません。

antenna_check:アンテナ検証

ここでのアンテナとは無線の送受信を行うアンテナではなく、半導体の製造工程で配線に溜まった電荷によって素子を破壊してしまう現象を指しており、そのアンテナ破壊の危険性のある配線構造を検出する工程です。

./flow.tcl -from antenna_check -to antenna_check -design spm -tag trial

実行ログはdesigns/spm/runs/trial/reports/routing/32-antenna.rptで、下記のように違反数が0であれば問題無しです。

Number of pins violated: 0
Number of nets violated: 0
Total number of unspecial nets: 356

CVC

CVC(Circuit Validity Check) 回路妥当性検証の工程です。

./flow.tcl -from cvc -to cvc -design spm -tag trial

実行結果はdesigns/spm/runs/trial/results/cvc/cvc_spm.logで、以下のようにエラー数が0であれば問題ありません。

CVC: Error Counts
CVC: Fuse Problems:         0
CVC: Min Voltage Conflicts: 0
CVC: Max Voltage Conflicts: 0
CVC: Leaks:                 0
CVC: LDD drain->source:     0
CVC: HI-Z Inputs:           0
CVC: Forward Bias Diodes:   0
CVC: NMOS Source vs Bulk:   0
CVC: NMOS Gate vs Source:   0
CVC: NMOS Possible Leaks:   0
CVC: PMOS Source vs Bulk:   0
CVC: PMOS Gate vs Source:   0
CVC: PMOS Possible Leaks:   0
CVC: Overvoltage-VBG:       0
CVC: Overvoltage-VBS:       0
CVC: Overvoltage-VDS:       0
CVC: Overvoltage-VGS:       0
CVC: Unexpected voltage :   0
CVC: Total:                 0

以上、一部不明な点はありますが、一連のフローをざっと確認できました。

magicでDEF/LEFを開く

これまでKLayoutでDEF/LEFを開いていましたが、magicというツールを使うこともできます。

以下のコマンドでmagicを使ってDEF/LEFを開くことができます。

magic -T $PDK_ROOT/sky130A/libs.tech/magic/sky130A.tech lef read <LEF-file> def read <DEF-file>

上のコマンドはかなり長いので、gui/Dockerfileで.bash_profileにmdefという便利関数を用意しました。

DEFだけ指定して、同じディレクトリにあるLEFを読み込み、上記コマンドに変換できるようにしてあるので、それを利用してDEF/LEFを開くと便利です。

以下の例のように実行することでDEF/LEFを開くことができます。

mdef designs/spm/runs/trial/results/routing/17-spm.def
Open DEF/LEF with magic

Zでズームイン、Shift+Zでズームアウト、左クリックと右クリックで範囲を指定してCtrl+Zで範囲指定のズーム、Vで全体を描画できます。

レイヤー表示ON/OFFは以下のようにsee no 〜で表示OFF(*はすべて)、see 〜で表示ONになります。

see no *
see m1
see m2
see vial
see via2

レイヤ名はpdks/open_pdks/sky130/magic/sky130.techを見るとわかります。

※via1はvial(ヴィアエル)となるようです。

私の場合だけかもしれませんが、初めてmagicを立ち上げた際にレイアウトウィンドウが画面の外にはみ出てしまって操作できない状態になりました。

はみ出ているウィンドウをクリックするとメニューバーがXquartzになるので、メニューからウィンドウ→拡大/縮小を選択すると枠内に表示されました。

独自回路の作成

独自にVerilog回路を書いてフローを流す方法を紹介します。

以下のコマンドで新たなデザインnew_design(任意の名称でOK)の作業環境を作ります。

./flow.tcl -design new_design -init_design_config

上記を実行すると下の内容のdesigns/new_design/config.tclができます。

config
set ::env(DESIGN_NAME) new_design

# Change if needed
set ::env(VERILOG_FILES) [glob $::env(DESIGN_DIR)/src/*.v]

# Fill this
set ::env(CLOCK_PERIOD) "10.0"
set ::env(CLOCK_PORT) "clk"

set filename $::env(DESIGN_DIR)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
if { [file exists $filename] == 1} {
        source $filename
}

クロック端子やクロック周波数をお好みで変えられますが、ここではそのまま進めます。

designs/new_design/srcの下は空になっているので、以下のnew_design.vを作成し保存します。

module new_design (clk, rst, a, q);
    input clk, rst;
    input a;
    output reg q;

    always @(posedge clk or posedge rst) begin
        if (rst) begin
            //Reset logic goes here.
            q <= 1'b0;
        end
        else begin
            //Sequential logic goes here.
            q <= !a;
        end
    end
endmodule

上記は非常にシンプルなVerilog HDLコードで、クロックに同期してqにaの反転を出力するインバータ回路になります。

同じくdesigns/new_design/srcの下にnew_design.sdcを作成し保存します。

set_units -time ns
create_clock [get_ports clk]  -name core_clock  -period 10

上記はクロック端子clkに10ns周期のクロックを入力するという定義になります。

非常に簡単な回路ではありますが、これでOpenLaneフローを流してみます。

./flow.tcl -design new_design

すると、配置の工程で下記のエラーとなり止まってしまいました。

[ERROR GPL-0120] instance _4_ width is larger than core.
Error: or_replace.tcl, 91 GPL-0120
[ERROR]: during executing: "openroad -exit /openLANE_flow/scripts/openroad/or_replace.tcl |& tee >&@stdout /openLANE_flow/designs/new_design/runs/20-09_11-31/logs/placement/7-replace.log"
[ERROR]: Exit code: 1
[ERROR]: Last 10 lines:
child process exited abnormally

[ERROR]: Please check openroad  log file
[ERROR]: Dumping to /openLANE_flow/designs/new_design/runs/20-09_11-31/error.log

敷地となるDIEサイズは回路規模と設定した占有率から自動的に決められ、そのサイズが小さすぎてセルが入らなかったようです。

small die

configuration/floorplan.tclに占有率を設定する箇所があったので、以下のように10(%)に変更しました。

#set ::env(FP_CORE_UTIL) 50
set ::env(FP_CORE_UTIL) 10

占有率はUtilizationと呼ばれる数値で、セル配置可能領域に対してセルを何%程度まで埋めるかを表すものです。

通常10%のような小さな値にすることはない(無駄に敷地が大きくなるため)のですが、今回の独自回路の規模が小さすぎてあまりにDIEが小さくなってしまったために、その対策としてこのようにしています。

これでうまく流れました。

Inverter Circuit Result

トラブルシューティング

WindowsのWSL2でOpenLaneのgit cloneに失敗する

WSL2のgitコマンドをつかってOpenLaneのgit cloneを実行すると下記のエラーが出ます。

$ git clone https://github.com/The-OpenROAD-Project/OpenLane.git
Cloning into 'OpenLane'...
remote: Enumerating objects: 11527, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

対策としてはGit BashやPowerShellのターミナルからネイティブのgitコマンドを使ってgit cloneしてください。

GUIが表示できない

OpenLaneのGitHubリポジトリのみではDockerを使ったフロー実行はできてもGUI表示ができません。

「GUIを使う方法」の章を参照してSSH接続のX11 Forwardingを行うことでKLayoutなどのGUIを利用することができます。

KLayoutのImport DEF/LEFでセルが表示されない

Import DEF/LEF時にOptionボタンを押し、「LEF+Macro FIles」タブから「Always produce LEF geometry and ignore LEF FOREIGN」の設定にするとセルが表示されます。

もし、下図のようにTechnology Setupの中身が空になっている場合、DEF/LEF読み込みした後、KLayoutを閉じ、再度KLayoutを起動してFile→Import→DEF/LEF→Optionsと進むと上図のように中身が表示されます。

Empty Technology Setup

flow.tclが正常に流れない

環境変数OPENLANE_ROOT、PDK_ROOTが設定されていない場合もうまくいかない可能性があります。

本記事のgui/Dockerfileを使用していれば.bash_profile内で設定していますが、そうでない方は設定をご確認ください。

下記の環境変数設定のコマンドを実行してからKLayoutを立ち上げるか、~/.bash_profileに追記するなどしてください。

export OPENLANE_ROOT=/openLANE_flow
export PDK_ROOT=/openLANE_flow/pdks

magicのレイアウトウィンドウが画面の外に出てしまって操作できない

はみ出ているウィンドウをクリックするとメニューバーがXquartzになるので、メニューからウィンドウ→拡大/縮小を選択すると枠内に表示されました。

magic out of window

書籍紹介

入門Verilog HDL記述―ハードウェア記述言語の速習&実践 (Design wave basic)

記述例を見ながら実践的なVerilog回路の書き方を学ぶことができ、初心者にやさしく、半導体関連企業における新人研修で使われることもあるようです。


わかるVerilog HDL入門―文法の基礎から論理回路設計、論理合成、実装まで (トランジスタ技術SPECIAL)

トラ技派生のVerilog入門書でFPGAを使った実践的な内容も紹介されており、基礎から応用まで丁寧に説明されていて、特にFPGAで自作回路を作りたい方には最適な書籍だと思います。

まとめ

OpenLaneで用意されたサンプルVerilogコードを使ってRTL→GDSフローを流し、レイアウト結果をKLayoutやmagicのGUIで表示して確認する方法を紹介しました。

そして、各工程でどのような処理がなされているか、簡単ではあるものの確認を行いました。

さらに新たにVerilog RTLを書いてRTL→GDSフローを流し、GDSを生成するまでの方法を紹介しました。

これが家でできる時代が来たことに時代の変化を感じます。

現時点で試したのは、ここまでですが、Verilogシミュレーションやアナログ回路の設計についても気になりますよね。

ネットで検索するとある程度はこういった内容もあるようなので、今後試していきたいと思います。

2020年から2021年にかけてCaravelという無料のシャトルプロジェクトがあったようで、製造や輸送まで無料で実施できたようです。

今後もこういったシャトルプロジェクトが実施されるのかわかりませんが、目が離せませんね。

参考文献

SkyWater SKY130 PDK(https://skywater-pdk.readthedocs.io/en/latest/

KLayout(https://www.klayout.de/build.html

Carvel Harness(https://github.com/efabless/caravel

Efabless Caravel harness SoC(https://caravel-harness.readthedocs.io/en/latest/

OpenLANE Workshop(https://gitlab.com/gab13c/openlane-workshop#about-the-project

タイトルとURLをコピーしました