RISC-VとChiselで学ぶ はじめてのCPU自作
――オープンソース命令セットによるカスタムCPU実装への第一歩
――オープンソース命令セットによるカスタム
2021年8月25日紙版発売
2021年8月20日電子版発売
⻄⼭悠太朗,井⽥健太 著
B5変形判/336ページ
定価3,520円(本体3,200円+税10%)
ISBN 978-4-297-12305-5
書籍の概要
この本の概要
本書では,UCバークレーで開発されたオープンソースの命令セット(ISA)「RISC-V」を用いて,CPUの作り方を解説します。コンピュータアーキテクチャ,ハードウェアに関する知識があまりない方にも理解できるように基礎からわかりやすく学んでいきます。CPUとコンピュータアーキテクチャのしくみを解説したうえで,基本整数命令の実装から,CPUの高速化で活躍するパイプラインの実装,スーパーコンピューターでも活躍するベクトル拡張命令(SIMD),さらに,汎用CPUでは負荷の高い処理をより高速に実行するためにCPUへ追加可能なカスタム命令の実装までを行います。CPU設計に用いる基本言語としては,Velilogを抽象化したHDL(ハードウェア記述言語)であるChiselを利用しています。
CPUの自作範囲に関して,手順が煩雑なFPGAでの動作確認は行わず,ソフトウェア上でエミュレーションをゴールとしているので,ソフトウェアエンジニアの方にも取っ付きやすいものとなっています。
巻末には,昨今RISC-Vが注目されている理由を整理するため,RISC-Vのもたらす価値についてまとめています。
こんな方におすすめ
- ソフトウェアエンジニアで,CPUや命令セットなどのローレイヤーを学びたい人
- 情報,コンピュータ関連学部へ通う学生
- RISC-Vに興味がある人
- カスタムCPU,DSA(Domain Specific Architecture)に興味がある人
この書籍に関連する記事があります!
- CPUは何をしているのか?
- コンピュータの頭脳と例えられるCPU。CPUを動かすためには,CPUが解釈して実行できる機械語の仕様を定めた,命令セットアーキテクチャと呼ばれるものが必要となります。
目次
- まえがき
第Ⅰ部 CPU自作のための基礎知識
第1章 CPUとは何か
- 1-1 電子回路が論理を表現できる理由
- 1-1-1 デジタル信号への変換
- 1-1-2 論理演算を表現する回路
- 1-1-3 いかなる真理値表も表現できる基本論理回路
- 1-2 基本論理回路がCPUを実現できる理由
- 1-2-1 順序論理回路:ラッチ回路
- 1-2-2 有限状態機械
- 1-2-3 クロック信号による同期
- 1-3 CPUの製造プロセス
- Column バイポーラトランジスタとCMOS
第2章 コンピュータ・アーキテクチャ
- 2-1 メモリ
- 2-1-1 レジスタ
- 2-1-2 メインメモリ
- 2-2 コンピュータの基本的な処理の流れ
- 2-2-1 命令フェッチ(IF:Instruction Fetch)
- 2-2-2 命令デコード(ID:Instruction Decode)
- 2-2-3 演算(EX:Execution)
- 2-2-4 メモリアクセス(MEM:Memory Access)
- 2-2-5 ライトバック(WB:Write Back)
- Column デコード処理の簡略化
- Column RISCとCISC
- Column レジスタとメモリの扱い
第3章 ハードウェア記述言語Chiselの基本
- 3-1 Chiselとは
- 3-2 オブジェクト指向とは
- 3-2-1 クラスとインスタンス
- 3-2-2 継承
- 3-3 Scalaの基本文法
- 3-3-1 変数varとval
- 3-3-2 メソッド:def
- 3-3-3 コレクション:Seq
- 3-3-4 for式
- 3-3-5 オブジェクト
- 3-3-6 名前空間
- 3-4 Chiselの基本文法
- 3-4-1 bit値を表す基本型
- 3-4-2 演算子
- 3-4-3 Module
- 3-4-4 IO
- 3-4-5 Flippedオブジェクト
- 3-4-6 配線の接続
- 3-4-7 組み合わせ論理回路:Wire/WireDefault
- 3-4-8 順序論理回路:RegInit
- 3-4-9 Memによるレジスタファイル定義
- 3-4-10 制御回路
- 3-4-11 bit操作
- 3-4-12 printfによるデバッグ
- Column あらゆるものがオブジェクト
第Ⅱ部「簡単なCPUの実装」
第4章 環境構築
- 4-1 chisel-templateのダウンロード
- 4-2 Dockerによる実行環境の構築
- 4-2-1 Dockerのインストール
- 4-2-2 Dockerfileの作成
- 4-2-3 イメージの作成
- 4-2-4 コンテナの作成
- 4-3 命令bit列および定数ファイル
- 4-3-1 Instructions.Scala
- 4-3-2 Consts.scala
- 4-4 第Ⅱ部で実装する命令とChiselコード全体
第5章 命令フェッチの実装
- 5-1 Chiselコードの概要
- 5-2 Chiselの実装
第6章 ChiselTestによる命令フェッチテスト
- 6-1 ChiselTestのインストール
- 6-2 テストの流れ
- 6-3 Chiselテストコードの作成
- 6-3-1 trait
- 6-3-2 peekメソッド
- 6-3-3 clock.stepメソッド
- 6-4 メモリ用hexファイルの作成
- 6-5 printfを活用したデバッグ信号の出力
- 6-6 テストの実行
- 6-7 Dockerコンテナのcommit
第7章 命令デコーダの実装
- 7-1 Chiselの実装
- 7-1-1 レジスタ番号の解読
- 7-1-2 レジスタデータの読み出し
- 7-1-3 デバッグ用信号の出力
- 7-2 テストの実行
第8章 LW命令の実装
- 8-1 RISC-VのLW命令定義
- 8-2 Chiselの実装
- 8-2-1 ①命令bitパターンの定義
- 8-2-2 ②CPUとメモリ間のポート定義
- 8-2-3 ③CPU内の処理実装
- 8-2-4 ④メモリのデータ読み込み実装
- 8-3 テストの実行
- 8-3-1 命令ファイルlw.hexの作成
- 8-3-2 メモリにロードするファイル名の変更
- 8-3-3 テスト終了条件の変更
- 8-3-4 デバッグ信号の追加
- 8-3-5 テストの実行
第9章 SW命令の実装
- 9-1 RISC-VのSW命令定義
- 9-2 Chiselの実装
- 9-2-1 ①命令bitパターンの定義
- 9-2-2 ②CPUとメモリ間のポート定義
- 9-2-3 ③CPU内の処理実装
- 9-2-4 ④メモリのデータ書き込み実装
- 9-3 テストの実行
- 9-3-1 命令ファイルsw.hexの作成
- 9-3-2 メモリにロードするファイル名の変更
- 9-3-3 テスト終了条件の変更
- 9-3-4 デバッグ用信号の追加
- 9-3-5 テストの実行
第10章 加減算命令の実装
- 10-1 RISC-Vの加減算命令定義
- 10-2 Chiselの実装
- 10-2-1 命令bitパターンの定義
- 10-2-2 加減算結果の接続@EXステージ
- 10-2-3 加減算結果のレジスタライトバック@WBステージ
第11章 論理演算の実装
- 11-1 RISC-Vの論理演算命令定義
- 11-2 Chiselの実装
- 11-2-1 命令bitパターンの定義
- 11-2-2 論理演算結果の接続@EXステージ
- 11-2-3 論理演算結果のレジスタライトバック@WBステージ
第12章 デコーダの強化
- 12-1 ALU用デコード
- 12-1-1 デコーダの強化@IDステージ
- 12-1-2 デコード信号を活用したALU簡略化@EXステージ
- 12-2 MEM用デコード
- 12-2-1 デコーダの強化@IDステージ
- 12-2-2 命令デコードの不要化@MEMステージ
- 12-3 WB用デコード
- 12-3-1 デコーダの強化@IDステージ
- 12-3-2 命令デコードの不要化@WBステージ
第13章 シフト演算の実装
- 13-1 RISC-Vのシフト演算命令定義
- 13-2 Chiselの実装
- 13-2-1 命令bitパターンの定義
- 13-2-2 デコード信号の生成@IDステージ
- 13-2-3 シフト演算結果の接続@EXステージ
第14章 比較演算の実装
- 14-1 RISC-Vの比較演算命令定義
- 14-2 Chiselの実装
- 14-2-1 命令bitパターンの定義
- 14-2-2 デコード信号の生成@IDステージ
- 14-2-3 比較演算結果の接続@EXステージ
第15章 分岐命令の実装
- 15-1 RISC-Vの分岐命令定義
- 15-2 Chiselの実装
- 15-2-1 命令bitパターンの定義
- 15-2-2 PCの制御@IFステージ
- 15-2-3 即値およびデコード信号の生成@IDステージ
- 15-2-4 分岐可否、ジャンプ先アドレスの計算@EXステージ
第16章 ジャンプ命令の実装
- 16-1 RISC-Vのジャンプ命令定義
- 16-2 Chiselの実装
- 16-2-1 命令bitパターンの定義
- 16-2-2 デコードおよびオペランドデータの読み出し@IDステージ
- 16-2-3 JALR用演算の追加@EXステージ
- 16-2-4 PCの制御@IFステージ
- 16-2-5 raのライトバック@WBステージ
第17章 即値ロード命令の実装
- 17-1 RISC-Vの即値ロード命令定義
- 17-2 Chiselの実装
- 17-2-1 命令bitパターンの定義
- 17-2-2 デコードおよびオペランドデータの読み出し@IDステージ
- Column LI(Load Immediate)命令
第18章 CSR命令の実装
- 18-1 RISC-VのCSR命令定義
- 18-2 Chiselの実装
- 18-2-1 命令bitパターンの定義
- 18-2-2 即値およびデコード信号の生成@IDステージ
- 18-2-3 op1_dataの接続@EXステージ
- 18-2-4 CSRの読み書き@MEMステージ
- 18-2-5 CSR読み出しデータのレジスタライトバック@WBステージ
第19章 ECALLの実装
- 19-1 RISC-VのECALL命令定義
- 19-2 Chiselの実装
- 19-2-1 命令bitパターンの定義
- 19-2-2 PCの制御@IFステージ
- 19-2-3 デコード信号の生成@IDステージ
- 19-2-4 CSR書き込み@MEMステージ
第20章 riscv-testsによるテスト
- 20-1 riscv-testsのビルド
- 20-2 ELFファイルをBINファイルへ変換
- 20-3 BINファイルのhex化
- 20-4 riscv-testsのパス条件
- 20-5 riscv-testsの実行
- 20-5-1 Chiselの実装
- 20-5-2 テストの実行
- 20-6 一括テストスクリプト
- 20-6-1 hexファイルの一括生成:tohex.sh
- 20-6-2 riscv-testsの一括実行:riscv_tests.sh
第21章 Cプログラムを動かしてみよう
- 21-1 Cプログラム作成
- 21-2 コンパイル
- 21-3 リンク
- 21-4 機械語のhex化とdumpファイルの生成
- 21-5 テストの実行
- Column コンパイルとアセンブル
第Ⅲ部 パイプラインの実装
第22章 パイプラインとは
- 22-1 パイプライン処理の意義
- 22-2 CPU処理のパイプライン化
- 22-3 第Ⅲ部で完成するChiselコード
第23章 パイプラインレジスタの実装
- 23-1 レジスタ定義
- 23-2 IFステージ
- 23-2-1 命令フェッチおよびPC制御
- 23-2-2 IF/IDレジスタへの書き込み
- 23-3 IDステージ
- 23-3-1 ①レジスタ番号のデコードおよびレジスタデータの読み出し
- 23-3-2 ②即値のデコード
- 23-3-3 ③csignalsのデコード
- 23-3-4 ④オペランドデータの選択
- 23-3-5 ⑤csr_addrの生成
- 23-3-6 ⑥ID/EXレジスタへの書き込み
- 23-4 EXステージ
- 23-4-1 ①alu_outへの信号接続
- 23-4-2 ②分岐命令の処理
- 23-4-3 ③EX/MEMレジスタへの書き込み
- 23-5 MEMステージ
- 23-5-1 ①メモリアクセス
- 23-5-2 ②CSR
- 23-5-3 ③wb_data
- 23-5-4 ④MEM/WBレジスタへの書き込み
- 23-6 WBステージ
第24章 分岐ハザード処理
- 24-1 分岐ハザードとは
- 24-2 Chiselの実装
- 24-2-1 IFステージの無効化
- 24-2-2 IDステージの無効化
- 24-2-3 デバッグ用信号の追加
- 24-3 分岐ハザードのテスト
- 24-3-1 テスト用Cプログラムの作成
- 24-3-2 hexおよびdumpファイルの生成
- 24-3-3 分岐ハザード対応前CPUでのテスト
- 24-3-4 分岐ハザード対応後CPUでのテスト
- Column 静的分岐予測と動的分岐予測
第25章 データハザード処理
- 25-1 データハザードとは
- 25-2 フォワーディングのChisel実装
- 25-3 ストールのChisel実装
- 25-3-1 stall_flg信号の追加@IDステージ
- 25-3-2 ストール処理@IFステージ
- 25-3-3 BUBBLE化@IDステージ
- 25-3-4 デバッグ用信号の追加
- 25-4 データハザードのテスト
- 25-4-1 ①ID/WB間のデータハザードをフォワーディングするパターン
- 25-4-2 ②ID/EX間のデータハザードによるストール→ID/MEM間でフォワーディングするパターン
- 25-4-3 riscv-testsテスト
第Ⅳ部 ベクトル拡張命令の実装
第26章 ベクトル命令とは
- 26-1 SIMDとは
- 26-2 既存のベクトルアーキテクチャ
- 26-3 RISC-Vのベクトル命令とSIMD命令の相違点
- 26-3-1 SIMD命令のベクトルレジスタ長
- 26-3-2 RVV命令のベクトルレジスタ長
- 26-4 第Ⅳ部で完成するChiselコード
- Column スーパーコンピュータ「富岳」
第27章 VSETVLI命令の実装
- 27-1 RISC-VのVSETVLI命令定義
- 27-2 VTYPE
- 27-2-1 SEWとLMUL
- 27-2-2 vill、vta、vma
- 27-3 Chiselの実装
- 27-3-1 命令bitパターンの定義
- 27-3-2 デコード信号の生成@IDステージ
- 27-3-3 ベクトルCSRへの書き込み@MEMステージ
- 27-3-4 VLのレジスタライトバック@WBステージ
- 27-4 テストの実行
- 27-4-1 e32/m1テスト
- 27-4-2 e64/m1テスト
- 27-4-3 e32/m2テスト
第28章 ベクトルロード命令の実装
- 28-1 unit-stride形式のベクトルロード命令定義
- 28-1-1 SEWとEEW
- 28-1-2 bit配置
- 28-2 Chiselの実装
- 28-2-1 命令bitパターンの定義
- 28-2-2 DmemPortIoの拡張
- 28-2-3 ベクトルレジスタの追加
- 28-2-4 デコード信号の生成@IDステージ
- 28-2-5 ベクトルロードデータのレジスタライトバック@WBステージ
- 28-2-6 メモリからベクトルデータの読み出し@Memoryクラス
- 28-2-7 デバッグ用信号の追加
- 28-3 テストの実行
- 28-3-1 e32/m1テスト
- 28-3-2 e64/m1テスト
- 28-3-3 e32/m2テスト
第29章 ベクトル加算命令VADD.VVの実装
- 29-1 RISC-VのVADD.VV命令定義
- 29-2 Chiselの実装
- 29-2-1 命令bitパターンの定義
- 29-2-2 ベクトルレジスタの読み出し@IDステージ
- 29-2-3 デコード信号の生成@IDステージ
- 29-2-4 ベクトル加算器の追加@EXステージ
- 29-2-5 加算結果のレジスタライトバック@WBステージ
- 29-2-6 デバッグ用信号の追加
- 29-3 テストの実行
- 29-3-1 e32/m1テスト
- 29-3-2 e64/m1のテスト
- 29-3-3 e32/m2のテスト
第30章 ベクトルストア命令の実装
- 30-1 unit-stride形式のベクトルストア命令定義
- 30-2 Chiselの実装
- 30-2-1 命令bitパターンの定義
- 30-2-2 DmemPortIoの拡張
- 30-2-3 デコード信号の生成、ストアデータの読み出し@IDステージ
- 30-2-4 ストアデータの接続@MEMステージ
- 30-2-5 ベクトルデータのメモリへの書き込み@Memoryクラス
- 30-3 テストの実行
- 30-3-1 e32/m1テスト
- 30-3-2 e64/m1テスト
- 30-3-3 e32/m2テスト
第Ⅴ部 カスタム命令の実装
第31章 カスタム命令の意義
- 31-1 シングルコアの性能向上と限界
- 31-1-1 ムーアの法則
- 31-1-2 デナード則
- 31-1-3 デナード則の崩壊
- 31-2 マルチコアによる並列処理の効率化と限界
- 31-2-1 マルチコアへの移行
- 31-2-2 並列処理の効率化の限界
- 31-3 DSAの可能性
- 31-3-1 ASIC
- 31-3-2 FPGA
- 31-3-3 DSAのデメリット
- 31-4 DSAとRISC-V
- 31-4-1 自由なアーキテクチャ設計
- 31-4-2 カスタム命令
- Column 消費電力対策
- Column アクセラレータ
第32章 ポピュレーションカウント命令の実装
- 32-1 ポピュレーションカウント命令とは
- 32-2 カスタム命令を実装しない場合のポピュレーションカウントプログラム
- 32-3 カスタム命令用のコンパイラ(アセンブラ)実装
- 32-3-1 GNU Assemblerの概要
- 32-3-2 PCNT命令をGASへ追加
- 32-3-3 コンパイラの再ビルド
- 32-3-4 PCNT 命令のコンパイル
- 32-4 Chiselの実装
- 32-4-1 命令列の定義
- 32-4-2 デコード信号の生成@IDステージ
- 32-4-3 ALUの追加@EXステージ
- 32-5 テストの実行
付録 RISC-Vの価値
- A-1 オープンソースISAの必要性
- A-2 RISC-Vが実現するもの
- A-2-1 ①高性能・低コストを両立するDSA
- A-2-2 ②安価な汎用CPU
- A-2-3 ③誰でも気軽に勉強・実装ができる教育環境
- A-3 チップ製造コストの壁とその将来性
- もっと深く学びたい人へのお勧め書籍
この本に関連する書籍
-
新・標準プログラマーズライブラリ RISC-Vで学ぶコンピュータアーキテクチャ 完全入門
コンピュータアーキテクチャとは,より良いコンピュータの構成を模索し,設計し,実現するための方式です。学習には,重要概念の理解とハードウェアの設計,実装,その...
-
作って学ぶコンピュータアーキテクチャ ——LLVMとRISC-Vによる低レイヤプログラミングの基礎
コンピュータアーキテクチャ,とくにCPUの命令セットアーキテクチャについて,RISC-Vを例に「上のレイヤからアプローチする」ことで理解を深めることを目的とした一冊。...
-
動かしてわかる CPUの作り方10講
野村達雄氏(『ポケモンGO』開発者)推薦!! 「簡潔明瞭な文章でソフトウェアからトランジスタまで漏れなく解説。 CPUをゼロから設計してFPGAで実装する, 僕の人生を...
-
コンピュータアーキテクチャ技術入門 ――高速化の追求×消費電力の壁
わずか70年余りで,150億倍もの演算速度向上を遂げたプロセッサ, 40年余りで記憶容量が800万倍に増加したメインメモリ, 55年余りで記憶密度が3億倍に達したストレー...