これまで半導体を設計するには、非常に高価な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世代まで表現されており、まだまだ微細化は止まっていません。
そのような先端プロセスと比べると130nmは一昔以上前のテクノロジではありますが、これまで全く不可能だったものが可能になったことは大きな進歩です。
半導体設計を仕事にしている私としては、オープンソースになって誰もが半導体を設計できるようになると、少量多品種の新たな市場が生まれるチャンスとも捉えられますが、会社としては脅威になり得ると感じます。
誰もが無料ツールでソフトウェアを作れるのと同じように、今後は個人が半導体チップを設計でき、それが商品となって流通する時代が来るでしょう。
この記事では、SkyWarter PDKを利用して、Verilogのサンプルコードを入力とし、RTL→GDLのデジタル回路のインプリメンテーション環境OpenLaneを実行して、レイアウト結果ファイルとなるGDSを作成し、GUIで表示する方法、各工程の処理内容、自作Verilog回路でフローを流す方法を紹介します。
本記事の内容を動画に収めていますので、よろしければご覧ください。
Windows版の動画は以下です。
Mac版の動画は以下です。
実行環境
Mac (Intel CPU)とWindowsで動作確認済みです。
Ubuntu等のLinuxでも実行できると思います。
項目 | Mac (Intel CPU) | Windows |
---|---|---|
PC | macOS Catalina 10.15.7, macOS Big Sur 11.6 | Windows10, Ubuntu20.04 on WSL2 |
Docker | Docker Desktop for Mac 3.6.0, Docker Desktop for Mac 4.1.1 | Docker Desktop for Windows 4.0.1 |
Python | 3.8.9 3.8.11 | 3.8.10 |
X11 | XQuartz 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
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が展開されます。
ここまでの内容は環境構築のためのものなので、一度だけ実行すれば良いです。
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のすべての工程が流れます。
正常に実行できていれば、designs/spm/runs/〜/results/magic/spm.gds
としてGDSファイルが生成できていると思います。
GDSファイルは半導体設計の結果となる図形情報を格納したファイルです。
通常の半導体設計でここまで自動化されていることはまず無いと思いますが、初心者にはありがたい作りですね。
反面、何が実行されているのか意識しづらいですね。
-from, -toでステージ名を指定して部分的に実行することもできます。
ステージ名はflow.tcl
内のrun_non_interactive_mode
関数内にある”synthesis”, “floorplan”, …を指定すれば良いです。
以下、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などは使わなくなりました。)
Macの場合、以下のコマンドでXquartzをインストールします。
HomeBrewをインストールしていない場合はこちらからインストールします。
brew install --cask xquartz
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
これで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を押します。
下の用に表示されれば成功です。
右の方にある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
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を制御するのか、現時点では不明です。
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
File→Import→DEF/LEFを順にクリックします。
下図のようにImport Fileの「…」ボタンからDEFファイルdesigns/spm/runs/trial/results/floorplan/spm.floorplan.def
を指定します。
DEFファイルを指定すると同じディレクトリにあるmerged_unpadded.lef
もWith LEF files:の欄に表示されると思います。(表示されない場合は手動で指定します)
Optionsボタンをクリックします。
初回KLayout実行時は以下のようにTechnology Setupの中身が空になると思います。
初回KLayout起動時はこのままOK→さらにOKを押してDEFを開きます。
しかし、下図のようにセルが表示されない状態になると思いますので、File→Exitで一旦KLayoutを閉じます。
再度KLayoutを立ち上げ、File→Import→DEF/LEF→Optionsと進むと下図のようにTechnology Setupが表示されると思います。
「LEF+Macro Files」タブを開き、LEF macro geometryの欄にプルダウンから「Always produce LEF geometry and ignore LEF FOREIGN」を選択してOKを押します。
これにしておかないとセルが表示されない状態になりました。
これで以下のようにフロアプラン結果が表示されます。
左側にあるCellsのパネルのLevelsの右側の数値を1にするとセルは下図のように外形のみ表示されます。
フロアプラン結果として、周囲の端子、Decap、Tapセルが置かれていることがわかります。
Levelsの右側の数値を2にすると、下図のようにセルの中身(LEF情報)が表示されます。
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で確認します。
上図のとおり、セルが配置されていることがわかります。
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です。
セルをクリックしてQを押すと上図のようにセルの情報を表示できます。
routing:配線
論理合成やCTSで作られた回路の接続情報をメタル層、VIA層による結線に落とし込む工程です。
実行結果はDEFファイルdesigns/spm/runs/trial/results/routing/17-spm.def
に出力されます。
KLayoutで表示すると下図のようにメタル層、VIA層による信号配線が引かれているのがわかります。
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_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で、以下のように表示されました。
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と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
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サイズは回路規模と設定した占有率から自動的に決められ、そのサイズが小さすぎてセルが入らなかったようです。
configuration/floorplan.tcl
に占有率を設定する箇所があったので、以下のように10(%)に変更しました。
#set ::env(FP_CORE_UTIL) 50 set ::env(FP_CORE_UTIL) 10
これでうまく流れました。
トラブルシューティング
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と進むと上図のように中身が表示されます。
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になるので、メニューからウィンドウ→拡大/縮小を選択すると枠内に表示されました。
まとめ
OpenLaneで用意されたサンプルVerilogコードを使ってRTL→GDSフローを流し、レイアウト結果をKLayoutやmagicのGUIで表示して確認する方法を紹介しました。
そして、各工程でどのような処理がなされているか、簡単ではあるものの確認を行いました。
さらに新たにVerilog RTLを書いてRTL→GDSフローを流し、GDSを生成するまでの方法を紹介しました。
これが家でできる時代が来たことに時代の変化を感じます。
現時点で試したのは、ここまでですが、Verilogシミュレーションやアナログ回路の設計についても気になりますよね。
ネットで検索するとある程度はこういった内容もあるようなので、今後試していきたいと思います。
2020年から2021年にかけてCaravelという無料のシャトルプロジェクトがあったようで、製造や輸送まで無料で実施できたようです。
今後もこういったシャトルプロジェクトが実施されるのかわかりませんが、目が離せませんね。
書籍紹介
入門Verilog HDL記述―ハードウェア記述言語の速習&実践 (Design wave basic)
記述例を見ながら実践的なVerilog回路の書き方を学ぶことができ、初心者にやさしく、半導体関連企業における新人研修で使われることもあるようです。
わかるVerilog HDL入門―文法の基礎から論理回路設計、論理合成、実装まで (トランジスタ技術SPECIAL)
トラ技派生のVerilog入門書でFPGAを使った実践的な内容も紹介されており、基礎から応用まで丁寧に説明されていて、特にFPGAで自作回路を作りたい方には最適な書籍だと思います。
参考文献
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)