Ruby+DXOpalでリレー式論理回路シミュレータを自作して1bit CPUまで動かした


  • 「1bit CPU」というのは、書籍『CPUの創りかた』に載っている「オリジナルCPU 試作3号機(エレキ式)」のことです。
  • ※ ブログに書いていた記事を Qiita に引っ越してきました。元の公開日は 2020-05-03 です。

概要

リポジトリ:

デモ(ブラウザで動かせます):
https://sonota88.github.io/kairo-gokko/pages/39/index.html

  • 音量を小さめにしていますが、音が出ます
  • 表示サイズや負荷の関係でPCブラウザ推奨です
    • とりあえず富豪的に作っていて、まだ最適化などやってません
  • 最初は発振するので、スイッチを適当に操作して発振を止める必要があります。
    止め方についてはこちらを参照してください。

製作過程のメモ(どういうステップを踏んで何を実装していったか、具体的な話はこっちにまとめています):


動かしている様子です。

(Firefox だとアニメgifが再生されない場合があるようです。ファイルをクリックして画像だけ表示すると動くものが見れます。以下、画像の脇に <アニメgif> と添えます)

左下のスイッチがクロックで、右下のスイッチで命令( MOV A, ANOT A )を切り替えています。


回路図を描いて動かすまでの流れ:

  • 回路図を LibreOffice Draw で描いて .fodg 形式で保存
  • fodg ファイルを読んで前処理し、中間データ(JSON)に変換
  • シミュレータのプログラムと中間データを使ってブラウザで実行

LibreOffice Draw で描いた回路図はこんな感じ。

直線と矩形、矩形内のテキストだけです。部品はグリッドに合わせて配置します。ナナメの配線は禁止。


使っている部品:

  • 導線
  • 電池のプラス極・マイナス極
  • ランプ
  • スイッチ。マウスでクリックすると ON/OFF が切り替わります。
  • リレー(2種類)

ランプ、リレーには極性なし(プラス極・マイナス極を入れ替えても動作は変わらない)


小さい回路の例をいくつか:

NOT(を3つ繋げたもの)
<アニメgif>

NAND
<アニメgif>

XOR
<アニメgif>

RSフリップフロップ
<アニメgif>


ほぼ Ruby 製。ブラウザで動かす部分は DXOpal を使っています。

(一応残してあるが)不要になっている部分、補助ツール的なスクリプト、コメントなどを除くと主な部分は 2000行弱(2021-04-11 時点)。途中いろいろありましたができあがってみると意外と小さい。

$ wc -l *.rb
  283 child_circuit.rb
  456 circuit.rb
  114 drawer_dxopal.rb
  137 libo_draw.rb
  237 main.rb
   26 preprocess.rb
  307 unit.rb
  346 view.rb
 1906 合計

製作期間

2019-12-31 〜 2020-02-02
(プロトタイプを作り始めてから 1bit CPU が動くまで)

始める前からいろいろ調べたりはしていて、書き始めたのが 12/31 だったか 12/30 だったか。

回路図エディタの部分を LibreOffice Draw に丸投げすることにより、製作期間をかなり短縮してシミュレータ部分に集中することができました。

どのくらいの電気の知識で始めたか

  • 小学校、中学校の理科レベル
    • 電池、エナメル線、豆電球、電磁石、直列・並列つなぎ
  • 大学の頃にちょっとだけ電子工作やろうとするも鉱石ラジオ作った程度で終わった
  • 『CPUの創りかた』のうっすらした記憶
  • リレーは名前は聞いたことあったけどどういうものか知らなかった
  • トランジスタの前は真空管を使っていたらしい
  • GND って何?

……という程度。

コンセプト・方針

  • ガチャガチャ動く機械仕掛けのおもちゃ
  • ピタゴラ装置みたいなの
  • 電圧や抵抗は考慮しない
    • 難しそうなので
    • 電気が流れているか、流れていないかだけ考える
  • 小学校の理科の工作の延長程度のもの
  • なるべく寄り道せずに曳光弾を通す
    • 遅すぎて辛い、ということがなければ最適化は後回し
    • そもそも作れるのか、(論理)回路を動かすには最低限何が必要なのかがよく分かっていなかったので、まずそこをクリアにしたい。他の部分は枝葉。

なぜ作ったか / 作り始めるまでの経緯

並行してボンヤリと考えていたのですっきりまとめることができませんが、思い出して雑に書き出してみました。

列挙の順序も適当です。

そもそもは『CPUの創りかた』

  • 最初に読んだのは 4年くらい前
  • かなり基本的なところから手取り足取り説明されていてとっても良い本だが、
    単に読むだけだと後半で分からなくなる
  • さすがに何も知らない私みたいなド素人が
    さらっと読んだだけで理解できるほど甘くはない
  • (自分のような初心者は)作りながら読まないと分からないのでは
    • 回路図を読むところがネックになる
    • 回路図というものは抽象化された図なわけで、
      そこから具体的な回路や動作がどうなるかよく分からない
  • しかし作るのは面倒
    • 部品の調達
    • また部屋が散らかる……
    • 知識・経験がなさすぎてゴールが遠い
  • 物理CPU作るのは老後の楽しみにしよう……
  • とはいえ、先にしくみだけでも理解したい
  • しくみを理解するには、やはり自分で作って電子回路についての経験を積む必要があるんだろうな……
    • → 「しかし作るのは面倒」に戻る
    • ブートストラップ問題
  • しくみを理解するだけなら、枝葉の部分を捨ててもっと簡素化してハードルを下げられないか

こういうのって、実際に手を動かして作って壊して、回路図とにらめっこしたり計算をやりなおして試行錯誤を繰り返すうちにだんだん勘が養われていくものだと思いますが、そういう経験がない状態なのでなかなか大変です。

論理回路シミュレータ

  • そもそも論理回路シミュレータというものをよく知らなかった
  • シミュレータで CPU(TD4など)を作っている人たちがいると知る
  • 物理CPU作る前にこれで試すのは良さそう
    • 手間・時間をかけずに好きなだけスクラップ&ビルドできる
    • 部屋も散らからない

nand2tetlis

  • 通称(?) nand2tetlis
  • 物理的な電子回路でなぜ論理回路が動くのか、という部分がよく分からないまま
    HDL に進んでしまうのがちょっと不満
  • そこの部分のブラックボックス感を解消したいのに

そもそも論理回路が動くしくみがよく分かってない

  • 入力側から電流が流れてきて、それが出力側に伝わるというのは分かる
  • NOTゲートってどうなってるの。謎。
    • 入力が L で出力が H になる場合、その H の電力はどこから来てるの
    • 省略されると分からない
  • フリップフロップ
    • タイミングが絡んでくるし、入力がループするので、
      脳内でエミュレートできない
    • (自分で作って)動かしてみないとどうも実感が湧かない
  • 論理回路図というものは抽象化された図なわけで、
    どうすればそれを物理的な回路で実現できるかが分からない

今だからこうやって言語化できていますが、もっとボンヤリとモヤモヤしてました。「なんとなく……分かった気がする……たぶん……とりあえずそういうものだと飲み込んで先に進んでもいいが……(モヤモヤ)」みたいな。

リレー

  • トランジスタについてもよく分かっていなかったので、
    トランジスタ → 真空管 → リレー と遡って調べたりしていた
  • リレーについて知ることで
    「要するに何をやっているのか」「何のための部品なのか」が分かった
  • 要するに「電気を使ってスイッチを切り替える装置」
    • 英語版 Wikipedia の説明が簡潔で良いです。 "A relay is an electrically operated switch."
    • 「それを早く教えてよ!」という気分に
  • リレー、めっちゃ良い。分かりやすい。小学生でも理解できる。電磁石まで知ってればあともう一歩。そのくせインパクトがでかい。
    • 「小学校の理科でついでにリレーまで教えてくれてればよかったのに!」
      という気分に 1
    • 「小学校の理科の知識に、あとはリレーだけ付け加えれば CPU まで作れる」
      というのは、なんかいい。よくないですか?
  • トランジスタについても、「N型 と P型があって正孔が……」という
    半導体自体の説明よりも、
    先に役割や目的について着目した方が(自分には)分かりやすかったと思います

たしか、ここがクリアされたことで「あ、これなら自分でも作れるかも?」みたいな気分になった気がします。

Minecraft や Oxygen Not Included の論理回路

水流モデル(失敗)

  • 電気について詳しくないので水流モデルの方が分かりやすいかな、と思って
    セルオートマトンで作ろうとした
  • 逆に複雑で難しかったので中止

どうやって作るか

  • ググっても「論理回路シミュレータの作りかた」なんて解説は出てこない
  • OSS なシミュレータのソースを読む手もあるが……
    • Logisim とか 2
    • そんなに本格的なものでなくてよい
    • おもちゃみたいなのでよい
    • 実用目的ではない。いわゆる「教育目的」なもの。
      枝葉を排して理解しやすさを優先したもの。
    • 自分が作りたかったのは普通の論理回路シミュレータではなく、
      電池と導線と……で論理回路が動かせる、抽象化されていないシミュレータ
  • 結局手探りで
  • 詳しくは
    製作過程のメモ
    の方に書きました

感想

TODO

気が向いたらやりたい

  • 最適化・リファクタリング
    • 現状ではだいぶ富豪的なので
  • タイミングチャート付ける
  • 1bit CPU から先
    • これ以上規模が大きくなると大変そうだし、
      論理回路と物理回路の接続の理解についてはだいぶ気が済んだので、
      続きを作るとしたら既存の論理回路シミュレータを使えばよさそう
  • オブザーバーパターンや Actor モデルを使って書くとよさそう?

関連

今のところ直接関連するというわけではないですが、もっと上のレイヤーの話ということで。1bit CPU と下記の VM の間のギャップも埋めていければなあと考えてはいます。

作った後に読んだもの

他に Ruby 関連で書いたもの

  1. 指導要領の都合とかでいろいろあるんだと思います

  2. 有名っぽいので Logisim を例に出しましたが、Logisim は開発が終わっているようなので他のものを探すのが良さそうです