RDAバグ(RegisterDeleteとAccumulatorを採用したCPUに起きるバグ)
前置き
RDAバグとは、レジスタデリートとアキュムレータを採用した僕の赤石CPUに起きるバグです。
仮で実行された命令のデータにアクセス出来てしまう問題です。
今回は、RDAバグを解説したいと思います。
RDAバグの名前の由来
RDAバグは、レジスタデリートとアキュムレータの両方を採用した赤石CPUに発生するバグです。
なので、RegisterDeleteとAccumulatorの一部を取って、RDAバグとしています。
レジスタデリートとアキュムレータ
レジスタデリート
レジスタデリートとは、条件分岐の際に仮で命令を読み出して実行し、もしフラグがオフだったらそのまま実行し、フラグがオンだったらレジスタに保存しないようにして、なかったことにする僕の独自技術です。
投機的実行な考え方で、性能が向上する場面もあれば、あまり効果がない場面もあります。
アキュムレータ
僕が使用しているアキュムレータは、本物のCPUのアキュムレータと若干違います。
ALUから出力された演算結果を、出来る限り早くALUの入力部分に送るための記憶装置で、この記憶装置のおかげで、シングルスレッド性能が向上します。
RDAバグの原理
図を使って解説
RDAバグは、レジスタデリートとアキュムレータが組み合わさることで発生します。
では、この二つが搭載されたCPUの内部では、何が起こっているのか、解説していきたいと思います。
今回は、NX RED VIII(ver.1)の内部構造の図を使って解説したいと思います。
※NX RED VIII(ver.1)はRDAバグ対策予定です。
RDAバグが発生するプログラムは、仮で読み出した最後の命令の保存先と、ジャンプ先の命令の読み出し先が一致した時です。
アキュムレータの制御回路からは、この二つは連続して送られてきているため、アキュムレータを動作するべきだと判断してしまいます。
どういうことかというと、まず、仮で実行した命令の演算結果が赤の1だとします。
その次に、レジスタとアキュムレータにこの1という情報が送られます。
そして、フラグが判明します。
フラグがオンだったとしたら、それをレジスタに伝えることで、レジスタに1が保存されないようにします。
そうすると、アキュムレータに1という情報が残ります。
そして、フラグがオンだと分かっているので、この次の命令は、必要な実際にジャンプした命令になってきます。
ですが、その命令がアキュムレータにアクセスするような命令だった場合、アキュムレータの中にあるのは、仮で実行された1という演算結果です。
そして、その演算結果が出力され、使われてしまうという感じです。
文章で解説
今度は、文章で解説したいと思います。
まず、レジスタデリートで仮の命令が実行されます。
そして、仮で読み出され、実行された命令の最後が、「2番地に保存」だったとしましょう。
次に、仮ではなく、実際に実行する命令が読み出され、実行されます。
この実行された命令の最初の命令が、2番地にアクセスしたとします。
そうすると、アキュムレータの制御からはどう見えるでしょうか?
2番地に保存した直後に2番地の情報が欲しいという命令が来ました。
アキュムレータを動かす出番だ!と、勘違いをしちゃうわけですね。
その結果、仮で実行され、保存された2番地の情報が、実際に実行する命令で使用されてしまい、壊れてしまうといった感じです。
対策
もちろん、対策法は見つかっています。
それは、フラグがオンだった時に一時的にアキュムレータの動作を制御すればいいのです!
アキュムレータの制御回路に、フラグがオンだったという情報を伝え、強制的にアキュムレータの機能を停止させ、レジスタから情報を読み出すようにすれば、このバグは解決できます。
ですが、そのためには、フラグの信号をいい感じのタイミングでアキュムレータの制御回路に伝える必要があるので、それが少し面倒で、忘れちゃいそうですが、一本の配線で不具合を防げるなら、やる価値は十分あると思います。
最後に
今回は、僕のCPUの重大なバグの一つであるRDAバグについて解説しました。
配線のミスなどで不具合が起きることはよくありますが、構造的な欠陥で発生するバグは多分初めて、、?なので、名前を付けてRDAバグとしました。
今後、このバグが起こらないように、気を付けていきたいと思います。
ちなみに、レジスタデリート と アキュムレータ の二つを採用しているCRED X(バージョン4)で実際に
0:2番地と0番地を足して3番地に保存
1:0にジャンプ
2:0番地と0番地を足してインクリして2番地に保存
3:0番地と0番地を足してインクリして2番地に保存
4:0番地と0番地を足してインクリして2番地に保存
5:0番地と0番地を足してインクリして2番地に保存
6:0番地と0番地を足してインクリして2番地に保存
7:0番地と0番地を足してインクリして2番地に保存
というプログラムを実行したところ、3番地に0000 0001が保存されました。
これは、本来なら全てのレジスタが0000 0000のままのはずなので、おかしいです。
しかも、仮で読み出された命令の保存先と実際に実行された命令の読み出し先が一致した時のみデータにアクセスされるので、どこに保存される予定だったのかもバレバレという現実のCPUだったらかなり恐ろしいバグです()
ですが、おそらくこのバグを実際に抱えているのは、CRED X(バージョン4)だけのはずなので、そこはまだよかったです。(もしもっとたくさんの赤石CPUに起きていたら、、、)
それでは、最後まで読んでいただき、ありがとうございました!
この記事が気に入ったらサポートをしてみませんか?