kairo-gokko (36) 落ち穂拾いというか



1bit CPU まで作るという話に関していえば前回で一区切りなんですが、書いておかないといけないことがあるので、それを書いて今回でいったん最終回とします。


まず、回路を少し整理します。

通電 1 の回で「プラス極とマイナス極は離して置いても同じ回路」という話をしました。 このときは説明のための簡略化として離して描いたものの、 その後の回路は離さないスタイルで描いてきました。

これは意図的なもので、 「小学校の理科の工作の延長みたいな感じで CPU まで作れるのでは」 みたいなことを考えていたため、 ちゃんと輪っかになった子回路を使って、 いわば地面に足をベタッと付けたままここまでやってきたわけです。

しかし、論理回路の作成にも多少慣れてきたことですし、 ここらへんでその縛りを外して、 足がふわっと地面から浮いた感じにするとどうなるか試してみるのも悪くないでしょう。

あとは、回路が大きくなって複雑になってきたのですっきりさせたいとか、 省スペースにできないかとか、そういう考えもなくはないです。


前回の回路(オリジナルCPU試作3号機(エレキ式))を使って実際にやってみましょう。

たとえばここ。 まずはこの一番横に長い子回路でやってみます。

f:id:sonota88:20200419120011p:plain

マイナス極をプラス極から少し離して、 次のようにしても同じ回路になります(動作は同じままです)。

f:id:sonota88:20200418110659p:plain

これをもっともっと離していくとどこまで行くかというと、次の図のようになります。

f:id:sonota88:20200418111020p:plain

上の部分の、線が2本並んでいた部分が 1本になりました。 もちろんここまでやっても回路の動作は変わりません。 ふーむ、なるほど、これでいいのか……。


例をもう 1つということで、今度は下側の門番の子回路に着目してみます。

f:id:sonota88:20200419095542p:plain

さっきと同じように素直に(他の部品にぶつかる手前まで)マイナス極を動かしていくと、次のようになるでしょう。

f:id:sonota88:20200419095732p:plain

しかし、この場合、右の部分は次のように描くこともできます。

f:id:sonota88:20200419100009p:plain

要するに動作が変わらなければいいわけですから、これでも同じです*1

この作業、なんかパズルみたいで楽しい。


そんな感じで整理していくと、こうなって、

f:id:sonota88:20200418145945p:plain

もっといじるとこうなります。

f:id:sonota88:20200419101430p:plain

すっきりしてきましたね。 スカスカになったところを詰めると、回路全体のサイズも小さくできるでしょう。

f:id:sonota88:20200419101255g:plain

2本だったところが1本になると、1本の線で情報が伝達されてるっぽい感じになって、より論理回路っぽさが漂ってくる気がします。

※ もっとできるのですが、あんまりやりすぎると各部分の役割が分かりにくくなってしまうので、ここらへんで留めています。


めでたしめでたし…… と言いたいところですが、話はまだ続きます。 実はここからが本題です。

よく見ると、すべての子回路が

  • エッジが1本
  • 並列つなぎの OR

のどちらかになっていることに気づき……あっ

……

えっ……

てことは……

ダイクストラ法要らなくない????

……

はい、そうです。不要でした。 少なくとも、「オリジナルCPU試作3号機」を動かす分には不要です。 経路探索けっこうがんばったのに……。

通電判定の部分は下記のようになっていましたが、else の部分の分岐の処理は消すことができますね。

# child_circuit.rb

case @edges.size
when 1
  # エッジ1本のときの処理
when 4
  # エッジ4本のときの処理(並列つなぎの配線のみ対応)
else
  # それ以外の場合はダイクストラ法を使った通電判定
end

勘が良ければもっと前の段階で気付けたと思うんですが、 私は余裕がなくてそこまで気が回らなくて、 上記のように回路を整理していてやっと気が付きました……。


そして、もう一つのことに気づきます。

そういえば、 OR って NAND で作れるんじゃなかったっけ?

f:id:sonota88:20200418161301g:plain

つ、作れますね……。

f:id:sonota88:20200419104522g:plain

つまり、エッジ4本のときの分岐も不要で、

エッジ1本の通電判定さえできればよかった

のでした。なんですとー!

(とはいえ、並列つなぎの OR は見た目に分かりやすく、 プログラムもそこまで複雑ではないので残しておいてもいいかなと思います。)

まあしかし、こういう経緯を経て「結局要らなかった」という結論が導き出されるのは、なんといいますか、清々しいですね。 ターゲットを論理回路に絞れば、意外とコンパクトなプログラムでシミュレータが作れるみたいです。

脇道にそれて下手な最適化とかやらずに、曳光弾を通すことに注力してよかった、と言えるかもしれません。


というわけで、ダイクストラ法が不要だったというオチが付きました。 これにていったん終了です。 めでたしめでたし!

(新型コロナで倒れる前にここまで書けてよかった……)


以下のリンク先で実際に動かせます。

https://sonota88.github.io/kairo-gokko/pages/36/index.html

※ 音量小さめにしていますが音が出ます。
スマホでは全体が表示できないかもしれません。PCブラウザなどで見てください。



*1:リレーやランプなどの部品に極性があると動作が変わってしまいますが、 このシミュレータでは無視しているので、 プラス極とマイナス極を逆にしても動作は変わりません。