Rubyで作る論理回路シミュレータの設計の話 - Kashiwa.rb #12
by
Koji NAKAMURA
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で作る論理回路シミュレータ CPUを理解したくてDSLを創った話 の設計の話 2025.6.19 Kashiwa.rb #12 Koji NAKAMURA (@kozy4324)
Slide 2
Slide 2 text
Koji NAKAMURA ● 𝕏: @kozy4324 ● GitHub:@kozy4324 ● Classi株式会社所属 ● Kashiwa.rb主催 自己紹介
Slide 3
Slide 3 text
デモ
Slide 4
Slide 4 text
No content
Slide 5
Slide 5 text
作ったもの: logicuit ● logi(c cir)cuit -> logicuit ● 電気回路シミュレータ ● 書籍「CPUの創りかた」を理解したくて作った ● https://www.amazon.co.jp/dp/4839909865/
Slide 6
Slide 6 text
この発表でお話しすること ● 「論理回路のモデリング」と「内部DSLの設計」をどういった道 筋でやったのかという話 ● 作ったものは小さいのだけれどそれなりに試行錯誤したという 話
Slide 7
Slide 7 text
この発表の楽しみ方 ● 「自分ならこうモデリングするだろう」「こう設計するだろう」とい うのを考えながら聞いてもらえるといいかもしれない ○ モデリングや設計は唯一解があるものでもないと考えてい ます(要件や制約にもよるものではあるけど) ○ 「自分ならこうする」というフィードバックがもらえるとむしろ 嬉しい
Slide 8
Slide 8 text
作り始め初期フェーズ
Slide 9
Slide 9 text
前提状態 ● 書籍を1周ちょうど読み終えてRubyでコード書いてみるかと思 い立ったタイミング ● 対象(コードで表現しようとしているもの)のイメージがぼんやり とあるだけ
Slide 10
Slide 10 text
最初に設計指針は決めた ● 最優先事項は CPUの仕組みを理解すること ○ 自分の認知に寄り添う形で論理回路を論理回路らしく設計 すること とも表現できる ● 逆に優先しないこと ○ CPUや論理回路の理解に寄与しない設計の追求 ○ 処理速度や効率的な処理実行の最適化
Slide 11
Slide 11 text
まず 論理回路らしいとは? の解像度を上げる A B Y AND A Y NOT and more…
Slide 12
Slide 12 text
ゴールはこれ
Slide 13
Slide 13 text
基本論理ゲートの一つを眺めてみる A B Y AND A B Y AND Bをon Bをoff ● どこに電流が流れているかを 状態 として表現する? ● 出力Yは入力A,Bの射影とも言えそう → 関数型の機運?
Slide 14
Slide 14 text
電流は「流れる」もの ● 左の入力Bをonにすると右の出力Yに伝播されてほしい ● コレってストリーム?リアクティブプログラミング?? A B AND Y AND
Slide 15
Slide 15 text
こーゆーのもある: Dフリップフロップとクロック ● 入力 D の値をクロック立ち上がり時に Q 出 力に保持する ● 1ビットの状態を記憶可能 ● つまり CPU の「レジスタ」になるやつ ● \(状態)/ CK
Slide 16
Slide 16 text
さて、どうしよう? (ここでシンキングタイム)
Slide 17
Slide 17 text
私の選択「まずは素朴でええやろ」 ● 悩んだら素朴な方法を選択する ● 困るまで素朴な方法で頑張る
Slide 18
Slide 18 text
素朴なモデリング(1) ● Ruby なので OOP を選択 ● Signal クラス ○ 電流が流れる単位の信号 ○ #current: true | false ○ #on / #off ● Gates::And クラス ○ has many Signal(s) A B Y AND
Slide 19
Slide 19 text
素朴なモデリング(1) ● 入力A/Bの状態(#current)が変化 するたびに出力Yを評価する (#evaluate) A B Y AND #evaluate
Slide 20
Slide 20 text
擬似コード(1)
Slide 21
Slide 21 text
素朴なモデリング(2) ● AND(1)の出力YとAND(2)の入力Bは接続している ● Yの@downstreamにBが入っている ● Yの値が変わったらBに値を伝播するだけ A B AND(1) Y AND(2) A Y B
Slide 22
Slide 22 text
擬似コード(2)
Slide 23
Slide 23 text
擬似コード(2)
Slide 24
Slide 24 text
素朴なモデリング(3) ● フリップフロップはクロック立ち上がり時に入 力Dで出力Qを評価する ● Clock クラス ○ #connects_to(component) ○ #tick ■ #connects_toで接続したもの全てを 再評価する CK
Slide 25
Slide 25 text
擬似コード(3)
Slide 26
Slide 26 text
擬似コード(3)
Slide 27
Slide 27 text
擬似コード(3)
Slide 28
Slide 28 text
クロックはシングルトンにした ● 同じタイミングで信号が送られる ○ =同じタイミングで処理したい ● 1回路に1クロックあれば良さそう ○ 少なくとも書籍が説明する範囲の 回路においては CK D Q CK D Q
Slide 29
Slide 29 text
ここまでで作ったクラス群 Signal #connects_to(other) #on #off Clock #connects_to(comp) #tick And Or Not and more…
Slide 30
Slide 30 text
DSL設計フェーズ
Slide 31
Slide 31 text
ANDゲートの実装
Slide 32
Slide 32 text
ORゲートとの実装差分
Slide 33
Slide 33 text
部品と部品を繋げて組み合わせる実装
Slide 34
Slide 34 text
部品と部品を繋げて組み合わせる実装
Slide 35
Slide 35 text
DSLを創るモチベーション ● 各部品をもっとシンプルに宣言的に定義したい ● 部品と部品を組み合わせてより複雑な部品を作り上げること を実現したい ○ その際のコード記述による認知負荷は極力下げたい ● 直感的に理解できるコード記述であって欲しい ○ 少なくとも自分にとっては
Slide 36
Slide 36 text
さて、どうしよう? (2回目のシンキングタイム)
Slide 37
Slide 37 text
部品を定義するDSL: ANDゲート
Slide 38
Slide 38 text
部品を定義するDSL: ORゲート
Slide 39
Slide 39 text
部品を定義するDSL: Dフリップフロップ
Slide 40
Slide 40 text
部品を定義するDSL: Dフリップフロップ inputsに clock: :ck を含めるとSequential な 部品となり、クロック信号を受け取るごとに outputsを評価するようになる
Slide 41
Slide 41 text
部品を組み立てるDSL: 半加算器
Slide 42
Slide 42 text
部品を組み立てるDSL: 半加算器 connects_to の alias で >> メソッドを導入 この部品とこの部品を繋げているよ〜を記号的に表現している
Slide 43
Slide 43 text
これを組み立てる
Slide 44
Slide 44 text
CPU実装の一部分: 読み解くには少しツラい...
Slide 45
Slide 45 text
1Signal=1bit、4bit でまとめて部品を繋げたい イミディエイトデータ 0000 入力ポート 出力ポート データセレクタ Aレジスタ Bレジスタ 出力ポート プログラムカウンタ SELECT A SELECT B A B C3 C2 C1 C0 ALU LD0 LD1 LD2 LD3 書籍にある図を引用 概念的にも4bitでまとめて扱いたい
Slide 46
Slide 46 text
最終形: 多対多の接続を可能にした
Slide 47
Slide 47 text
No content
Slide 48
Slide 48 text
まとめ
Slide 49
Slide 49 text
まとめ(1) ● モデリングと実装において困るまでは素朴な方法で進もうとい う選択をしたが、大きな困りごとに遭遇することなくゴールまで 作り切ることができた ○ 実は途中でシグナルの伝播で頭を悩ませる問題もあった が、うまい解決策を見つけられて事なきを得ている ● 素朴なモデリング・素朴な実装でも割とうまくいくものですよ ねっていうのが今回伝えたかった事の一つ
Slide 50
Slide 50 text
まとめ(2) ● (自分の中では)なかなか論理回路を論理回路らしく表現する 実装が実現できたと思っている ● Rubyで内部DSLを設計・実装して何かしらの問題領域に取り 組むのって楽しいですね! ○ Ruby力が試されている気がする ○ これがもう一つの伝えたかったこと
Slide 51
Slide 51 text
リポジトリ URL https://github.com/kozy4324/logicuit
Slide 52
Slide 52 text
EOF