communicating-between-toy-cpus

自作 CPU 同士で通信してみた

「第 4 回 自作 CPU を語る会」で数台の自作 CPU をネットワークで接続し、メッセージをやり取りする試みをしました。本記事では通信実験の結果報告と、私の CPU での処理で改良すべきところの考察を述べます。

なお、本記事では「自作 CPU」を、私の周辺で一般的な用法である「自作 CPU を核としたコンピュータ」の意味で使っています。普通「CPU」と言うと、メモリや周辺機能を含みませんが、本記事における「自作 CPU」はそれらも含みます。

MSMP

MSMP は Make-cpu Simple Messaging Protocol の略で、自作 CPU 向けのメッセージ交換プロトコルです。「make-cpu」は「自作CPUを語る会」を意味します。

自作 CPU は処理性能が低いものが多いため、MSMP は最低限のヘッダのみ持ち、また通信速度は遅く設定されています。詳しい仕様は 自作CPU向けメッセージングプロトコル にまとめています。

通信実験のセットアップ

通信実験に参加した自作 CPU は MNP004(さん)、NLP-16A(ちぇりーたくあんさん)、RISC-V CPU(Kenta IDA さん)、そして筆者の ComProc PC です。Kenta IDA さんの愛機は現地調整が発生し、最後の方に少しだけ通信できました。

MSMP通信実験の構成図@第4回自作CPUを語る会

上図の通り ComProc PC→MNP004→NLP-16A→ComProc PC の順で接続しました。MSMP は受信端子を左隣のノードと、送信端子を右隣のノードと繋ぐことで、全体をリングで繋ぐ接続方式です。そのため、離れているノードへメッセージを送るには他のノードを経由する必要があります。

MSMPインターフェース基板を介してComProc MUCにMSMP通信ケーブルが接続されている

ComProc PC の接続を拡大したのが上図です。ComProc MCU(右上の黒い基板)に対し、MSMP インターフェース基板を介して 2 本の通信ケーブルが刺さっています。これらが MNP004 と NLP-16A に対して配線されています。

世界初の MSMP による通信

MSMP を使った世界初の自作 CPU 同士の通信は、ComProc PC から MNP004 への通信でした。MNP004 は MSMP 用 API として「H」という 1 文字を受け取ると電球を光らせるという機能を持っていて、それを叩いてみるというのが最初の実験でした。岩さんからそのとき撮影した電球の写真を提供いただきましたので、ここに紹介します。

ComProcからMNP004へHを送る前は電球が消灯している

まだ何も通信していないとき、電球は消灯しています。ちなみに、電球の手前にある装置は MNP004 とは関係ない作品(レトロな表示が特徴の電卓)です。たまたま電球の近くに置いてあっただけです。MNP004 は写真に写っておらず、もっと右の方に置かれています。

ComProcからMNP004へHを送ると電球が点灯した

ComProc PC から MNP004 へ「H」を送ると電球が点灯しました。なんと、最初の送信チャレンジですんなりと点灯したのはとても驚きました。各自が MSMP 規格に沿うよう、しっかり開発して準備を整えてきた証ですね。

なお、「H」以外の文字を受け取ると消灯する機能もあって、そちらもちゃんと動きました。すばらしい!

ノードをまたぐ通信

次に ComProc PC と NLP-16A の通信を試しました。この通信では、ComProc PC から NLP-16A への通信が MNP004 を経由するため、先ほどの ComProc PC から MNP004 への通信より格段に複雑な構成となります。

ComProcからNLP16Aへメッセージ送信成功

それでも、ComProc PC から送った「ComProc!」というメッセージがちゃんと NLP-16A へ届きました。ComProc PC が正しい信号を出し、MNP004 が自分宛てではないメッセージを正しく転送し、NLP-16A が正しく受信したということです。

驚くべきことに、MNP004 は「4 ビット CPU」です。レジスタ幅が 4 ビットで、一度に転送できるデータは 4 ビットです。一方で MSMP はバイト単位の転送を前提にした通信方式です。MNP004 は 1 バイトを 2 回に分けて読み書きするという努力をして、MSMP 通信を実現しているのだそうです。MSMP の仕様を決めたとき、まさか 8 ビット未満のデータ幅を持つ CPU が参戦してくるなんて思いませんでした。しかし、実際に会場で最も安定してメッセージを裁いていたのはまぎれもない MNP004 だったのです!

さて、NLP-16A から ComProc PC へのメッセージ送信についても紹介しておきます。NLP-16A から ComProc PC へメッセージ「hello!」を送信したときの写真を示します。LCD での表示で 2→5[ワタシ アテ] L=06 の意味は、2→5 がノード 2 からノード 5 への通信であることを表し、ワタシ アテ がノード 5 は自分のアドレスなので「私宛て」であることを表し、L=06 はメッセージ本文が 6 バイトであることを表します。

NLP16AからComProcへメッセージ送信成功

こちらは間にノードを挟まない直接通信ですので、それほど難しい話ではありません。しかし ComProc PC 上の MSMP 制御プログラムにバグがあるのか、何度か通信すると不安定になりリセットが必要になるという状態でした。リセットせずずっと転送し続けている MNP004 の安定度が際立ちました。

NLP-16A の RPN 計算 API

NLP-16A は RPN(逆ポーランド記法)で計算を行う MSMP API を公開しています。MSMP メッセージとして計算式を送りつけると、返事として計算結果を得られます。試しに「2 3 *」を計算する様子を動画に撮りましたので、ご覧ください。MSMPで自作CPU間通信:RPN計算APIを呼び出す - YouTube

NLP-16A の作者ちぇりーさん自身が ComProc PC を操作し、自身の愛機に計算式を送っています。エンターキーを押して少しすると、NLP-16A から計算結果 6 が送られてくるのが見えますね。

ComProc PC のメッセージ転送

NLP-16A から MNP004 の持つ電球制御 API を使う実験を行いました。MNP004 に対し「L」を送り消灯させる様子を撮りましたのでご覧ください。MSMPで自作CPU間通信:電球制御APIを呼び出す - YouTube

NLP-16A から MNP004 への通信は、途中に ComProc PC が挟まっています。すなわち、ComProc PC が正しくメッセージを転送できる必要があります。上記動画の後半で、ComProc PC のディスプレイに「テンソウ」と表示され、さらにメッセージ本文が「L」であったことが表示されていて、確かに消灯メッセージが転送されたことが分かります。これは期待通りの動作です。

MSMP 実験を通して分かったこと

世界で初めて自作 CPU 同士を MSMP によりつなぎ、通信してみたわけですが、何点か改善すべき点が見つかりました。ここで簡単に紹介します。

メッセージ先頭にタイミング同期信号を入れたい

ComProc PC の MSMP 制御プログラムは、1 メッセージを完全に受信したら画面に表示するという処理にしていました。正しいバイト列だけが送られてくる世界では良く機能するのですが、現実は違いました。他 CPU から不意にゴミデータが受信されるなどして、メッセージ受信処理が誤動作してしまうことが多々ありました。ゴミデータに続いて正規のメッセージが来ても、もはやタイミングを逃してしまった受信処理から復帰ができず、リセットするしかない状態になりました。

ゴミデータを受信してしまっても、その次から正しくメッセージを受信するために、メッセージの先頭に 0x00 という 1 バイトを送ることにすると良いと思いました。MSMP において 0 というバイトは特別な意味があります。これはメッセージ本文中に現れてはならず、もし 0 を受信したら強制的にメッセージ受信を中止せよ、ということになっています。この仕様を活用し、必ず 0 を送ることで強制的に状態を初期化し、その次のバイトから正しくメッセージを受信できるように工夫すると、ゴミデータやノイズに強くなると思います。

途中状態を観察できるようにすべし

上記に関連するのですが、1 メッセージを完全に受信し終わる前でも今の受信状態がどうなっているかが分かると、現地での運用に役立つと思いました。例えば、宛先を表す 1 バイト目を受信したのかどうか(受信したならそのアドレス)、メッセージ長を表す 2 バイト目を受信したのかどうか(受信したならその値)、未受信のデータが後何バイトあるかどうか、など。

ComProc PC は表示領域が 4 行しかなく、全部ちゃんと表示するのは厳しいかもしれませんが、簡易でも良いのでなんとか表示したいところです。

タイムアウト処理

0 バイトを先頭に置く工夫に加え、受信タイムアウトもあると良さそうだという話が出ました。例えば、最後のバイトを受信してから 1 秒以上経過したらタイムアウトとみなすとか。1 バイト受信するたびにタイマをリセットし、そのタイマが 1 秒になったら状態をリセットするということです。このような目的のタイマを「WDT」(ウォッチドッグタイマ)と呼びます。

模擬信号生成器が欲しい

自分の CPU へ MSMP を実装しようとすると、MSMP の信号を作り出す相手が欲しくなります。私は USB-UART 変換基板を使い、パソコンから指示を出して UART 信号を作り出していました。しかし、これでは不十分だったのです。この方法ではなかなか「送信中にも受信データが来る」状況や、ノイズでスタートビットのような波形が一瞬出てしまう状況などを再現できません。

そこで、いろいろな状況を想定した「汚い信号」も出せる、デバッグ用の MSMP 信号生成器が欲しいなと思いました。この信号生成器が出す信号に全部対応できるようになったら、展示会本番でもほぼ問題無く通信し続けることができるというようなレベルになったら良いなと思いました。

MSMP の輪へのお誘い

MSMP を用いた通信は本当に楽しかったです。今までの展示会では自分の CPU をスタンドアローンで展示するだけだったのが、アーキテクチャや実装が異なる異種 CPU 同士でメッセージを送り合えるという世界観は本当に感動しました。

MSMP による通信実験は今後の自作 CPU を語る会で継続してやっていく予定です。是非、皆さんの CPU にも MSMP 通信機能を追加し、次回以降のイベントで通信の輪に入っていただければと思っています!



この記事を参照しているブログ内記事はありません。

作成:2024-12-02 17:48:18

最終更新:2024-12-06 13:23:28