Chiselで始める爆速LSI設計

この記事は HDL Advent Calendar 2021 5日目の記事です。 qiita.com

はい、Cra2yPierr0tです。

皆さん、来週の月曜に会社や研究室に顔を出すと、ボスがニコニコしながら近づいてきて「〇〇さん、一ヶ月くらいでこんな感じのLSI作ってくれない?ツールはフリーな物を自分で探してね!」と言ってきたらどうしますか?こんな無茶振りをされるという事は、妻子を人質に取られているか拳銃を突き付けられている可能性がありますね。今この文章を読んでいる皆さん、幸運です。この記事を読めば、ボスとの交渉に使えるギリギリ成果物っぽいサムシングをこしらえる事が可能です。

ではやっていきましょう。

概要

RTLをChiselで生やしてGDSII*1をOpenLANEを使って生成しましょう。Chiselの詳しい説明はインターネットに先達が書いた記事が存在しているのでそちらを参照してください。

1. Chiselのインストール

始めにscalaのビルドツールであるsbtをインストールしましょう。インストール方法は各自OSに応じて調べてください。

$ sudo pacman -S sbt

次にChiselのプロジェクトテンプレートをダウンロード、このディレクトリ下でChiselが使えます。

$ git clone https://github.com/ucb-bar/chisel-template.git

2. Chiselを書く

今回はボスに5つの8bitの入力の分散を計算するハードウェアを要求されたと仮定しましょう。

ダウンロードしたchisel-templateのsrc/main/scala以下にvarianceディレクトリを作成し、variance.scalaにChiselを書いていきます。

.
└── chisel-template
    └── src
        └── main
            └── scala
                └── variance
                    └── variance.scala

以下が分散を計算するvariance.scalaの内容です。Chiselを初めて書いたので正しく動くか分かりませんが多分動きます。

import chisel3._

class variance extends Module {
  val io = IO(new Bundle {
    val in = Input(Vec(5, UInt(8.W)))
    val out = Output(UInt((8.W)))
  })

  var r_sum = Reg(UInt(16.W))       // 総和
  var r_sum2 = Reg(UInt(16.W))      // 2乗の総和

  val r_average_2 = Reg(UInt(16.W)) // 平均の2乗
  val r_average2  = Reg(UInt(16.W)) // 2乗の平均

  r_sum   = 0.U
  r_sum2  = 0.U
  for (i <- 0 to 4) {
    r_sum   = r_sum + io.in(i)
    r_sum2  = r_sum2 + io.in(i) * io.in(i)
  }
  r_average_2 := (r_sum / 5.U) * (r_sum / 5.U)
  r_average2  := r_sum2 / 5.U

  io.out := r_average2 - r_average_2
}

object Elaborate extends App {
  chisel3.Driver.execute(args, () => new variance)
}

そしたらchisel-template直下でsbt "run"を実行すればvariance.vが生成されます。

$ sbt "run"

variance.vは一旦置いておき、次はOpenLANEの準備に入ります。

3. OpenLANEのインストール

先程生成したTop.vをGDSIIにするために、OpenLANEをインストールしましょう。 OpenLANEは約20個のOSSを組み合わせて作成されたRTL-to-GDSIIコンパイラです。すごいね。

まずはOpenLANEリポジトリをクローン

$ git clone git@github.com:The-OpenROAD-Project/OpenLane.git
$ cd OpenLane

次にOpenLANEのDockerコンテナをダウンロード。事前にDockerデーモンを起動しておきましょう。

$ make pull-openlane

最後にskywater PDKをビルド、20分くらい掛かります。

$ make pdk

次は遂にGDSIIの生成です。

4. OpenLANEでGDSIIを生成

OpenLaneディレクトリ直下で以下のコマンドを実行し、designs以下に自分のデザインのディレクトリとコンフィグを追加しましょう。

$ make mount
bash-4.2$ ./flow.tcl -design variance -init_design_config

するとOpenLane/designs以下にvarianceディレクトリが生成されます。そしたらvariance/srcに先程生成したvariance.vを追加しましょう。

$ cp ../chisel-template/variance.v designs/variance/src

次にvarianceディレクトリにあるconfig.tclを編集します。CLOCK_PERIODとCLOCK_PORTの値を編集するだけで大丈夫です。

# User config
set ::env(DESIGN_NAME) variance

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

# Fill this
# 10MHz
set ::env(CLOCK_PERIOD) "100.0"
set ::env(CLOCK_PORT) "clock"

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

各変数の説明はここに書いてあります Variables information - OpenLane Documentation

config.tclの編集が終わったら、OpenLaneディレクトリ直下で以下のコマンドを実行してビルドを開始します。祈りましょう。

$ make mount
$ ./flow.tcl -design variance

ビルドが完了したらOpenLane/designs/variance/runs/RUN_<実行時刻>/result/finishingにvariance.gdsが生成されています。 klayoutでレイアウトを見ることが出来ます、これをボスに見せて猶予を貰いましょう。

おわりに

という訳でChiselからGDSIIを生成しました。実際にChisekを書き始めてからGDSIIファイルが生成されるまで大体3時間です。早いですね。 もし実際にOpenLANEを用いてオレオレLSIを焼きたいなら、OpenMPW Shuttle Programがオススメです。

efabless.com

GoogleがEfablessに出資したおかげで、デザインをオープンにする代わりに無料でLSIを焼くことが出来ます。送料も無料で5個の評価ボードと50個のチップがあなたの家に届きます! 流石にこの記事よりは時間も必要になりますしconfig.tclもそこそこ書くことになりますが、自分でチップを焼くことは他の現代人に対し圧倒的なアドバンテージになります。そんな事を言っていいのか、俺は130nmプロセスを焼いた漢だぞ。

もし興味が湧いたり質問がありましたらVLSI.jpを参照するかMake:LSIを覗いてみるか筆者に聞いてみてください。良き半導体ライフを。

参考

booth.pm

*1:LSIのレイアウトデータ