×
Copy
Open
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Ruby で作る RISC-V CPU エミュレーター hachi 2025/05/10
Slide 2
Slide 2 text
目次 ● 大阪府交野市在住 Rubyist ● 低レイヤーエケチェン ○ 京都の?大学で電気電子工学 を修めたんだが… ● Kernel/VM探検隊は初参加です ● 初参加初登壇を選んだことをちょっ と後悔しています hachi (@hachiblog)
Slide 3
Slide 3 text
なんで Ruby で? 作って意味ある?🤔
Slide 4
Slide 4 text
まあ聴いてくれ
Slide 5
Slide 5 text
2025年3月初旬
Slide 6
Slide 6 text
技術書典18サークル応募
Slide 7
Slide 7 text
技術書典18サークル応募
Slide 8
Slide 8 text
No content
Slide 9
Slide 9 text
実践で学ぶ基本情報を テーマにしてみるか
Slide 10
Slide 10 text
基本情報技術者試験の本をちょっと読む
Slide 11
Slide 11 text
基本情報技術者試験 ● 基本 ● 大学の時やったなぁみたいな内容が結構出てくる ○ データ構造 ○ アルゴリズム ○ ネットワーク ○ etc ● マイナスの数の表し方とかも出てくる ○ 1の補数、2の補数 ○ 2の補数を一般的には使っていることが多い
Slide 12
Slide 12 text
なんで2の補数がいいんだっけ
Slide 13
Slide 13 text
作ってみればわかるか?
Slide 14
Slide 14 text
CPU作ってみるかー
Slide 15
Slide 15 text
ちなみに
Slide 16
Slide 16 text
ちなみに
Slide 17
Slide 17 text
自分の前提知識 ● 高校生ぐらいの時に書籍 「CPU の創りかた」を買って放置する ● 大学2年生ぐらいの時に実験でロジックICを組み合わせてなんか作る課題 ○ 全然記憶ない ● 大学4年生ぐらいの時に実験でFPGAでなんかCPUみたいなものを作った気がす る ○ これは結構楽しかった
Slide 18
Slide 18 text
自分の前提知識 ● 高校生ぐらいの時に書籍 「CPU の創りかた」を買って放置する ● 大学2年生ぐらいの時に実験でロジックICを組み合わせてなんか作る課題 ○ 全然記憶ない ● 大学4年生ぐらいの時に実験でFPGAでなんかCPUみたいなものを作った気がす る ○ これは結構楽しかった つまりほぼ無い
Slide 19
Slide 19 text
早速作っていこう
Slide 20
Slide 20 text
前提知識
Slide 21
Slide 21 text
CPUエミュレーター
Slide 22
Slide 22 text
一般的なCPU(エミュレーター)の構成 レジスタ CPU デコーダ 演算器 メモリ
Slide 23
Slide 23 text
一般的なCPU(エミュレーター)の動き①フェッチ レジスタ CPU デコーダ 演算器 メモリ Program Counter 0x34202f73 0x800001a0
Slide 24
Slide 24 text
一般的なCPU(エミュレーター)の動き②デコード レジスタ CPU デコーダ 演算器 メモリ 0x34202f73
Slide 25
Slide 25 text
一般的なCPU(エミュレーター)の動き②デコード レジスタ CPU デコーダ 演算器 メモリ 0x34202f73 34202f73
Slide 26
Slide 26 text
一般的なCPU(エミュレーター)の動き②デコード レジスタ CPU デコーダ 演算器 メモリ 0x34202f73 34202f73 110100001000000010111101110011
Slide 27
Slide 27 text
一般的なCPU(エミュレーター)の動き②デコード レジスタ CPU デコーダ 演算器 メモリ 0x34202f73 4c771663 1001100011101110001011001100011 bne a4,t2,8000066c
Slide 28
Slide 28 text
一般的なCPU(エミュレーター)の動き③実行 レジスタ CPU デコーダ 演算器 メモリ bne a4,t2,8000066c
Slide 29
Slide 29 text
一般的なCPU(エミュレーター)の動き③実行 レジスタ CPU デコーダ 演算器 メモリ bne a4,t2,8000066c a4,t2
Slide 30
Slide 30 text
一般的なCPU(エミュレーター)の動き③実行 レジスタ CPU デコーダ 演算器 メモリ bne a4,t2,8000066c a4,t2 8000066c Program Counter
Slide 31
Slide 31 text
RISC-V(リスクファイブ) ● オープンソースの命令セットアーキテクチャ ● RISC(reduced instruction set computer) というように基本の命令セット数が少な い ● 現状PC の CPU としての事例はまだ少なく、マイコンや特定の用途が多い
Slide 32
Slide 32 text
RISC-V(リスクファイブ) ● オープンソースの命令セットアーキテクチャ ● RISC(reduced instruction set computer) というように基本の命令セット数が少な い ● 現状PC の CPU としての事例はまだ少なく、マイコンや特定の用途が多い
Slide 33
Slide 33 text
RISC-V(リスクファイブ) ● オープンソースの命令セットアーキテクチャ ● RISC(reduced instruction set computer) というように基本の命令セット数が少な い ● 現状PC の CPU としての事例はまだ少なく、マイコンや特定の用途が多い
Slide 34
Slide 34 text
今回作るもののスコープ
Slide 35
Slide 35 text
今回作るもののスコープ add 命令テストが pass する
Slide 36
Slide 36 text
今回作るもののスコープ add 命令テストが pass する
Slide 37
Slide 37 text
実装した命令 ADD ADDI LUI AUIPC 算術演算 SW ストア JAL ジャンプ &リンク SLLI シフト ORI 論理演算 ECALL 環境 CSRRS CSRRW CSRRWI CSR BEQ BNE BLT 分岐
Slide 38
Slide 38 text
実装方針 ● とりあえず基本のレジスタ、メモリ、デコーダあたりを作る ● テストを実行する ● 実行不可能な命令が来たら例外を吐く ○ 実装する ● テストが通る!
Slide 39
Slide 39 text
実装方針 ● とりあえず基本のレジスタ、メモリ、デコーダあたりを作る ● テストを実行する ● 実行不可能な命令が来たら例外を吐く ○ 実装する ● テストが通る!
Slide 40
Slide 40 text
実装 ● RISCV32CPU class を作成 ● load_program method でプログラムをメモリに読み込む ● execute method でプログラムを実行
Slide 41
Slide 41 text
実装 ● RISCV32CPU class を作成 ● load_program method でプログラムをメモリに読み込む ● execute method でプログラムを実行
Slide 42
Slide 42 text
実装
Slide 43
Slide 43 text
実装
Slide 44
Slide 44 text
実装
Slide 45
Slide 45 text
実装 これだけ!
Slide 46
Slide 46 text
実装
Slide 47
Slide 47 text
苦労したポイント①テスト用バイナリの作成 ● riscv-tests は自分でコンパイルする必要がある ○ Apple Silicon では結局うまくいかなかった ○ Docker on rosetta2 も撃沈 ○ 結局 Linux 機を引っ張り出してくるとすんなり実行できた
Slide 48
Slide 48 text
苦労したポイント①テスト用バイナリの作成 ● riscv-tests は自分でコンパイルする必要がある ○ Apple Silicon では結局うまくいかなかった ○ Docker on rosetta2 も撃沈 ○ 結局 Linux 機を引っ張り出してくるとすんなり実行できた
Slide 49
Slide 49 text
苦労したポイント②RubyのIntegerの扱い ● Rubyの Integer は多倍長整数 ● 一方で RISC-V で扱える数は 32bit が最大 ○ 符号拡張 ○ オーバーフロー
Slide 50
Slide 50 text
苦労したポイント②RubyのIntegerの扱い ● Rubyの Integer は多倍長整数 ● 一方で RISC-V で扱える数は 32bit が最大 ○ オーバーフロー ○ 符号拡張 0b100 -> 8
Slide 51
Slide 51 text
苦労したポイント②RubyのIntegerの扱い ● Rubyの Integer は多倍長整数 ● 一方で RISC-V で扱える数は 32bit が最大 ○ オーバーフロー ○ 符号拡張 0b100 -> 8 0b100 -> -4
Slide 52
Slide 52 text
苦労したポイント②RubyのIntegerの扱い ● Rubyの Integer は多倍長整数 ● 一方で RISC-V で扱える数は 32bit が最大 ○ オーバーフロー ○ 符号拡張 0b100 -> 8 0b100 -> -4 2147483648 + 32768 = 2147516416
Slide 53
Slide 53 text
苦労したポイント②RubyのIntegerの扱い ● Rubyの Integer は多倍長整数 ● 一方で RISC-V で扱える数は 32bit が最大 ○ オーバーフロー ○ 符号拡張 0b100 -> 8 0b100 -> -4 2147483648 + 32768 = 2147516416 2147483648 + 32768 = 32768
Slide 54
Slide 54 text
ということで無事実装完了 🎉
Slide 55
Slide 55 text
良かった点 ● 曲がりなりにもバイナリが読めるようになった ● 簡単にとりあえず動くCPUが作れた ● 慣れ親しんだ Ruby で実装できた
Slide 56
Slide 56 text
良くなかった点 ● Ruby の Integer は多倍長整数なので 32bit にわざわざ制限してやる必要がある ので面倒 ● HDL ほどハードウェアに寄ってないので実際どう配線するんだ?みたいなところは わからない
Slide 57
Slide 57 text
まとめ ● Ruby で riscv-tests の add 命令のテストが通る CPU エミュレーターを作った ● 簡単に CPU の仕組みがまなべるよ(足りないところはたくさんあるので許して ● みんなも好きな言語でやってみてね ● Next Step は bootloader が動くところまで作りたい
Slide 58
Slide 58 text
なんで Ruby で? 作って意味ある?🤔
Slide 59
Slide 59 text
なんで Ruby で? 作って意味ある?🤔
Slide 60
Slide 60 text
なんで Ruby で? 作って意味ある?🤔 俺にとってはある!
Slide 61
Slide 61 text
ご清聴ありがとうございました
Slide 62
Slide 62 text
出典 ● RISC-V原典 ● コンピュータの構成と設計 ● The RISC-V Instruction Set Manual