Caravel template 環境の構築と試用

efabless 社 chipignite シャトルサービスでは,チップ作製データを作成するための Caravel template 環境が提供されています.本ドキュメントでは,Caravel template 環境構築からテンプレートを利用して最小構成の回路を含むチップ作製データの生成の手順を記載します.

Caravel template では,あらかじめ IO パッド,クロック・リセット生成,制御 RISC-V プロセッサ,制御用の汎用インタフェースの IP コアが構成されており,シャトルサービスのユーザは論理回路のみを開発してチップを製造できる仕組みが提供されています.

また,回路を合成してチップ製造データを作成するためのオープンソース EDA や PDK の導入や設定など環境構築をスクリプトにより自動的に行えます.さらに,回路の合成やチップ作製データのチェックも同様にスクリプトを用いて半自動的に行うことが可能です.

以下のセクションでは,環境構築,テンプレートの最小構成の回路の合成,合成により得られたチップ作製データのチェックを順に行います.

注釈

Caravel template 環境では,efabless 社 chipignite シャトルサービス向けのユーザ領域のみであり,Caravelの制御回路などは含んでいません.Caravel制御回路との接続などはシャトルサービスにて行われます.このため,作製されるチップ全体のレイアウトは確認できませんが,ユーザ領域のみ用意すればシャトルサービスが利用できる点にご留意下さい.

Caravel template 環境のセットアップ

本ガイドでは,Ubuntu 22.04 LTS に Rootless mode の Docker がセットアップされており,ユーザ名が openeda を前提としています.

必要パッケージの導入

開発環境の導入に必要となるパッケージを導入します.(既にインストールされているものも含まれている場合があります)

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install -y build-essential python3 python3-venv python3-pip
sudo apt-get install -y make git
python3 -m pip install pyyaml click

Caravel template 環境のディレクトリ構成

Caravel template 環境を構築するディレクトリを下記のように構成します.

$HOME/
|-- Caravel_mpw-9k/
    |-- caravel_mpw-9k/
    |-- dependencies/
    |   |-- openlane_src/
    |   |-- pdks/
    |-- precheck_mpw-9k/
    |setenv.sh

Caravel template のダウンロード

Caravel template (mpw-9k) ディレクトリを作成し,efabless 社の git サイトから Caravel template (caravel_user_template) レポジトリの mpw-9k タグのテンプレートをクローンします.

mkdir Caravel_mpw-9k
cd Caravel_mpw-9k
git clone -b mpw-9k https://github.com/efabless/caravel_user_project.git caravel_mpw-9k

環境変数の設定ファイルの作成

まず,ツールなどの導入や利用に必要な環境変数の設定を行うファイルをあらかじめ作成します.ファイル名を setenv.sh とします.

export OPENLANE_ROOT=$HOME/Caravel_mpw-9k/dependencies/openlane_src
export PDK_ROOT=$HOME/Caravel_mpw-9k/dependencies/pdks
export PDK=sky130A
export CARAVEL_ROOTT=$HOME/Caravel_mpw-9k/caravel_mpw-9k/caravel
コマンドラインからファイルを生成する方法
touch setenv.sh
echo "export OPENLANE_ROOT=\$HOME/Caravel_mpw-9k/dependencies/openlane_src" | tee -a setenv.sh
echo "export PDK_ROOT=\$HOME/Caravel_mpw-9k/dependencies/pdks" | tee -a setenv.sh
echo "export PDK=sky130A" | tee -a setenv.sh
echo "export CARAVEL_ROOTT=\$HOME/Caravel_mpw-9k/caravel_mpw-9k/caravel" | tee -a setenv.sh

ツール・PDK のセットアップ

環境変数の設定を行い,Caravel template ディレクトリに移動します.

source setenv.sh
cd caravel_mpw-9k

次に,一部ツールのディレクトリや Rootless mode の Docker へ対応できるよう,Makefile の修正を行います.ここではパッチファイルを利用します.

$HOME/Caravel_mpw-9k ディレクトリに下記の内容の Makefile.patch を作成します.

Makefile.patch
20c20
< PRECHECK_ROOT?=${HOME}/mpw_precheck
---
> PRECHECK_ROOT?=${HOME}/Caravel_mpw-9k/precheck_mpw-9k
34c34
< ROOTLESS ?= 0
---
> ROOTLESS ?= 1
261d260
< 		-u $(shell id -u $(USER)):$(shell id -g $(USER)) \
273d271
< 		-u $(shell id -u $(USER)):$(shell id -g $(USER)) \
289d286
< 	-u $(shell id -u $(USER)):$(shell id -g $(USER)) \

パッチ内容を --dry-run オプションにより確認後,Makefile へ適用します.

patch --dry-run caravel_mpw-9k/Makefile < Makefile.patch
patch caravel_mpw-9k/Makefile < Makefile.patch
パッチ内容について

パッチファイルでは,以下の修正を行っています.

  • 回路合成結果をチェックする precheck のインストールフォルダの修正

- PRECHECK_ROOT?=${HOME}/mpw_precheck
+ PRECHECK_ROOT?=${HOME}/Caravel_mpw-9k/precheck_mpw-9k
  • Caravel template の環境を Rootless mode の Docker により利用するための修正.

- ROOTLESS ?= 0
+ ROOTLESS ?= 1
  • 上記の ROOTLESS 設定では動作が切り替わらない箇所,261, 273, 289 行あたりの「-u」オプション行を削除

-		-u $(shell id -u $(USER)):$(shell id -g $(USER)) \

Makefile ファイルの修正後,セットアップ実行します.(10分程度要します)

make setup

テンプレートを利用した最小構成の回路の合成

テンプレートの初期サンプル回路を合成し,Caravel template 環境を用いたビルドの手順を確認します.なお,回路合成にはおよそ1~2時間程度を要します.

サンプル回路は 16-bit のカウンタ回路であり,カウンタの値がユーザ用 IO に接続されています.また,Caravel 制御回路の RISC-V プロセッサと Wishbone バス,内部ロジックアナライザにも接続されており,Caravel 制御回路からユーザ回路を操作する機構を試用することもできます.

クロックやリセットも Caravel 制御回路により生成されます.

サンプル回路の修正

サンプル回路の IO (GPIO) の電源投入時の設定を記述するファイル verilog/rtl/user_defines.v の修正を行う必要があります.ここではパッチファイルを利用します.

$HOME/Caravel_mpw-9k ディレクトリに下記の内容の user_defines.v.patch を作成します.

user_defines.v.patch
55,63c55,63
< `define USER_CONFIG_GPIO_5_INIT  `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_6_INIT  `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_7_INIT  `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_8_INIT  `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_9_INIT  `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_10_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_11_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_12_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_13_INIT `GPIO_MODE_INVALID
---
> `define USER_CONFIG_GPIO_5_INIT  `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_6_INIT  `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_7_INIT  `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_8_INIT  `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_9_INIT  `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_10_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_11_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_12_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_13_INIT `GPIO_MODE_USER_STD_OUTPUT
66,76c66,76
< `define USER_CONFIG_GPIO_14_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_15_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_16_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_17_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_18_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_19_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_20_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_21_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_22_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_23_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_24_INIT `GPIO_MODE_INVALID
---
> `define USER_CONFIG_GPIO_14_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_15_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_16_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_17_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_18_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_19_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_20_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_21_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_22_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_23_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_24_INIT `GPIO_MODE_USER_STD_OUTPUT
78,90c78,90
< `define USER_CONFIG_GPIO_25_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_26_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_27_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_28_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_29_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_30_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_31_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_32_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_33_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_34_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_35_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_36_INIT `GPIO_MODE_INVALID
< `define USER_CONFIG_GPIO_37_INIT `GPIO_MODE_INVALID
---
> `define USER_CONFIG_GPIO_25_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_26_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_27_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_28_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_29_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_30_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_31_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_32_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_33_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_34_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_35_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_36_INIT `GPIO_MODE_USER_STD_OUTPUT
> `define USER_CONFIG_GPIO_37_INIT `GPIO_MODE_USER_STD_OUTPUT

パッチ内容を --dry-run オプションにより確認後,verilog/rtl/user_defines.v へ適用します.

patch --dry-run caravel_mpw-9k/verilog/rtl/user_defines.v < user_defines.v.patch
patch caravel_mpw-9k/verilog/rtl/user_defines.v < user_defines.v.patch

パッチでは,verilog/rtl/user_defines.v 中の USER_CONFIG_GPIO_*_INIT が GPIO_MODE_INVALID(無効)を GPIO_MODE_USER_STD_OUTPUT (出力)へ修正しています.

回路合成の実行

user_defines.v の修正後,ユーザ回路本体(user_proj_example)と Caravel と接続するラッパー(user_project_wrapper)の合成を実行します.

make user_proj_example
make user_project_wrapper

エラーなど表示されず回路合成が成功すると「Flow complete」と表示され,gdsフォルダ下に user_progect_wrapper.gds ファイルが生成されます.

チップ作製データのチェック

回路合成により得られるチップ作製データの整合性などのチェックを行います. チェックではチップ製造の工程との整合性チェックのほか,説明ファイル README.md の内容についてもチェックされます.

チェック用スクリプトの修正

チェック用スクリプトを Rootless mode の Docker へ対応させる修正を行います.

$HOME/Caravel_mpw-9k ディレクトリに下記の内容の docker-mount.sh.patch を作成します.

docker-mount.sh.patch
19a20
>   -u $(id -u "$USER"):$(id -g "$USER") \

パッチ内容を --dry-run オプションにより確認後,Makefile へパッチを適用します.

patch --dry-run precheck_mpw-9k/docker-mount.sh < docker-mount.sh.patch
patch precheck_mpw-9k/docker-mount.sh < docker-mount.sh.patch
パッチ内容について

パッチファイルでは,以下の修正を行っています.

Caravel_mpw-9k/precheck_mpw-9k/docker-mount.sh ファイル 19 行あたりの「-u」オプション行を削除することで,Rootless mode の Docker に対応させています.


README の修正

README.md を下記の例のように書き換えます.

This project is minimally modified to mpw-9i caravel template.
The function is 32-bit counter. 16-bit IOs are set to OUTPUT.

なお,README.md に原文が残っている場合や README.bak などオリジナルの複製など残している場合もチェックにてエラーが報告されます.

チェックの実行

下記コマンドによりチェックを実行します. チェック中に不具合が見つかった場合でも全ての項目が確認され,1時間程度要します.

make run-precheck

全て項目のチェックに合格すると All Checks Passed !!! と表示されます.